mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
sw_engine: replace RLE memory with common array
This commit has two purposes: - refactoring to introduce y indexing method for the upcoming partial rendering. - replaces the RLE-specific memory allocation with a shared array structure, eliminating potential memory overflows during RLE clipping.
This commit is contained in:
parent
d0be8cd2bd
commit
995f756c26
8 changed files with 160 additions and 210 deletions
|
@ -102,6 +102,17 @@ struct Array
|
||||||
count = rhs.count;
|
count = rhs.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void move(Array& to)
|
||||||
|
{
|
||||||
|
to.reset();
|
||||||
|
to.data = data;
|
||||||
|
to.count = count;
|
||||||
|
to.reserved = reserved;
|
||||||
|
|
||||||
|
data = nullptr;
|
||||||
|
count = reserved = 0;
|
||||||
|
}
|
||||||
|
|
||||||
const T* begin() const
|
const T* begin() const
|
||||||
{
|
{
|
||||||
return data;
|
return data;
|
||||||
|
@ -137,6 +148,12 @@ struct Array
|
||||||
return data[count - 1];
|
return data[count - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T& next()
|
||||||
|
{
|
||||||
|
if (full()) grow(count + 1);
|
||||||
|
return data[count++];
|
||||||
|
}
|
||||||
|
|
||||||
T& first()
|
T& first()
|
||||||
{
|
{
|
||||||
return data[0];
|
return data[0];
|
||||||
|
@ -164,6 +181,12 @@ struct Array
|
||||||
return count == 0;
|
return count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool full()
|
||||||
|
{
|
||||||
|
return count == reserved;
|
||||||
|
}
|
||||||
|
|
||||||
template<class COMPARE> void sort()
|
template<class COMPARE> void sort()
|
||||||
{
|
{
|
||||||
qsort<COMPARE>(data, 0, (int32_t)(count - 1));
|
qsort<COMPARE>(data, 0, (int32_t)(count - 1));
|
||||||
|
|
|
@ -121,9 +121,10 @@ struct SwSpan
|
||||||
|
|
||||||
struct SwRle
|
struct SwRle
|
||||||
{
|
{
|
||||||
SwSpan *spans;
|
Array<SwSpan> spans;
|
||||||
uint32_t alloc;
|
|
||||||
uint32_t size;
|
uint32_t size() const { return spans.count; }
|
||||||
|
SwSpan* data() const { return spans.data; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SwFill
|
struct SwFill
|
||||||
|
|
|
@ -474,12 +474,12 @@ static bool _rasterRect(SwSurface* surface, const RenderRegion& bbox, const Rend
|
||||||
|
|
||||||
static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRle* rle, SwMask maskOp, uint8_t a)
|
static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRle* rle, SwMask maskOp, uint8_t a)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
auto cbuffer = surface->compositor->image.buf8;
|
auto cbuffer = surface->compositor->image.buf8;
|
||||||
auto cstride = surface->compositor->image.stride;
|
auto cstride = surface->compositor->image.stride;
|
||||||
uint8_t src;
|
uint8_t src;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto cmp = &cbuffer[span->y * cstride + span->x];
|
auto cmp = &cbuffer[span->y * cstride + span->x];
|
||||||
if (span->coverage == 255) src = a;
|
if (span->coverage == 255) src = a;
|
||||||
else src = MULTIPLY(a, span->coverage);
|
else src = MULTIPLY(a, span->coverage);
|
||||||
|
@ -494,12 +494,12 @@ static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRle* rle, SwMask mas
|
||||||
|
|
||||||
static bool _rasterDirectMaskedRle(SwSurface* surface, SwRle* rle, SwMask maskOp, uint8_t a)
|
static bool _rasterDirectMaskedRle(SwSurface* surface, SwRle* rle, SwMask maskOp, uint8_t a)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
auto cbuffer = surface->compositor->image.buf8;
|
auto cbuffer = surface->compositor->image.buf8;
|
||||||
auto cstride = surface->compositor->image.stride;
|
auto cstride = surface->compositor->image.stride;
|
||||||
uint8_t src;
|
uint8_t src;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto cmp = &cbuffer[span->y * cstride + span->x];
|
auto cmp = &cbuffer[span->y * cstride + span->x];
|
||||||
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
if (span->coverage == 255) src = a;
|
if (span->coverage == 255) src = a;
|
||||||
|
@ -531,7 +531,7 @@ static bool _rasterMattedRle(SwSurface* surface, SwRle* rle, const RenderColor&
|
||||||
{
|
{
|
||||||
TVGLOG("SW_ENGINE", "Matted(%d) Rle", (int)surface->compositor->method);
|
TVGLOG("SW_ENGINE", "Matted(%d) Rle", (int)surface->compositor->method);
|
||||||
|
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
auto cbuffer = surface->compositor->image.buf8;
|
auto cbuffer = surface->compositor->image.buf8;
|
||||||
auto csize = surface->compositor->image.channelSize;
|
auto csize = surface->compositor->image.channelSize;
|
||||||
auto alpha = surface->alpha(surface->compositor->method);
|
auto alpha = surface->alpha(surface->compositor->method);
|
||||||
|
@ -540,7 +540,7 @@ static bool _rasterMattedRle(SwSurface* surface, SwRle* rle, const RenderColor&
|
||||||
if (surface->channelSize == sizeof(uint32_t)) {
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
uint32_t src;
|
uint32_t src;
|
||||||
auto color = surface->join(c.r, c.g, c.b, c.a);
|
auto color = surface->join(c.r, c.g, c.b, c.a);
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
|
auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
|
||||||
if (span->coverage == 255) src = color;
|
if (span->coverage == 255) src = color;
|
||||||
|
@ -553,7 +553,7 @@ static bool _rasterMattedRle(SwSurface* surface, SwRle* rle, const RenderColor&
|
||||||
//8bit grayscale
|
//8bit grayscale
|
||||||
} else if (surface->channelSize == sizeof(uint8_t)) {
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
uint8_t src;
|
uint8_t src;
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
|
auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
|
||||||
if (span->coverage == 255) src = c.a;
|
if (span->coverage == 255) src = c.a;
|
||||||
|
@ -571,10 +571,10 @@ static bool _rasterBlendingRle(SwSurface* surface, const SwRle* rle, const Rende
|
||||||
{
|
{
|
||||||
if (surface->channelSize != sizeof(uint32_t)) return false;
|
if (surface->channelSize != sizeof(uint32_t)) return false;
|
||||||
|
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
auto color = surface->join(c.r, c.g, c.b, c.a);
|
auto color = surface->join(c.r, c.g, c.b, c.a);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
if (span->coverage == 255) {
|
if (span->coverage == 255) {
|
||||||
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||||
|
@ -605,12 +605,12 @@ static bool _rasterTranslucentRle(SwSurface* surface, const SwRle* rle, const Re
|
||||||
|
|
||||||
static bool _rasterSolidRle(SwSurface* surface, const SwRle* rle, const RenderColor& c)
|
static bool _rasterSolidRle(SwSurface* surface, const SwRle* rle, const RenderColor& c)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
|
|
||||||
//32bit channels
|
//32bit channels
|
||||||
if (surface->channelSize == sizeof(uint32_t)) {
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
auto color = surface->join(c.r, c.g, c.b, 255);
|
auto color = surface->join(c.r, c.g, c.b, 255);
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
if (span->coverage == 255) {
|
if (span->coverage == 255) {
|
||||||
rasterPixel32(surface->buf32 + span->y * surface->stride, color, span->x, span->len);
|
rasterPixel32(surface->buf32 + span->y * surface->stride, color, span->x, span->len);
|
||||||
} else {
|
} else {
|
||||||
|
@ -624,7 +624,7 @@ static bool _rasterSolidRle(SwSurface* surface, const SwRle* rle, const RenderCo
|
||||||
}
|
}
|
||||||
//8bit grayscale
|
//8bit grayscale
|
||||||
} else if (surface->channelSize == sizeof(uint8_t)) {
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
if (span->coverage == 255) {
|
if (span->coverage == 255) {
|
||||||
rasterGrayscale8(surface->buf8, span->coverage, span->y * surface->stride + span->x, span->len);
|
rasterGrayscale8(surface->buf8, span->coverage, span->y * surface->stride + span->x, span->len);
|
||||||
} else {
|
} else {
|
||||||
|
@ -687,14 +687,14 @@ static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage* image
|
||||||
{
|
{
|
||||||
TVGLOG("SW_ENGINE", "Scaled Matted(%d) Rle Image", (int)surface->compositor->method);
|
TVGLOG("SW_ENGINE", "Scaled Matted(%d) Rle Image", (int)surface->compositor->method);
|
||||||
|
|
||||||
auto span = image->rle->spans;
|
auto span = image->rle->data();
|
||||||
auto csize = surface->compositor->image.channelSize;
|
auto csize = surface->compositor->image.channelSize;
|
||||||
auto alpha = surface->alpha(surface->compositor->method);
|
auto alpha = surface->alpha(surface->compositor->method);
|
||||||
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
|
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
|
||||||
auto sampleSize = _sampleSize(image->scale);
|
auto sampleSize = _sampleSize(image->scale);
|
||||||
int32_t miny = 0, maxy = 0;
|
int32_t miny = 0, maxy = 0;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) {
|
||||||
SCALED_IMAGE_RANGE_Y(span->y)
|
SCALED_IMAGE_RANGE_Y(span->y)
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize];
|
auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize];
|
||||||
|
@ -712,12 +712,12 @@ static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage* image
|
||||||
|
|
||||||
static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const RenderRegion& bbox, uint8_t opacity)
|
static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const RenderRegion& bbox, uint8_t opacity)
|
||||||
{
|
{
|
||||||
auto span = image->rle->spans;
|
auto span = image->rle->data();
|
||||||
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
|
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
|
||||||
auto sampleSize = _sampleSize(image->scale);
|
auto sampleSize = _sampleSize(image->scale);
|
||||||
int32_t miny = 0, maxy = 0;
|
int32_t miny = 0, maxy = 0;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) {
|
||||||
SCALED_IMAGE_RANGE_Y(span->y)
|
SCALED_IMAGE_RANGE_Y(span->y)
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
auto alpha = MULTIPLY(span->coverage, opacity);
|
auto alpha = MULTIPLY(span->coverage, opacity);
|
||||||
|
@ -743,12 +743,12 @@ static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* ima
|
||||||
|
|
||||||
static bool _rasterScaledRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const RenderRegion& bbox, uint8_t opacity)
|
static bool _rasterScaledRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const RenderRegion& bbox, uint8_t opacity)
|
||||||
{
|
{
|
||||||
auto span = image->rle->spans;
|
auto span = image->rle->data();
|
||||||
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
|
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
|
||||||
auto sampleSize = _sampleSize(image->scale);
|
auto sampleSize = _sampleSize(image->scale);
|
||||||
int32_t miny = 0, maxy = 0;
|
int32_t miny = 0, maxy = 0;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) {
|
||||||
SCALED_IMAGE_RANGE_Y(span->y)
|
SCALED_IMAGE_RANGE_Y(span->y)
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
auto alpha = MULTIPLY(span->coverage, opacity);
|
auto alpha = MULTIPLY(span->coverage, opacity);
|
||||||
|
@ -794,12 +794,12 @@ static bool _rasterDirectMattedRleImage(SwSurface* surface, const SwImage* image
|
||||||
{
|
{
|
||||||
TVGLOG("SW_ENGINE", "Direct Matted(%d) Rle Image", (int)surface->compositor->method);
|
TVGLOG("SW_ENGINE", "Direct Matted(%d) Rle Image", (int)surface->compositor->method);
|
||||||
|
|
||||||
auto span = image->rle->spans;
|
auto span = image->rle->data();
|
||||||
auto csize = surface->compositor->image.channelSize;
|
auto csize = surface->compositor->image.channelSize;
|
||||||
auto cbuffer = surface->compositor->image.buf8;
|
auto cbuffer = surface->compositor->image.buf8;
|
||||||
auto alpha = surface->alpha(surface->compositor->method);
|
auto alpha = surface->alpha(surface->compositor->method);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
|
auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
|
||||||
auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
|
auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
|
||||||
|
@ -822,9 +822,9 @@ static bool _rasterDirectMattedRleImage(SwSurface* surface, const SwImage* image
|
||||||
|
|
||||||
static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity)
|
static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity)
|
||||||
{
|
{
|
||||||
auto span = image->rle->spans;
|
auto span = image->rle->data();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
|
auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
|
||||||
auto alpha = MULTIPLY(span->coverage, opacity);
|
auto alpha = MULTIPLY(span->coverage, opacity);
|
||||||
|
@ -845,9 +845,9 @@ static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* ima
|
||||||
|
|
||||||
static bool _rasterDirectRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity)
|
static bool _rasterDirectRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity)
|
||||||
{
|
{
|
||||||
auto span = image->rle->spans;
|
auto span = image->rle->data();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
|
auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
|
||||||
auto alpha = MULTIPLY(span->coverage, opacity);
|
auto alpha = MULTIPLY(span->coverage, opacity);
|
||||||
|
@ -1378,11 +1378,11 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const RenderRegion& bb
|
||||||
template<typename fillMethod>
|
template<typename fillMethod>
|
||||||
static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRle* rle, const SwFill* fill, SwMask maskOp)
|
static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRle* rle, const SwFill* fill, SwMask maskOp)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
auto cstride = surface->compositor->image.stride;
|
auto cstride = surface->compositor->image.stride;
|
||||||
auto cbuffer = surface->compositor->image.buf8;
|
auto cbuffer = surface->compositor->image.buf8;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto cmp = &cbuffer[span->y * cstride + span->x];
|
auto cmp = &cbuffer[span->y * cstride + span->x];
|
||||||
fillMethod()(fill, cmp, span->y, span->x, span->len, maskOp, span->coverage);
|
fillMethod()(fill, cmp, span->y, span->x, span->len, maskOp, span->coverage);
|
||||||
}
|
}
|
||||||
|
@ -1393,12 +1393,12 @@ static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRle* r
|
||||||
template<typename fillMethod>
|
template<typename fillMethod>
|
||||||
static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRle* rle, const SwFill* fill, SwMask maskOp)
|
static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRle* rle, const SwFill* fill, SwMask maskOp)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
auto cstride = surface->compositor->image.stride;
|
auto cstride = surface->compositor->image.stride;
|
||||||
auto cbuffer = surface->compositor->image.buf8;
|
auto cbuffer = surface->compositor->image.buf8;
|
||||||
auto dbuffer = surface->buf8;
|
auto dbuffer = surface->buf8;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto cmp = &cbuffer[span->y * cstride + span->x];
|
auto cmp = &cbuffer[span->y * cstride + span->x];
|
||||||
auto dst = &dbuffer[span->y * surface->stride + span->x];
|
auto dst = &dbuffer[span->y * surface->stride + span->x];
|
||||||
fillMethod()(fill, dst, span->y, span->x, span->len, cmp, maskOp, span->coverage);
|
fillMethod()(fill, dst, span->y, span->x, span->len, cmp, maskOp, span->coverage);
|
||||||
|
@ -1427,12 +1427,12 @@ static bool _rasterGradientMattedRle(SwSurface* surface, const SwRle* rle, const
|
||||||
{
|
{
|
||||||
TVGLOG("SW_ENGINE", "Matted(%d) Rle Linear Gradient", (int)surface->compositor->method);
|
TVGLOG("SW_ENGINE", "Matted(%d) Rle Linear Gradient", (int)surface->compositor->method);
|
||||||
|
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
auto csize = surface->compositor->image.channelSize;
|
auto csize = surface->compositor->image.channelSize;
|
||||||
auto cbuffer = surface->compositor->image.buf8;
|
auto cbuffer = surface->compositor->image.buf8;
|
||||||
auto alpha = surface->alpha(surface->compositor->method);
|
auto alpha = surface->alpha(surface->compositor->method);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
|
auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
|
||||||
fillMethod()(fill, dst, span->y, span->x, span->len, cmp, alpha, csize, span->coverage);
|
fillMethod()(fill, dst, span->y, span->x, span->len, cmp, alpha, csize, span->coverage);
|
||||||
|
@ -1444,9 +1444,9 @@ static bool _rasterGradientMattedRle(SwSurface* surface, const SwRle* rle, const
|
||||||
template<typename fillMethod>
|
template<typename fillMethod>
|
||||||
static bool _rasterBlendingGradientRle(SwSurface* surface, const SwRle* rle, const SwFill* fill)
|
static bool _rasterBlendingGradientRle(SwSurface* surface, const SwRle* rle, const SwFill* fill)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, surface->blender, span->coverage);
|
fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, surface->blender, span->coverage);
|
||||||
}
|
}
|
||||||
|
@ -1457,18 +1457,18 @@ static bool _rasterBlendingGradientRle(SwSurface* surface, const SwRle* rle, con
|
||||||
template<typename fillMethod>
|
template<typename fillMethod>
|
||||||
static bool _rasterTranslucentGradientRle(SwSurface* surface, const SwRle* rle, const SwFill* fill)
|
static bool _rasterTranslucentGradientRle(SwSurface* surface, const SwRle* rle, const SwFill* fill)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
|
|
||||||
//32 bits
|
//32 bits
|
||||||
if (surface->channelSize == sizeof(uint32_t)) {
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, 255);
|
if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, 255);
|
||||||
else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendNormal, span->coverage);
|
else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendNormal, span->coverage);
|
||||||
}
|
}
|
||||||
//8 bits
|
//8 bits
|
||||||
} else if (surface->channelSize == sizeof(uint8_t)) {
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, span->coverage);
|
fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, span->coverage);
|
||||||
}
|
}
|
||||||
|
@ -1480,18 +1480,18 @@ static bool _rasterTranslucentGradientRle(SwSurface* surface, const SwRle* rle,
|
||||||
template<typename fillMethod>
|
template<typename fillMethod>
|
||||||
static bool _rasterSolidGradientRle(SwSurface* surface, const SwRle* rle, const SwFill* fill)
|
static bool _rasterSolidGradientRle(SwSurface* surface, const SwRle* rle, const SwFill* fill)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
|
|
||||||
//32 bits
|
//32 bits
|
||||||
if (surface->channelSize == sizeof(uint32_t)) {
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendSrcOver, 255);
|
if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendSrcOver, 255);
|
||||||
else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendInterp, span->coverage);
|
else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendInterp, span->coverage);
|
||||||
}
|
}
|
||||||
//8 bits
|
//8 bits
|
||||||
} else if (surface->channelSize == sizeof(uint8_t)) {
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskNone, 255);
|
if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskNone, 255);
|
||||||
else fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, span->coverage);
|
else fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, span->coverage);
|
||||||
|
|
|
@ -160,14 +160,14 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const RenderRegion& bbo
|
||||||
|
|
||||||
static bool avxRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const RenderColor& c)
|
static bool avxRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const RenderColor& c)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
|
|
||||||
//32bit channels
|
//32bit channels
|
||||||
if (surface->channelSize == sizeof(uint32_t)) {
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
auto color = surface->join(c.r, c.g, c.b, c.a);
|
auto color = surface->join(c.r, c.g, c.b, c.a);
|
||||||
uint32_t src;
|
uint32_t src;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size(); ++i) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
|
|
||||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||||
|
@ -213,7 +213,7 @@ static bool avxRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const
|
||||||
} else if (surface->channelSize == sizeof(uint8_t)) {
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
TVGLOG("SW_ENGINE", "Require AVX Optimization, Channel Size = %d", surface->channelSize);
|
TVGLOG("SW_ENGINE", "Require AVX Optimization, Channel Size = %d", surface->channelSize);
|
||||||
uint8_t src;
|
uint8_t src;
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
if (span->coverage < 255) src = MULTIPLY(span->coverage, c.a);
|
if (span->coverage < 255) src = MULTIPLY(span->coverage, c.a);
|
||||||
else src = c.a;
|
else src = c.a;
|
||||||
|
|
|
@ -94,13 +94,13 @@ static void inline cRasterPixels(PIXEL_T* dst, PIXEL_T val, uint32_t offset, int
|
||||||
|
|
||||||
static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const RenderColor& c)
|
static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const RenderColor& c)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
|
|
||||||
//32bit channels
|
//32bit channels
|
||||||
if (surface->channelSize == sizeof(uint32_t)) {
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
auto color = surface->join(c.r, c.g, c.b, c.a);
|
auto color = surface->join(c.r, c.g, c.b, c.a);
|
||||||
uint32_t src;
|
uint32_t src;
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||||
else src = color;
|
else src = color;
|
||||||
|
@ -112,7 +112,7 @@ static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRle* rle, c
|
||||||
//8bit grayscale
|
//8bit grayscale
|
||||||
} else if (surface->channelSize == sizeof(uint8_t)) {
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
uint8_t src;
|
uint8_t src;
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
if (span->coverage < 255) src = MULTIPLY(span->coverage, c.a);
|
if (span->coverage < 255) src = MULTIPLY(span->coverage, c.a);
|
||||||
else src = c.a;
|
else src = c.a;
|
||||||
|
|
|
@ -91,7 +91,7 @@ static void neonRasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int3
|
||||||
|
|
||||||
static bool neonRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const RenderColor& c)
|
static bool neonRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const RenderColor& c)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->data();
|
||||||
|
|
||||||
//32bit channels
|
//32bit channels
|
||||||
if (surface->channelSize == sizeof(uint32_t)) {
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
|
@ -100,7 +100,7 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const
|
||||||
uint8x8_t *vDst = nullptr;
|
uint8x8_t *vDst = nullptr;
|
||||||
uint16_t align;
|
uint16_t align;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size(); ++i) {
|
||||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||||
else src = color;
|
else src = color;
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const
|
||||||
} else if (surface->channelSize == sizeof(uint8_t)) {
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
TVGLOG("SW_ENGINE", "Require Neon Optimization, Channel Size = %d", surface->channelSize);
|
TVGLOG("SW_ENGINE", "Require Neon Optimization, Channel Size = %d", surface->channelSize);
|
||||||
uint8_t src;
|
uint8_t src;
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size(); ++i, ++span) {
|
||||||
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
if (span->coverage < 255) src = MULTIPLY(span->coverage, c.a);
|
if (span->coverage < 255) src = MULTIPLY(span->coverage, c.a);
|
||||||
else src = c.a;
|
else src = c.a;
|
||||||
|
|
|
@ -60,8 +60,8 @@ static bool _arrange(const SwImage* image, const RenderRegion* bbox, int& yStart
|
||||||
bboxTop = bbox->min.y;
|
bboxTop = bbox->min.y;
|
||||||
bboxBottom = bbox->max.y;
|
bboxBottom = bbox->max.y;
|
||||||
} else {
|
} else {
|
||||||
bboxTop = image->rle->spans->y;
|
bboxTop = image->rle->spans.first().y;
|
||||||
bboxBottom = image->rle->spans[image->rle->size - 1].y;
|
bboxBottom = image->rle->spans.last().y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yStart < bboxTop) yStart = bboxTop;
|
if (yStart < bboxTop) yStart = bboxTop;
|
||||||
|
@ -103,7 +103,7 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage
|
||||||
minx = bbox->min.x;
|
minx = bbox->min.x;
|
||||||
maxx = bbox->max.x;
|
maxx = bbox->max.x;
|
||||||
} else {
|
} else {
|
||||||
span = image->rle->spans;
|
span = image->rle->data();
|
||||||
while (span->y < yStart) {
|
while (span->y < yStart) {
|
||||||
++span;
|
++span;
|
||||||
++spanIdx;
|
++spanIdx;
|
||||||
|
@ -120,7 +120,7 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage
|
||||||
minx = INT32_MAX;
|
minx = INT32_MAX;
|
||||||
maxx = 0;
|
maxx = 0;
|
||||||
//one single row, could be consisted of multiple spans.
|
//one single row, could be consisted of multiple spans.
|
||||||
while (span->y == y && spanIdx < image->rle->size) {
|
while (span->y == y && spanIdx < image->rle->size()) {
|
||||||
if (minx > span->x) minx = span->x;
|
if (minx > span->x) minx = span->x;
|
||||||
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
||||||
++span;
|
++span;
|
||||||
|
@ -195,7 +195,7 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage
|
||||||
_ua += _dudya;
|
_ua += _dudya;
|
||||||
_va += _dvdya;
|
_va += _dvdya;
|
||||||
|
|
||||||
if (!bbox && spanIdx >= image->rle->size) break;
|
if (!bbox && spanIdx >= image->rle->size()) break;
|
||||||
|
|
||||||
++y;
|
++y;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +236,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
|
||||||
minx = bbox->min.x;
|
minx = bbox->min.x;
|
||||||
maxx = bbox->max.x;
|
maxx = bbox->max.x;
|
||||||
} else {
|
} else {
|
||||||
span = image->rle->spans;
|
span = image->rle->data();
|
||||||
while (span->y < yStart) {
|
while (span->y < yStart) {
|
||||||
++span;
|
++span;
|
||||||
++spanIdx;
|
++spanIdx;
|
||||||
|
@ -253,7 +253,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
|
||||||
minx = INT32_MAX;
|
minx = INT32_MAX;
|
||||||
maxx = 0;
|
maxx = 0;
|
||||||
//one single row, could be consisted of multiple spans.
|
//one single row, could be consisted of multiple spans.
|
||||||
while (span->y == y && spanIdx < image->rle->size) {
|
while (span->y == y && spanIdx < image->rle->size()) {
|
||||||
if (minx > span->x) minx = span->x;
|
if (minx > span->x) minx = span->x;
|
||||||
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
||||||
++span;
|
++span;
|
||||||
|
@ -387,7 +387,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
|
||||||
_ua += _dudya;
|
_ua += _dudya;
|
||||||
_va += _dvdya;
|
_va += _dvdya;
|
||||||
|
|
||||||
if (!bbox && spanIdx >= image->rle->size) break;
|
if (!bbox && spanIdx >= image->rle->size()) break;
|
||||||
|
|
||||||
++y;
|
++y;
|
||||||
}
|
}
|
||||||
|
@ -460,7 +460,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
if (tvg::equal(y[0], y[1])) side = x[0] > x[1];
|
if (tvg::equal(y[0], y[1])) side = x[0] > x[1];
|
||||||
if (tvg::equal(y[1], y[2])) side = x[2] > x[1];
|
if (tvg::equal(y[1], y[2])) side = x[2] > x[1];
|
||||||
|
|
||||||
auto bboxTop = bbox ? bbox->min.y : image->rle->spans->y; //Normal Image or Rle Image?
|
auto bboxTop = bbox ? bbox->min.y : image->rle->data()->y; //Normal Image or Rle Image?
|
||||||
auto compositing = _compositing(surface); //Composition required
|
auto compositing = _compositing(surface); //Composition required
|
||||||
auto blending = _blending(surface); //Blending required
|
auto blending = _blending(surface); //Blending required
|
||||||
|
|
||||||
|
@ -871,7 +871,7 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
|
||||||
}
|
}
|
||||||
|
|
||||||
//Exceptions: No dedicated drawing area?
|
//Exceptions: No dedicated drawing area?
|
||||||
if ((!image->rle && !bbox) || (image->rle && image->rle->size == 0)) return true;
|
if ((!image->rle && !bbox) || (image->rle && image->rle->size() == 0)) return true;
|
||||||
|
|
||||||
/* Prepare vertices.
|
/* Prepare vertices.
|
||||||
shift XY coordinates to match the sub-pixeling technique. */
|
shift XY coordinates to match the sub-pixeling technique. */
|
||||||
|
|
|
@ -324,27 +324,18 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
|
||||||
if (!rw.antiAlias) coverage = 255;
|
if (!rw.antiAlias) coverage = 255;
|
||||||
|
|
||||||
//see whether we can add this span to the current list
|
//see whether we can add this span to the current list
|
||||||
if (rle->size > 0) {
|
if (!rle->spans.empty()) {
|
||||||
auto span = rle->spans + rle->size - 1;
|
auto& span = rle->spans.last();
|
||||||
if ((span->coverage == coverage) && (span->y == y) && (span->x + span->len == x)) {
|
if ((span.coverage == coverage) && (span.y == y) && (span.x + span.len == x)) {
|
||||||
//Clip x range
|
//Clip x range
|
||||||
SwCoord xOver = 0;
|
SwCoord xOver = 0;
|
||||||
if (x + aCount >= rw.cellMax.x) xOver -= (x + aCount - rw.cellMax.x);
|
if (x + aCount >= rw.cellMax.x) xOver -= (x + aCount - rw.cellMax.x);
|
||||||
if (x < rw.cellMin.x) xOver -= (rw.cellMin.x - x);
|
if (x < rw.cellMin.x) xOver -= (rw.cellMin.x - x);
|
||||||
span->len += (aCount + xOver);
|
span.len += (aCount + xOver);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//span pool is full, grow it.
|
|
||||||
if (rle->size >= rle->alloc) {
|
|
||||||
auto newSize = (rle->size > 0) ? (rle->size * 2) : 256;
|
|
||||||
if (rle->alloc < newSize) {
|
|
||||||
rle->alloc = newSize;
|
|
||||||
rle->spans = tvg::realloc<SwSpan*>(rle->spans, rle->alloc * sizeof(SwSpan));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Clip x range
|
//Clip x range
|
||||||
SwCoord xOver = 0;
|
SwCoord xOver = 0;
|
||||||
if (x + aCount >= rw.cellMax.x) xOver -= (x + aCount - rw.cellMax.x);
|
if (x + aCount >= rw.cellMax.x) xOver -= (x + aCount - rw.cellMax.x);
|
||||||
|
@ -357,12 +348,7 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
|
||||||
if (aCount + xOver <= 0) return;
|
if (aCount + xOver <= 0) return;
|
||||||
|
|
||||||
//add a span to the current list
|
//add a span to the current list
|
||||||
auto span = rle->spans + rle->size;
|
rle->spans.next() = {(uint16_t)x, (uint16_t)y, uint16_t(aCount + xOver), (uint8_t)coverage};
|
||||||
span->x = x;
|
|
||||||
span->y = y;
|
|
||||||
span->len = (aCount + xOver);
|
|
||||||
span->coverage = coverage;
|
|
||||||
rle->size++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -737,109 +723,6 @@ static bool _genRle(RleWorker& rw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SwSpan* _intersectSpansRegion(const SwRle *clip, const SwRle *target, SwSpan *outSpans, uint32_t outSpansCnt)
|
|
||||||
{
|
|
||||||
auto out = outSpans;
|
|
||||||
auto spans = target->spans;
|
|
||||||
auto end = target->spans + target->size;
|
|
||||||
auto clipSpans = clip->spans;
|
|
||||||
auto clipEnd = clip->spans + clip->size;
|
|
||||||
|
|
||||||
while (spans < end && clipSpans < clipEnd) {
|
|
||||||
//align y-coordinates.
|
|
||||||
if (clipSpans->y > spans->y) {
|
|
||||||
++spans;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (spans->y > clipSpans->y) {
|
|
||||||
++clipSpans;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Try clipping with all clip spans which have a same y-coordinate.
|
|
||||||
auto temp = clipSpans;
|
|
||||||
while(temp < clipEnd && temp->y == clipSpans->y) {
|
|
||||||
if (outSpansCnt == 0) {
|
|
||||||
TVGERR("SW_ENGINE", "span buffer is over.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
auto sx1 = spans->x;
|
|
||||||
auto sx2 = sx1 + spans->len;
|
|
||||||
auto cx1 = temp->x;
|
|
||||||
auto cx2 = cx1 + temp->len;
|
|
||||||
|
|
||||||
//The span must be left(x1) to right(x2) direction. Not intersected.
|
|
||||||
if (cx2 < sx1 || sx2 < cx1) {
|
|
||||||
++temp;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//clip span region.
|
|
||||||
auto x = sx1 > cx1 ? sx1 : cx1;
|
|
||||||
auto len = (sx2 < cx2 ? sx2 : cx2) - x;
|
|
||||||
if (len > 0) {
|
|
||||||
out->x = x;
|
|
||||||
out->y = temp->y;
|
|
||||||
out->len = len;
|
|
||||||
out->coverage = (uint8_t)(((spans->coverage * temp->coverage) + 0xff) >> 8);
|
|
||||||
++out;
|
|
||||||
--outSpansCnt;
|
|
||||||
}
|
|
||||||
++temp;
|
|
||||||
}
|
|
||||||
++spans;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static SwSpan* _intersectSpansRect(const RenderRegion *bbox, const SwRle *targetRle, SwSpan *outSpans, uint32_t outSpansCnt)
|
|
||||||
{
|
|
||||||
auto out = outSpans;
|
|
||||||
auto spans = targetRle->spans;
|
|
||||||
auto end = targetRle->spans + targetRle->size;
|
|
||||||
auto minx = static_cast<int16_t>(bbox->min.x);
|
|
||||||
auto miny = static_cast<int16_t>(bbox->min.y);
|
|
||||||
auto maxx = minx + static_cast<int16_t>(bbox->max.x - bbox->min.x) - 1;
|
|
||||||
auto maxy = miny + static_cast<int16_t>(bbox->max.y - bbox->min.y) - 1;
|
|
||||||
|
|
||||||
while (outSpansCnt > 0 && spans < end) {
|
|
||||||
if (spans->y > maxy) {
|
|
||||||
spans = end;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (spans->y < miny || spans->x > maxx || spans->x + spans->len <= minx) {
|
|
||||||
++spans;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (spans->x < minx) {
|
|
||||||
out->len = (spans->len - (minx - spans->x)) < (maxx - minx + 1) ? (spans->len - (minx - spans->x)) : (maxx - minx + 1);
|
|
||||||
out->x = minx;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
out->x = spans->x;
|
|
||||||
out->len = spans->len < (maxx - spans->x + 1) ? spans->len : (maxx - spans->x + 1);
|
|
||||||
}
|
|
||||||
if (out->len > 0) {
|
|
||||||
out->y = spans->y;
|
|
||||||
out->coverage = spans->coverage;
|
|
||||||
++out;
|
|
||||||
--outSpansCnt;
|
|
||||||
}
|
|
||||||
++spans;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void _replaceClipSpan(SwRle *rle, SwSpan* clippedSpans, uint32_t size)
|
|
||||||
{
|
|
||||||
tvg::free(rle->spans);
|
|
||||||
rle->spans = clippedSpans;
|
|
||||||
rle->size = rle->alloc = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -876,6 +759,7 @@ SwRle* rleRender(SwRle* rle, const SwOutline* outline, const RenderRegion& bbox,
|
||||||
|
|
||||||
if (!rle) rw.rle = tvg::calloc<SwRle*>(1, sizeof(SwRle));
|
if (!rle) rw.rle = tvg::calloc<SwRle*>(1, sizeof(SwRle));
|
||||||
else rw.rle = rle;
|
else rw.rle = rle;
|
||||||
|
rw.rle->spans.reserve(256);
|
||||||
|
|
||||||
//Generate RLE
|
//Generate RLE
|
||||||
Band bands[BAND_SIZE];
|
Band bands[BAND_SIZE];
|
||||||
|
@ -963,20 +847,17 @@ error:
|
||||||
|
|
||||||
SwRle* rleRender(const RenderRegion* bbox)
|
SwRle* rleRender(const RenderRegion* bbox)
|
||||||
{
|
{
|
||||||
auto width = static_cast<uint16_t>(bbox->w());
|
auto rle = tvg::calloc<SwRle*>(sizeof(SwRle), 1);
|
||||||
auto height = static_cast<uint16_t>(bbox->h());
|
rle->spans.reserve(bbox->h());
|
||||||
|
rle->spans.count = bbox->h();
|
||||||
|
|
||||||
auto rle = tvg::malloc<SwRle*>(sizeof(SwRle));
|
//cheaper without push()
|
||||||
rle->spans = tvg::malloc<SwSpan*>(sizeof(SwSpan) * height);
|
auto x = uint16_t(bbox->min.x);
|
||||||
rle->size = height;
|
auto y = uint16_t(bbox->min.y);
|
||||||
rle->alloc = height;
|
auto len = uint16_t(bbox->w());
|
||||||
|
|
||||||
auto span = rle->spans;
|
ARRAY_FOREACH(p, rle->spans) {
|
||||||
for (uint16_t i = 0; i < height; ++i, ++span) {
|
*p = {x, y++, len, 255};
|
||||||
span->x = bbox->min.x;
|
|
||||||
span->y = bbox->min.y + i;
|
|
||||||
span->len = width;
|
|
||||||
span->coverage = 255;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rle;
|
return rle;
|
||||||
|
@ -985,44 +866,89 @@ SwRle* rleRender(const RenderRegion* bbox)
|
||||||
|
|
||||||
void rleReset(SwRle* rle)
|
void rleReset(SwRle* rle)
|
||||||
{
|
{
|
||||||
if (!rle) return;
|
if (rle) rle->spans.clear();
|
||||||
rle->size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void rleFree(SwRle* rle)
|
void rleFree(SwRle* rle)
|
||||||
{
|
{
|
||||||
if (!rle) return;
|
if (!rle) return;
|
||||||
if (rle->spans) tvg::free(rle->spans);
|
rle->spans.reset();
|
||||||
tvg::free(rle);
|
tvg::free(rle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool rleClip(SwRle *rle, const SwRle *clip)
|
bool rleClip(SwRle *rle, const SwRle *clip)
|
||||||
{
|
{
|
||||||
if (rle->size == 0 || clip->size == 0) return false;
|
if (rle->spans.empty() || clip->spans.empty()) return false;
|
||||||
auto spanCnt = 2 * (rle->size > clip->size ? rle->size : clip->size); //factor 2 added for safety (no real cases observed where the factor exceeded 1.4)
|
|
||||||
auto spans = tvg::malloc<SwSpan*>(sizeof(SwSpan) * (spanCnt));
|
|
||||||
auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
|
|
||||||
|
|
||||||
_replaceClipSpan(rle, spans, spansEnd - spans);
|
Array<SwSpan> out;
|
||||||
|
out.reserve(std::max(rle->spans.count, clip->spans.count));
|
||||||
|
|
||||||
TVGLOG("SW_ENGINE", "Using Path Clipping!");
|
auto spans = rle->data();
|
||||||
|
auto end = rle->spans.end();
|
||||||
|
auto cspans = clip->data();
|
||||||
|
auto cend = clip->spans.end();
|
||||||
|
|
||||||
|
while(spans < end && cspans < cend) {
|
||||||
|
//align y-coordinates.
|
||||||
|
if (cspans->y > spans->y) {
|
||||||
|
++spans;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (spans->y > cspans->y) {
|
||||||
|
++cspans;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//try clipping with all clip spans which have a same y-coordinate.
|
||||||
|
auto temp = cspans;
|
||||||
|
while(temp->y == cspans->y && temp < cend) {
|
||||||
|
//span must be left(x1) to right(x2) direction. Not intersected.
|
||||||
|
if ((spans->x + spans->len) < spans->x || (temp->x + temp->len) < temp->x) {
|
||||||
|
++temp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//clip span region
|
||||||
|
auto x = std::max(spans->x, temp->x);
|
||||||
|
auto len = std::min((spans->x + spans->len), (temp->x + temp->len)) - x;
|
||||||
|
if (len > 0) out.next() = {uint16_t(x), temp->y, uint16_t(len), (uint8_t)(((spans->coverage * temp->coverage) + 0xff) >> 8)};
|
||||||
|
++temp;
|
||||||
|
}
|
||||||
|
++spans;
|
||||||
|
}
|
||||||
|
out.move(rle->spans);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool rleClip(SwRle *rle, const RenderRegion* clip)
|
bool rleClip(SwRle *rle, const RenderRegion* clip)
|
||||||
{
|
{
|
||||||
if (rle->size == 0) return false;
|
if (rle->spans.empty() || clip->invalid()) return false;
|
||||||
auto spans = tvg::malloc<SwSpan*>(sizeof(SwSpan) * (rle->size));
|
|
||||||
auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size);
|
|
||||||
|
|
||||||
_replaceClipSpan(rle, spans, spansEnd - spans);
|
auto& min = clip->min;
|
||||||
|
auto& max = clip->max;
|
||||||
|
|
||||||
TVGLOG("SW_ENGINE", "Using Box Clipping!");
|
Array<SwSpan> out;
|
||||||
|
out.reserve(rle->spans.count);
|
||||||
|
auto data = out.data;
|
||||||
|
uint16_t x, len;
|
||||||
|
|
||||||
|
ARRAY_FOREACH(p, rle->spans) {
|
||||||
|
if (p->y >= max.y) break;
|
||||||
|
if (p->y < min.y || p->x >= max.x || (p->x + p->len) <= min.x) continue;
|
||||||
|
if (p->x < min.x) {
|
||||||
|
x = min.x;
|
||||||
|
len = std::min((p->len - (x - p->x)), (max.x - x));
|
||||||
|
} else {
|
||||||
|
x = p->x;
|
||||||
|
len = std::min(p->len, uint16_t(max.x - x));
|
||||||
|
}
|
||||||
|
if (len > 0) {
|
||||||
|
*data = {x, p->y, len, p->coverage};
|
||||||
|
++data;
|
||||||
|
++out.count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.move(rle->spans);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue