mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 21:53:41 +00:00
sw_engine texmap: code clean up.
eliminate logic duplication by introducing a c++ template mechanism. This will retain the opacity condition branches to minimize binary size.
This commit is contained in:
parent
3399da198f
commit
dbdf103e82
4 changed files with 555 additions and 629 deletions
|
@ -4,7 +4,6 @@ source_file = [
|
||||||
'tvgSwRasterAvx.h',
|
'tvgSwRasterAvx.h',
|
||||||
'tvgSwRasterNeon.h',
|
'tvgSwRasterNeon.h',
|
||||||
'tvgSwRasterTexmap.h',
|
'tvgSwRasterTexmap.h',
|
||||||
'tvgSwRasterTexmapInternal.h',
|
|
||||||
'tvgSwFill.cpp',
|
'tvgSwFill.cpp',
|
||||||
'tvgSwImage.cpp',
|
'tvgSwImage.cpp',
|
||||||
'tvgSwMath.cpp',
|
'tvgSwMath.cpp',
|
||||||
|
|
|
@ -1,380 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifdef TEXMAP_INT_MASK
|
|
||||||
{
|
|
||||||
float _dudx = dudx, _dvdx = dvdx;
|
|
||||||
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
|
||||||
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
|
||||||
auto sbuf = image->buf32;
|
|
||||||
int32_t sw = static_cast<int32_t>(image->stride);
|
|
||||||
int32_t sh = image->h;
|
|
||||||
int32_t x1, x2, ar, ab, iru, irv, px, ay;
|
|
||||||
int32_t vv = 0, uu = 0;
|
|
||||||
int32_t minx = INT32_MAX, maxx = INT32_MIN;
|
|
||||||
float dx, u, v, iptr;
|
|
||||||
auto cbuffer = surface->compositor->image.buf32;
|
|
||||||
SwSpan* span = nullptr; //used only when rle based.
|
|
||||||
|
|
||||||
if (!_arrange(image, region, yStart, yEnd)) return;
|
|
||||||
|
|
||||||
//Clear out of the Polygon vertical ranges
|
|
||||||
auto size = surface->compositor->bbox.max.x - surface->compositor->bbox.min.x;
|
|
||||||
if (dirFlag == 1) { //left top case.
|
|
||||||
for(int y = surface->compositor->bbox.min.y; y < yStart; ++y) {
|
|
||||||
rasterRGBA32(surface->compositor->image.buf32 + y * surface->compositor->image.stride, 0, surface->compositor->bbox.min.x, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dirFlag == 4) { //right bottom case.
|
|
||||||
for(int y = yEnd; y < surface->compositor->bbox.max.y; ++y) {
|
|
||||||
rasterRGBA32(surface->compositor->image.buf32 + y * surface->compositor->image.stride, 0, surface->compositor->bbox.min.x, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Loop through all lines in the segment
|
|
||||||
uint32_t spanIdx = 0;
|
|
||||||
|
|
||||||
if (region) {
|
|
||||||
minx = region->min.x;
|
|
||||||
maxx = region->max.x;
|
|
||||||
} else {
|
|
||||||
span = image->rle->spans;
|
|
||||||
while (span->y < yStart) {
|
|
||||||
++span;
|
|
||||||
++spanIdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32_t y = yStart; y < yEnd; ++y) {
|
|
||||||
auto cmp = &cbuffer[y * surface->compositor->image.stride];
|
|
||||||
x1 = (int32_t)_xa;
|
|
||||||
x2 = (int32_t)_xb;
|
|
||||||
|
|
||||||
if (!region) {
|
|
||||||
minx = INT32_MAX;
|
|
||||||
maxx = INT32_MIN;
|
|
||||||
//one single row, could be consisted of multiple spans.
|
|
||||||
while (span->y == y && spanIdx < image->rle->size) {
|
|
||||||
if (minx > span->x) minx = span->x;
|
|
||||||
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
|
||||||
++span;
|
|
||||||
++spanIdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x1 < minx) x1 = minx;
|
|
||||||
if (x2 > maxx) x2 = maxx;
|
|
||||||
|
|
||||||
//Anti-Aliasing frames
|
|
||||||
//FIXME: this aa must be applied before masking op
|
|
||||||
ay = y - aaSpans->yStart;
|
|
||||||
if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1;
|
|
||||||
if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2;
|
|
||||||
|
|
||||||
//Range allowed
|
|
||||||
if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) {
|
|
||||||
for (int32_t x = surface->compositor->bbox.min.x; x < surface->compositor->bbox.max.x; ++x) {
|
|
||||||
//Range allowed
|
|
||||||
if (x >= x1 && x < x2) {
|
|
||||||
//Perform subtexel pre-stepping on UV
|
|
||||||
dx = 1 - (_xa - x1);
|
|
||||||
u = _ua + dx * _dudx;
|
|
||||||
v = _va + dx * _dvdx;
|
|
||||||
if ((uint32_t)v >= image->h) {
|
|
||||||
cmp[x] = 0;
|
|
||||||
} else {
|
|
||||||
if (opacity == 255) {
|
|
||||||
uu = (int) u;
|
|
||||||
vv = (int) v;
|
|
||||||
ar = (int)(255 * (1 - modff(u, &iptr)));
|
|
||||||
ab = (int)(255 * (1 - modff(v, &iptr)));
|
|
||||||
iru = uu + 1;
|
|
||||||
irv = vv + 1;
|
|
||||||
|
|
||||||
if (vv >= sh) continue;
|
|
||||||
|
|
||||||
px = *(sbuf + (vv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* right pixel */
|
|
||||||
int px2 = *(sbuf + (vv * sw) + iru);
|
|
||||||
px = INTERPOLATE(px, px2, ar);
|
|
||||||
}
|
|
||||||
/* vertical interpolate */
|
|
||||||
if (irv < sh) {
|
|
||||||
/* bottom pixel */
|
|
||||||
int px2 = *(sbuf + (irv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* bottom right pixel */
|
|
||||||
int px3 = *(sbuf + (irv * sw) + iru);
|
|
||||||
px2 = INTERPOLATE(px2, px3, ar);
|
|
||||||
}
|
|
||||||
px = INTERPOLATE(px, px2, ab);
|
|
||||||
}
|
|
||||||
cmp[x] = ALPHA_BLEND(cmp[x], ALPHA(px));
|
|
||||||
|
|
||||||
//Step UV horizontally
|
|
||||||
u += _dudx;
|
|
||||||
v += _dvdx;
|
|
||||||
} else {
|
|
||||||
uu = (int) u;
|
|
||||||
vv = (int) v;
|
|
||||||
ar = (int)(255 * (1 - modff(u, &iptr)));
|
|
||||||
ab = (int)(255 * (1 - modff(v, &iptr)));
|
|
||||||
iru = uu + 1;
|
|
||||||
irv = vv + 1;
|
|
||||||
|
|
||||||
if (vv >= sh) continue;
|
|
||||||
|
|
||||||
px = *(sbuf + (vv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* right pixel */
|
|
||||||
int px2 = *(sbuf + (vv * sw) + iru);
|
|
||||||
px = INTERPOLATE(px, px2, ar);
|
|
||||||
}
|
|
||||||
/* vertical interpolate */
|
|
||||||
if (irv < sh) {
|
|
||||||
/* bottom pixel */
|
|
||||||
int px2 = *(sbuf + (irv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* bottom right pixel */
|
|
||||||
int px3 = *(sbuf + (irv * sw) + iru);
|
|
||||||
px2 = INTERPOLATE(px2, px3, ar);
|
|
||||||
}
|
|
||||||
px = INTERPOLATE(px, px2, ab);
|
|
||||||
}
|
|
||||||
cmp[x] = ALPHA_BLEND(cmp[x], MULTIPLY(ALPHA(px), opacity));
|
|
||||||
|
|
||||||
//Step UV horizontally
|
|
||||||
u += _dudx;
|
|
||||||
v += _dvdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Clear out of polygon horizontal range
|
|
||||||
if (x < x1 && (dirFlag == 1 || dirFlag == 2)) cmp[x] = 0;
|
|
||||||
else if (x >= x2 && (dirFlag == 3 || dirFlag == 4)) cmp[x] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Step along both edges
|
|
||||||
_xa += _dxdya;
|
|
||||||
_xb += _dxdyb;
|
|
||||||
_ua += _dudya;
|
|
||||||
_va += _dvdya;
|
|
||||||
}
|
|
||||||
xa = _xa;
|
|
||||||
xb = _xb;
|
|
||||||
ua = _ua;
|
|
||||||
va = _va;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
float _dudx = dudx, _dvdx = dvdx;
|
|
||||||
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
|
||||||
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
|
||||||
auto sbuf = image->buf32;
|
|
||||||
int32_t sw = static_cast<int32_t>(image->stride);
|
|
||||||
int32_t sh = image->h;
|
|
||||||
int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay;
|
|
||||||
int32_t vv = 0, uu = 0;
|
|
||||||
int32_t minx = INT32_MAX, maxx = INT32_MIN;
|
|
||||||
float dx, u, v, iptr;
|
|
||||||
SwSpan* span = nullptr; //used only when rle based.
|
|
||||||
|
|
||||||
if (!_arrange(image, region, yStart, yEnd)) return;
|
|
||||||
|
|
||||||
//Loop through all lines in the segment
|
|
||||||
uint32_t spanIdx = 0;
|
|
||||||
|
|
||||||
if (region) {
|
|
||||||
minx = region->min.x;
|
|
||||||
maxx = region->max.x;
|
|
||||||
} else {
|
|
||||||
span = image->rle->spans;
|
|
||||||
while (span->y < yStart) {
|
|
||||||
++span;
|
|
||||||
++spanIdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
y = yStart;
|
|
||||||
|
|
||||||
while (y < yEnd) {
|
|
||||||
x1 = (int32_t)_xa;
|
|
||||||
x2 = (int32_t)_xb;
|
|
||||||
|
|
||||||
if (!region) {
|
|
||||||
minx = INT32_MAX;
|
|
||||||
maxx = INT32_MIN;
|
|
||||||
//one single row, could be consisted of multiple spans.
|
|
||||||
while (span->y == y && spanIdx < image->rle->size) {
|
|
||||||
if (minx > span->x) minx = span->x;
|
|
||||||
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
|
||||||
++span;
|
|
||||||
++spanIdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (x1 < minx) x1 = minx;
|
|
||||||
if (x2 > maxx) x2 = maxx;
|
|
||||||
|
|
||||||
//Anti-Aliasing frames
|
|
||||||
ay = y - aaSpans->yStart;
|
|
||||||
if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1;
|
|
||||||
if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2;
|
|
||||||
|
|
||||||
//Range allowed
|
|
||||||
if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) {
|
|
||||||
|
|
||||||
//Perform subtexel pre-stepping on UV
|
|
||||||
dx = 1 - (_xa - x1);
|
|
||||||
u = _ua + dx * _dudx;
|
|
||||||
v = _va + dx * _dvdx;
|
|
||||||
|
|
||||||
x = x1;
|
|
||||||
|
|
||||||
auto cmp = &surface->compositor->image.buf32[y * surface->compositor->image.stride + x1];
|
|
||||||
|
|
||||||
if (opacity == 255) {
|
|
||||||
//Draw horizontal line
|
|
||||||
while (x++ < x2) {
|
|
||||||
uu = (int) u;
|
|
||||||
vv = (int) v;
|
|
||||||
|
|
||||||
ar = (int)(255 * (1 - modff(u, &iptr)));
|
|
||||||
ab = (int)(255 * (1 - modff(v, &iptr)));
|
|
||||||
iru = uu + 1;
|
|
||||||
irv = vv + 1;
|
|
||||||
|
|
||||||
if (vv >= sh) continue;
|
|
||||||
|
|
||||||
px = *(sbuf + (vv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* right pixel */
|
|
||||||
int px2 = *(sbuf + (vv * sw) + iru);
|
|
||||||
px = INTERPOLATE(px, px2, ar);
|
|
||||||
}
|
|
||||||
/* vertical interpolate */
|
|
||||||
if (irv < sh) {
|
|
||||||
/* bottom pixel */
|
|
||||||
int px2 = *(sbuf + (irv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* bottom right pixel */
|
|
||||||
int px3 = *(sbuf + (irv * sw) + iru);
|
|
||||||
px2 = INTERPOLATE(px2, px3, ar);
|
|
||||||
}
|
|
||||||
px = INTERPOLATE(px, px2, ab);
|
|
||||||
}
|
|
||||||
#ifdef TEXMAP_ADD_MASK
|
|
||||||
*cmp = px + ALPHA_BLEND(*cmp, IALPHA(px));
|
|
||||||
#elif defined(TEXMAP_SUB_MASK)
|
|
||||||
*cmp = ALPHA_BLEND(*cmp, IALPHA(px));
|
|
||||||
#elif defined(TEXMAP_DIF_MASK)
|
|
||||||
*cmp = ALPHA_BLEND(px, IALPHA(*cmp)) + ALPHA_BLEND(*cmp, IALPHA(px));
|
|
||||||
#endif
|
|
||||||
++cmp;
|
|
||||||
|
|
||||||
//Step UV horizontally
|
|
||||||
u += _dudx;
|
|
||||||
v += _dvdx;
|
|
||||||
//range over?
|
|
||||||
if ((uint32_t)v >= image->h) break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Draw horizontal line
|
|
||||||
while (x++ < x2) {
|
|
||||||
uu = (int) u;
|
|
||||||
vv = (int) v;
|
|
||||||
|
|
||||||
ar = (int)(255 * (1 - modff(u, &iptr)));
|
|
||||||
ab = (int)(255 * (1 - modff(v, &iptr)));
|
|
||||||
iru = uu + 1;
|
|
||||||
irv = vv + 1;
|
|
||||||
|
|
||||||
if (vv >= sh) continue;
|
|
||||||
|
|
||||||
px = *(sbuf + (vv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* right pixel */
|
|
||||||
int px2 = *(sbuf + (vv * sw) + iru);
|
|
||||||
px = INTERPOLATE(px, px2, ar);
|
|
||||||
}
|
|
||||||
/* vertical interpolate */
|
|
||||||
if (irv < sh) {
|
|
||||||
/* bottom pixel */
|
|
||||||
int px2 = *(sbuf + (irv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* bottom right pixel */
|
|
||||||
int px3 = *(sbuf + (irv * sw) + iru);
|
|
||||||
px2 = INTERPOLATE(px2, px3, ar);
|
|
||||||
}
|
|
||||||
px = INTERPOLATE(px, px2, ab);
|
|
||||||
}
|
|
||||||
#ifdef TEXMAP_ADD_MASK
|
|
||||||
*cmp = INTERPOLATE(px, *cmp, opacity);
|
|
||||||
#elif defined(TEXMAP_SUB_MASK)
|
|
||||||
*cmp = ALPHA_BLEND(*cmp, IALPHA(ALPHA_BLEND(px, opacity)));
|
|
||||||
#elif defined(TEXMAP_DIF_MASK)
|
|
||||||
auto src = ALPHA_BLEND(px, opacity);
|
|
||||||
*cmp = ALPHA_BLEND(src, IALPHA(*cmp)) + ALPHA_BLEND(*cmp, IALPHA(src));
|
|
||||||
#endif
|
|
||||||
++cmp;
|
|
||||||
|
|
||||||
//Step UV horizontally
|
|
||||||
u += _dudx;
|
|
||||||
v += _dvdx;
|
|
||||||
//range over?
|
|
||||||
if ((uint32_t)v >= image->h) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Step along both edges
|
|
||||||
_xa += _dxdya;
|
|
||||||
_xb += _dxdyb;
|
|
||||||
_ua += _dudya;
|
|
||||||
_va += _dvdya;
|
|
||||||
|
|
||||||
if (!region && spanIdx >= image->rle->size) break;
|
|
||||||
|
|
||||||
++y;
|
|
||||||
}
|
|
||||||
xa = _xa;
|
|
||||||
xb = _xb;
|
|
||||||
ua = _ua;
|
|
||||||
va = _va;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -41,6 +41,7 @@ static inline void _swap(float& a, float& b, float& tmp)
|
||||||
b = tmp;
|
b = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Careful! Shared resource, No support threading
|
//Careful! Shared resource, No support threading
|
||||||
static float dudx, dvdx;
|
static float dudx, dvdx;
|
||||||
static float dxdya, dxdyb, dudya, dvdya;
|
static float dxdya, dxdyb, dudya, dvdya;
|
||||||
|
@ -69,41 +70,561 @@ static bool _arrange(const SwImage* image, const SwBBox* region, int& yStart, in
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _rasterMaskedPolygonImageSegmentInt(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, AASpans* aaSpans, uint8_t dirFlag)
|
||||||
|
{
|
||||||
|
float _dudx = dudx, _dvdx = dvdx;
|
||||||
|
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
||||||
|
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
||||||
|
auto sbuf = image->buf32;
|
||||||
|
int32_t sw = static_cast<int32_t>(image->stride);
|
||||||
|
int32_t sh = image->h;
|
||||||
|
int32_t x1, x2, ar, ab, iru, irv, px, ay;
|
||||||
|
int32_t vv = 0, uu = 0;
|
||||||
|
int32_t minx = INT32_MAX, maxx = INT32_MIN;
|
||||||
|
float dx, u, v, iptr;
|
||||||
|
auto cbuffer = surface->compositor->image.buf32;
|
||||||
|
SwSpan* span = nullptr; //used only when rle based.
|
||||||
|
|
||||||
|
if (!_arrange(image, region, yStart, yEnd)) return;
|
||||||
|
|
||||||
|
//Clear out of the Polygon vertical ranges
|
||||||
|
auto size = surface->compositor->bbox.max.x - surface->compositor->bbox.min.x;
|
||||||
|
if (dirFlag == 1) { //left top case.
|
||||||
|
for(int y = surface->compositor->bbox.min.y; y < yStart; ++y) {
|
||||||
|
rasterRGBA32(surface->compositor->image.buf32 + y * surface->compositor->image.stride, 0, surface->compositor->bbox.min.x, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dirFlag == 4) { //right bottom case.
|
||||||
|
for(int y = yEnd; y < surface->compositor->bbox.max.y; ++y) {
|
||||||
|
rasterRGBA32(surface->compositor->image.buf32 + y * surface->compositor->image.stride, 0, surface->compositor->bbox.min.x, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Loop through all lines in the segment
|
||||||
|
uint32_t spanIdx = 0;
|
||||||
|
|
||||||
|
if (region) {
|
||||||
|
minx = region->min.x;
|
||||||
|
maxx = region->max.x;
|
||||||
|
} else {
|
||||||
|
span = image->rle->spans;
|
||||||
|
while (span->y < yStart) {
|
||||||
|
++span;
|
||||||
|
++spanIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32_t y = yStart; y < yEnd; ++y) {
|
||||||
|
auto cmp = &cbuffer[y * surface->compositor->image.stride];
|
||||||
|
x1 = (int32_t)_xa;
|
||||||
|
x2 = (int32_t)_xb;
|
||||||
|
|
||||||
|
if (!region) {
|
||||||
|
minx = INT32_MAX;
|
||||||
|
maxx = INT32_MIN;
|
||||||
|
//one single row, could be consisted of multiple spans.
|
||||||
|
while (span->y == y && spanIdx < image->rle->size) {
|
||||||
|
if (minx > span->x) minx = span->x;
|
||||||
|
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
||||||
|
++span;
|
||||||
|
++spanIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x1 < minx) x1 = minx;
|
||||||
|
if (x2 > maxx) x2 = maxx;
|
||||||
|
|
||||||
|
//Anti-Aliasing frames
|
||||||
|
//FIXME: this aa must be applied before masking op
|
||||||
|
ay = y - aaSpans->yStart;
|
||||||
|
if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1;
|
||||||
|
if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2;
|
||||||
|
|
||||||
|
//Range allowed
|
||||||
|
if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) {
|
||||||
|
for (int32_t x = surface->compositor->bbox.min.x; x < surface->compositor->bbox.max.x; ++x) {
|
||||||
|
//Range allowed
|
||||||
|
if (x >= x1 && x < x2) {
|
||||||
|
//Perform subtexel pre-stepping on UV
|
||||||
|
dx = 1 - (_xa - x1);
|
||||||
|
u = _ua + dx * _dudx;
|
||||||
|
v = _va + dx * _dvdx;
|
||||||
|
if ((uint32_t)v >= image->h) {
|
||||||
|
cmp[x] = 0;
|
||||||
|
} else {
|
||||||
|
if (opacity == 255) {
|
||||||
|
uu = (int) u;
|
||||||
|
vv = (int) v;
|
||||||
|
ar = (int)(255 * (1 - modff(u, &iptr)));
|
||||||
|
ab = (int)(255 * (1 - modff(v, &iptr)));
|
||||||
|
iru = uu + 1;
|
||||||
|
irv = vv + 1;
|
||||||
|
|
||||||
|
if (vv >= sh) continue;
|
||||||
|
|
||||||
|
px = *(sbuf + (vv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* right pixel */
|
||||||
|
int px2 = *(sbuf + (vv * sw) + iru);
|
||||||
|
px = INTERPOLATE(px, px2, ar);
|
||||||
|
}
|
||||||
|
/* vertical interpolate */
|
||||||
|
if (irv < sh) {
|
||||||
|
/* bottom pixel */
|
||||||
|
int px2 = *(sbuf + (irv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* bottom right pixel */
|
||||||
|
int px3 = *(sbuf + (irv * sw) + iru);
|
||||||
|
px2 = INTERPOLATE(px2, px3, ar);
|
||||||
|
}
|
||||||
|
px = INTERPOLATE(px, px2, ab);
|
||||||
|
}
|
||||||
|
cmp[x] = ALPHA_BLEND(cmp[x], ALPHA(px));
|
||||||
|
|
||||||
|
//Step UV horizontally
|
||||||
|
u += _dudx;
|
||||||
|
v += _dvdx;
|
||||||
|
} else {
|
||||||
|
uu = (int) u;
|
||||||
|
vv = (int) v;
|
||||||
|
ar = (int)(255 * (1 - modff(u, &iptr)));
|
||||||
|
ab = (int)(255 * (1 - modff(v, &iptr)));
|
||||||
|
iru = uu + 1;
|
||||||
|
irv = vv + 1;
|
||||||
|
|
||||||
|
if (vv >= sh) continue;
|
||||||
|
|
||||||
|
px = *(sbuf + (vv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* right pixel */
|
||||||
|
int px2 = *(sbuf + (vv * sw) + iru);
|
||||||
|
px = INTERPOLATE(px, px2, ar);
|
||||||
|
}
|
||||||
|
/* vertical interpolate */
|
||||||
|
if (irv < sh) {
|
||||||
|
/* bottom pixel */
|
||||||
|
int px2 = *(sbuf + (irv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* bottom right pixel */
|
||||||
|
int px3 = *(sbuf + (irv * sw) + iru);
|
||||||
|
px2 = INTERPOLATE(px2, px3, ar);
|
||||||
|
}
|
||||||
|
px = INTERPOLATE(px, px2, ab);
|
||||||
|
}
|
||||||
|
cmp[x] = ALPHA_BLEND(cmp[x], MULTIPLY(ALPHA(px), opacity));
|
||||||
|
|
||||||
|
//Step UV horizontally
|
||||||
|
u += _dudx;
|
||||||
|
v += _dvdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Clear out of polygon horizontal range
|
||||||
|
if (x < x1 && (dirFlag == 1 || dirFlag == 2)) cmp[x] = 0;
|
||||||
|
else if (x >= x2 && (dirFlag == 3 || dirFlag == 4)) cmp[x] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Step along both edges
|
||||||
|
_xa += _dxdya;
|
||||||
|
_xb += _dxdyb;
|
||||||
|
_ua += _dudya;
|
||||||
|
_va += _dvdya;
|
||||||
|
}
|
||||||
|
xa = _xa;
|
||||||
|
xb = _xb;
|
||||||
|
ua = _ua;
|
||||||
|
va = _va;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename maskOp, typename amaskOp>
|
||||||
|
static void _rasterMaskedPolygonImageSegmentDup(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, AASpans* aaSpans)
|
||||||
|
{
|
||||||
|
float _dudx = dudx, _dvdx = dvdx;
|
||||||
|
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
||||||
|
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
||||||
|
auto sbuf = image->buf32;
|
||||||
|
int32_t sw = static_cast<int32_t>(image->stride);
|
||||||
|
int32_t sh = image->h;
|
||||||
|
int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay;
|
||||||
|
int32_t vv = 0, uu = 0;
|
||||||
|
int32_t minx = INT32_MAX, maxx = INT32_MIN;
|
||||||
|
float dx, u, v, iptr;
|
||||||
|
SwSpan* span = nullptr; //used only when rle based.
|
||||||
|
|
||||||
|
if (!_arrange(image, region, yStart, yEnd)) return;
|
||||||
|
|
||||||
|
//Loop through all lines in the segment
|
||||||
|
uint32_t spanIdx = 0;
|
||||||
|
|
||||||
|
if (region) {
|
||||||
|
minx = region->min.x;
|
||||||
|
maxx = region->max.x;
|
||||||
|
} else {
|
||||||
|
span = image->rle->spans;
|
||||||
|
while (span->y < yStart) {
|
||||||
|
++span;
|
||||||
|
++spanIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
y = yStart;
|
||||||
|
|
||||||
|
while (y < yEnd) {
|
||||||
|
x1 = (int32_t)_xa;
|
||||||
|
x2 = (int32_t)_xb;
|
||||||
|
|
||||||
|
if (!region) {
|
||||||
|
minx = INT32_MAX;
|
||||||
|
maxx = INT32_MIN;
|
||||||
|
//one single row, could be consisted of multiple spans.
|
||||||
|
while (span->y == y && spanIdx < image->rle->size) {
|
||||||
|
if (minx > span->x) minx = span->x;
|
||||||
|
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
||||||
|
++span;
|
||||||
|
++spanIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x1 < minx) x1 = minx;
|
||||||
|
if (x2 > maxx) x2 = maxx;
|
||||||
|
|
||||||
|
//Anti-Aliasing frames
|
||||||
|
ay = y - aaSpans->yStart;
|
||||||
|
if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1;
|
||||||
|
if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2;
|
||||||
|
|
||||||
|
//Range allowed
|
||||||
|
if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) {
|
||||||
|
|
||||||
|
//Perform subtexel pre-stepping on UV
|
||||||
|
dx = 1 - (_xa - x1);
|
||||||
|
u = _ua + dx * _dudx;
|
||||||
|
v = _va + dx * _dvdx;
|
||||||
|
|
||||||
|
x = x1;
|
||||||
|
|
||||||
|
auto cmp = &surface->compositor->image.buf32[y * surface->compositor->image.stride + x1];
|
||||||
|
|
||||||
|
if (opacity == 255) {
|
||||||
|
//Draw horizontal line
|
||||||
|
while (x++ < x2) {
|
||||||
|
uu = (int) u;
|
||||||
|
vv = (int) v;
|
||||||
|
|
||||||
|
ar = (int)(255 * (1 - modff(u, &iptr)));
|
||||||
|
ab = (int)(255 * (1 - modff(v, &iptr)));
|
||||||
|
iru = uu + 1;
|
||||||
|
irv = vv + 1;
|
||||||
|
|
||||||
|
if (vv >= sh) continue;
|
||||||
|
|
||||||
|
px = *(sbuf + (vv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* right pixel */
|
||||||
|
int px2 = *(sbuf + (vv * sw) + iru);
|
||||||
|
px = INTERPOLATE(px, px2, ar);
|
||||||
|
}
|
||||||
|
/* vertical interpolate */
|
||||||
|
if (irv < sh) {
|
||||||
|
/* bottom pixel */
|
||||||
|
int px2 = *(sbuf + (irv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* bottom right pixel */
|
||||||
|
int px3 = *(sbuf + (irv * sw) + iru);
|
||||||
|
px2 = INTERPOLATE(px2, px3, ar);
|
||||||
|
}
|
||||||
|
px = INTERPOLATE(px, px2, ab);
|
||||||
|
}
|
||||||
|
*cmp = maskOp()(px, *cmp, IALPHA(px));
|
||||||
|
++cmp;
|
||||||
|
|
||||||
|
//Step UV horizontally
|
||||||
|
u += _dudx;
|
||||||
|
v += _dvdx;
|
||||||
|
//range over?
|
||||||
|
if ((uint32_t)v >= image->h) break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Draw horizontal line
|
||||||
|
while (x++ < x2) {
|
||||||
|
uu = (int) u;
|
||||||
|
vv = (int) v;
|
||||||
|
|
||||||
|
ar = (int)(255 * (1 - modff(u, &iptr)));
|
||||||
|
ab = (int)(255 * (1 - modff(v, &iptr)));
|
||||||
|
iru = uu + 1;
|
||||||
|
irv = vv + 1;
|
||||||
|
|
||||||
|
if (vv >= sh) continue;
|
||||||
|
|
||||||
|
px = *(sbuf + (vv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* right pixel */
|
||||||
|
int px2 = *(sbuf + (vv * sw) + iru);
|
||||||
|
px = INTERPOLATE(px, px2, ar);
|
||||||
|
}
|
||||||
|
/* vertical interpolate */
|
||||||
|
if (irv < sh) {
|
||||||
|
/* bottom pixel */
|
||||||
|
int px2 = *(sbuf + (irv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* bottom right pixel */
|
||||||
|
int px3 = *(sbuf + (irv * sw) + iru);
|
||||||
|
px2 = INTERPOLATE(px2, px3, ar);
|
||||||
|
}
|
||||||
|
px = INTERPOLATE(px, px2, ab);
|
||||||
|
}
|
||||||
|
*cmp = amaskOp()(px, *cmp, opacity);
|
||||||
|
++cmp;
|
||||||
|
|
||||||
|
//Step UV horizontally
|
||||||
|
u += _dudx;
|
||||||
|
v += _dvdx;
|
||||||
|
//range over?
|
||||||
|
if ((uint32_t)v >= image->h) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Step along both edges
|
||||||
|
_xa += _dxdya;
|
||||||
|
_xb += _dxdyb;
|
||||||
|
_ua += _dudya;
|
||||||
|
_va += _dvdya;
|
||||||
|
|
||||||
|
if (!region && spanIdx >= image->rle->size) break;
|
||||||
|
|
||||||
|
++y;
|
||||||
|
}
|
||||||
|
xa = _xa;
|
||||||
|
xb = _xb;
|
||||||
|
ua = _ua;
|
||||||
|
va = _va;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, AASpans* aaSpans, uint8_t dirFlag = 0)
|
static void _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, AASpans* aaSpans, uint8_t dirFlag = 0)
|
||||||
{
|
{
|
||||||
auto method = surface->compositor->method;
|
auto method = surface->compositor->method;
|
||||||
|
|
||||||
if (method == CompositeMethod::AddMask) {
|
if (method == CompositeMethod::AddMask) _rasterMaskedPolygonImageSegmentDup<AddMaskOp, AddMaskAOp>(surface, image, region, yStart, yEnd, opacity, aaSpans);
|
||||||
#define TEXMAP_ADD_MASK
|
else if (method == CompositeMethod::SubtractMask) _rasterMaskedPolygonImageSegmentDup<SubMaskOp, SubMaskAOp>(surface, image, region, yStart, yEnd, opacity, aaSpans);
|
||||||
#include "tvgSwRasterMaskedTexmapInternal.h"
|
else if (method == CompositeMethod::DifferenceMask) _rasterMaskedPolygonImageSegmentDup<DifMaskOp, DifMaskAOp>(surface, image, region, yStart, yEnd, opacity, aaSpans);
|
||||||
#undef TEXMAP_ADD_MASK
|
else if (method == CompositeMethod::IntersectMask) _rasterMaskedPolygonImageSegmentInt(surface, image, region, yStart, yEnd, opacity, aaSpans, dirFlag);
|
||||||
} else if (method == CompositeMethod::SubtractMask) {
|
}
|
||||||
#define TEXMAP_SUB_MASK
|
|
||||||
#include "tvgSwRasterMaskedTexmapInternal.h"
|
|
||||||
#undef TEXMAP_SUB_MASK
|
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, AASpans* aaSpans, bool matting)
|
||||||
} else if (method == CompositeMethod::IntersectMask) {
|
{
|
||||||
#define TEXMAP_INT_MASK
|
float _dudx = dudx, _dvdx = dvdx;
|
||||||
#include "tvgSwRasterMaskedTexmapInternal.h"
|
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
||||||
#undef TEXMAP_INT_MASK
|
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
||||||
} else if (method == CompositeMethod::DifferenceMask) {
|
auto sbuf = image->buf32;
|
||||||
#define TEXMAP_DIF_MASK
|
auto dbuf = surface->buf32;
|
||||||
#include "tvgSwRasterMaskedTexmapInternal.h"
|
int32_t sw = static_cast<int32_t>(image->stride);
|
||||||
#undef TEXMAP_DIF_MASK
|
int32_t sh = image->h;
|
||||||
|
int32_t dw = surface->stride;
|
||||||
|
int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay;
|
||||||
|
int32_t vv = 0, uu = 0;
|
||||||
|
int32_t minx = INT32_MAX, maxx = INT32_MIN;
|
||||||
|
float dx, u, v, iptr;
|
||||||
|
uint32_t* buf;
|
||||||
|
SwSpan* span = nullptr; //used only when rle based.
|
||||||
|
|
||||||
|
//for matting(composition)
|
||||||
|
auto csize = matting ? surface->compositor->image.channelSize: 0;
|
||||||
|
auto alpha = matting ? surface->blender.alpha(surface->compositor->method) : nullptr;
|
||||||
|
uint8_t* cmp = nullptr;
|
||||||
|
|
||||||
|
if (!_arrange(image, region, yStart, yEnd)) return;
|
||||||
|
|
||||||
|
//Loop through all lines in the segment
|
||||||
|
uint32_t spanIdx = 0;
|
||||||
|
|
||||||
|
if (region) {
|
||||||
|
minx = region->min.x;
|
||||||
|
maxx = region->max.x;
|
||||||
|
} else {
|
||||||
|
span = image->rle->spans;
|
||||||
|
while (span->y < yStart) {
|
||||||
|
++span;
|
||||||
|
++spanIdx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
y = yStart;
|
||||||
|
|
||||||
static void _rasterMattedPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, AASpans* aaSpans)
|
while (y < yEnd) {
|
||||||
{
|
x1 = (int32_t)_xa;
|
||||||
#define TEXMAP_MATTING
|
x2 = (int32_t)_xb;
|
||||||
#include "tvgSwRasterTexmapInternal.h"
|
|
||||||
#undef TEXMAP_MATTING
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!region) {
|
||||||
|
minx = INT32_MAX;
|
||||||
|
maxx = INT32_MIN;
|
||||||
|
//one single row, could be consisted of multiple spans.
|
||||||
|
while (span->y == y && spanIdx < image->rle->size) {
|
||||||
|
if (minx > span->x) minx = span->x;
|
||||||
|
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
||||||
|
++span;
|
||||||
|
++spanIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x1 < minx) x1 = minx;
|
||||||
|
if (x2 > maxx) x2 = maxx;
|
||||||
|
|
||||||
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, AASpans* aaSpans)
|
//Anti-Aliasing frames
|
||||||
{
|
ay = y - aaSpans->yStart;
|
||||||
#include "tvgSwRasterTexmapInternal.h"
|
if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1;
|
||||||
|
if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2;
|
||||||
|
|
||||||
|
//Range allowed
|
||||||
|
if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) {
|
||||||
|
|
||||||
|
//Perform subtexel pre-stepping on UV
|
||||||
|
dx = 1 - (_xa - x1);
|
||||||
|
u = _ua + dx * _dudx;
|
||||||
|
v = _va + dx * _dvdx;
|
||||||
|
|
||||||
|
buf = dbuf + ((y * dw) + x1);
|
||||||
|
|
||||||
|
x = x1;
|
||||||
|
|
||||||
|
if (matting) cmp = &surface->compositor->image.buf8[(y * surface->compositor->image.stride + x1) * csize];
|
||||||
|
|
||||||
|
if (opacity == 255) {
|
||||||
|
//Draw horizontal line
|
||||||
|
while (x++ < x2) {
|
||||||
|
uu = (int) u;
|
||||||
|
vv = (int) v;
|
||||||
|
|
||||||
|
ar = (int)(255 * (1 - modff(u, &iptr)));
|
||||||
|
ab = (int)(255 * (1 - modff(v, &iptr)));
|
||||||
|
iru = uu + 1;
|
||||||
|
irv = vv + 1;
|
||||||
|
|
||||||
|
if (vv >= sh) continue;
|
||||||
|
|
||||||
|
px = *(sbuf + (vv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* right pixel */
|
||||||
|
int px2 = *(sbuf + (vv * sw) + iru);
|
||||||
|
px = INTERPOLATE(px, px2, ar);
|
||||||
|
}
|
||||||
|
/* vertical interpolate */
|
||||||
|
if (irv < sh) {
|
||||||
|
/* bottom pixel */
|
||||||
|
int px2 = *(sbuf + (irv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* bottom right pixel */
|
||||||
|
int px3 = *(sbuf + (irv * sw) + iru);
|
||||||
|
px2 = INTERPOLATE(px2, px3, ar);
|
||||||
|
}
|
||||||
|
px = INTERPOLATE(px, px2, ab);
|
||||||
|
}
|
||||||
|
uint32_t src;
|
||||||
|
if (matting) {
|
||||||
|
src = ALPHA_BLEND(px, alpha(cmp));
|
||||||
|
cmp += csize;
|
||||||
|
} else {
|
||||||
|
src = px;
|
||||||
|
}
|
||||||
|
*buf = src + ALPHA_BLEND(*buf, IALPHA(src));
|
||||||
|
++buf;
|
||||||
|
|
||||||
|
//Step UV horizontally
|
||||||
|
u += _dudx;
|
||||||
|
v += _dvdx;
|
||||||
|
//range over?
|
||||||
|
if ((uint32_t)v >= image->h) break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Draw horizontal line
|
||||||
|
while (x++ < x2) {
|
||||||
|
uu = (int) u;
|
||||||
|
vv = (int) v;
|
||||||
|
|
||||||
|
ar = (int)(255 * (1 - modff(u, &iptr)));
|
||||||
|
ab = (int)(255 * (1 - modff(v, &iptr)));
|
||||||
|
iru = uu + 1;
|
||||||
|
irv = vv + 1;
|
||||||
|
|
||||||
|
if (vv >= sh) continue;
|
||||||
|
|
||||||
|
px = *(sbuf + (vv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* right pixel */
|
||||||
|
int px2 = *(sbuf + (vv * sw) + iru);
|
||||||
|
px = INTERPOLATE(px, px2, ar);
|
||||||
|
}
|
||||||
|
/* vertical interpolate */
|
||||||
|
if (irv < sh) {
|
||||||
|
/* bottom pixel */
|
||||||
|
int px2 = *(sbuf + (irv * sw) + uu);
|
||||||
|
|
||||||
|
/* horizontal interpolate */
|
||||||
|
if (iru < sw) {
|
||||||
|
/* bottom right pixel */
|
||||||
|
int px3 = *(sbuf + (irv * sw) + iru);
|
||||||
|
px2 = INTERPOLATE(px2, px3, ar);
|
||||||
|
}
|
||||||
|
px = INTERPOLATE(px, px2, ab);
|
||||||
|
}
|
||||||
|
uint32_t src;
|
||||||
|
if (matting) {
|
||||||
|
src = ALPHA_BLEND(px, MULTIPLY(opacity, alpha(cmp)));
|
||||||
|
cmp += csize;
|
||||||
|
} else {
|
||||||
|
src = ALPHA_BLEND(px, opacity);
|
||||||
|
}
|
||||||
|
*buf = src + ALPHA_BLEND(*buf, IALPHA(src));
|
||||||
|
++buf;
|
||||||
|
|
||||||
|
//Step UV horizontally
|
||||||
|
u += _dudx;
|
||||||
|
v += _dvdx;
|
||||||
|
//range over?
|
||||||
|
if ((uint32_t)v >= image->h) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Step along both edges
|
||||||
|
_xa += _dxdya;
|
||||||
|
_xb += _dxdyb;
|
||||||
|
_ua += _dudya;
|
||||||
|
_va += _dvdya;
|
||||||
|
|
||||||
|
if (!region && spanIdx >= image->rle->size) break;
|
||||||
|
|
||||||
|
++y;
|
||||||
|
}
|
||||||
|
xa = _xa;
|
||||||
|
xb = _xb;
|
||||||
|
ua = _ua;
|
||||||
|
va = _va;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -198,9 +719,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
xb = x[0] + dy * dxdyb + (off_y * dxdyb);
|
xb = x[0] + dy * dxdyb + (off_y * dxdyb);
|
||||||
|
|
||||||
if (compositing) {
|
if (compositing) {
|
||||||
if (_matting(surface)) _rasterMattedPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans, true);
|
||||||
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans, 1);
|
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans, 1);
|
||||||
} else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
} else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans, false);
|
||||||
|
|
||||||
upper = true;
|
upper = true;
|
||||||
}
|
}
|
||||||
|
@ -216,9 +737,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
dxdyb = dxdy[2];
|
dxdyb = dxdy[2];
|
||||||
xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb);
|
xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb);
|
||||||
if (compositing) {
|
if (compositing) {
|
||||||
if (_matting(surface)) _rasterMattedPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans, true);
|
||||||
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans, 2);
|
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans, 2);
|
||||||
} else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
} else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans, false);
|
||||||
}
|
}
|
||||||
//Longer edge is on the right side
|
//Longer edge is on the right side
|
||||||
} else {
|
} else {
|
||||||
|
@ -242,9 +763,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
va = v[0] + dy * dvdya + (off_y * dvdya);
|
va = v[0] + dy * dvdya + (off_y * dvdya);
|
||||||
|
|
||||||
if (compositing) {
|
if (compositing) {
|
||||||
if (_matting(surface)) _rasterMattedPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans, true);
|
||||||
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans, 3);
|
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans, 3);
|
||||||
} else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
} else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans, false);
|
||||||
|
|
||||||
upper = true;
|
upper = true;
|
||||||
}
|
}
|
||||||
|
@ -263,9 +784,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
va = v[1] + dy * dvdya + (off_y * dvdya);
|
va = v[1] + dy * dvdya + (off_y * dvdya);
|
||||||
|
|
||||||
if (compositing) {
|
if (compositing) {
|
||||||
if (_matting(surface)) _rasterMattedPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans, true);
|
||||||
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans, 4);
|
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans, 4);
|
||||||
} else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
} else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,214 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
|
||||||
float _dudx = dudx, _dvdx = dvdx;
|
|
||||||
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
|
||||||
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
|
||||||
auto sbuf = image->buf32;
|
|
||||||
auto dbuf = surface->buf32;
|
|
||||||
int32_t sw = static_cast<int32_t>(image->stride);
|
|
||||||
int32_t sh = image->h;
|
|
||||||
int32_t dw = surface->stride;
|
|
||||||
int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay;
|
|
||||||
int32_t vv = 0, uu = 0;
|
|
||||||
int32_t minx = INT32_MAX, maxx = INT32_MIN;
|
|
||||||
float dx, u, v, iptr;
|
|
||||||
uint32_t* buf;
|
|
||||||
SwSpan* span = nullptr; //used only when rle based.
|
|
||||||
|
|
||||||
#ifdef TEXMAP_MATTING
|
|
||||||
auto csize = surface->compositor->image.channelSize;
|
|
||||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!_arrange(image, region, yStart, yEnd)) return;
|
|
||||||
|
|
||||||
//Loop through all lines in the segment
|
|
||||||
uint32_t spanIdx = 0;
|
|
||||||
|
|
||||||
if (region) {
|
|
||||||
minx = region->min.x;
|
|
||||||
maxx = region->max.x;
|
|
||||||
} else {
|
|
||||||
span = image->rle->spans;
|
|
||||||
while (span->y < yStart) {
|
|
||||||
++span;
|
|
||||||
++spanIdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
y = yStart;
|
|
||||||
|
|
||||||
while (y < yEnd) {
|
|
||||||
x1 = (int32_t)_xa;
|
|
||||||
x2 = (int32_t)_xb;
|
|
||||||
|
|
||||||
if (!region) {
|
|
||||||
minx = INT32_MAX;
|
|
||||||
maxx = INT32_MIN;
|
|
||||||
//one single row, could be consisted of multiple spans.
|
|
||||||
while (span->y == y && spanIdx < image->rle->size) {
|
|
||||||
if (minx > span->x) minx = span->x;
|
|
||||||
if (maxx < span->x + span->len) maxx = span->x + span->len;
|
|
||||||
++span;
|
|
||||||
++spanIdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (x1 < minx) x1 = minx;
|
|
||||||
if (x2 > maxx) x2 = maxx;
|
|
||||||
|
|
||||||
//Anti-Aliasing frames
|
|
||||||
ay = y - aaSpans->yStart;
|
|
||||||
if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1;
|
|
||||||
if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2;
|
|
||||||
|
|
||||||
//Range allowed
|
|
||||||
if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) {
|
|
||||||
|
|
||||||
//Perform subtexel pre-stepping on UV
|
|
||||||
dx = 1 - (_xa - x1);
|
|
||||||
u = _ua + dx * _dudx;
|
|
||||||
v = _va + dx * _dvdx;
|
|
||||||
|
|
||||||
buf = dbuf + ((y * dw) + x1);
|
|
||||||
|
|
||||||
x = x1;
|
|
||||||
|
|
||||||
#ifdef TEXMAP_MATTING
|
|
||||||
auto cmp = &surface->compositor->image.buf8[(y * surface->compositor->image.stride + x1) * csize];
|
|
||||||
#endif
|
|
||||||
if (opacity == 255) {
|
|
||||||
//Draw horizontal line
|
|
||||||
while (x++ < x2) {
|
|
||||||
uu = (int) u;
|
|
||||||
vv = (int) v;
|
|
||||||
|
|
||||||
ar = (int)(255 * (1 - modff(u, &iptr)));
|
|
||||||
ab = (int)(255 * (1 - modff(v, &iptr)));
|
|
||||||
iru = uu + 1;
|
|
||||||
irv = vv + 1;
|
|
||||||
|
|
||||||
if (vv >= sh) continue;
|
|
||||||
|
|
||||||
px = *(sbuf + (vv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* right pixel */
|
|
||||||
int px2 = *(sbuf + (vv * sw) + iru);
|
|
||||||
px = INTERPOLATE(px, px2, ar);
|
|
||||||
}
|
|
||||||
/* vertical interpolate */
|
|
||||||
if (irv < sh) {
|
|
||||||
/* bottom pixel */
|
|
||||||
int px2 = *(sbuf + (irv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* bottom right pixel */
|
|
||||||
int px3 = *(sbuf + (irv * sw) + iru);
|
|
||||||
px2 = INTERPOLATE(px2, px3, ar);
|
|
||||||
}
|
|
||||||
px = INTERPOLATE(px, px2, ab);
|
|
||||||
}
|
|
||||||
#ifdef TEXMAP_MATTING
|
|
||||||
auto src = ALPHA_BLEND(px, alpha(cmp));
|
|
||||||
cmp += csize;
|
|
||||||
#else
|
|
||||||
auto src = px;
|
|
||||||
#endif
|
|
||||||
*buf = src + ALPHA_BLEND(*buf, IALPHA(src));
|
|
||||||
++buf;
|
|
||||||
|
|
||||||
//Step UV horizontally
|
|
||||||
u += _dudx;
|
|
||||||
v += _dvdx;
|
|
||||||
//range over?
|
|
||||||
if ((uint32_t)v >= image->h) break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Draw horizontal line
|
|
||||||
while (x++ < x2) {
|
|
||||||
uu = (int) u;
|
|
||||||
vv = (int) v;
|
|
||||||
|
|
||||||
ar = (int)(255 * (1 - modff(u, &iptr)));
|
|
||||||
ab = (int)(255 * (1 - modff(v, &iptr)));
|
|
||||||
iru = uu + 1;
|
|
||||||
irv = vv + 1;
|
|
||||||
|
|
||||||
if (vv >= sh) continue;
|
|
||||||
|
|
||||||
px = *(sbuf + (vv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* right pixel */
|
|
||||||
int px2 = *(sbuf + (vv * sw) + iru);
|
|
||||||
px = INTERPOLATE(px, px2, ar);
|
|
||||||
}
|
|
||||||
/* vertical interpolate */
|
|
||||||
if (irv < sh) {
|
|
||||||
/* bottom pixel */
|
|
||||||
int px2 = *(sbuf + (irv * sw) + uu);
|
|
||||||
|
|
||||||
/* horizontal interpolate */
|
|
||||||
if (iru < sw) {
|
|
||||||
/* bottom right pixel */
|
|
||||||
int px3 = *(sbuf + (irv * sw) + iru);
|
|
||||||
px2 = INTERPOLATE(px2, px3, ar);
|
|
||||||
}
|
|
||||||
px = INTERPOLATE(px, px2, ab);
|
|
||||||
}
|
|
||||||
#ifdef TEXMAP_MATTING
|
|
||||||
auto src = ALPHA_BLEND(px, MULTIPLY(opacity, alpha(cmp)));
|
|
||||||
cmp += csize;
|
|
||||||
#else
|
|
||||||
auto src = ALPHA_BLEND(px, opacity);
|
|
||||||
#endif
|
|
||||||
*buf = src + ALPHA_BLEND(*buf, IALPHA(src));
|
|
||||||
++buf;
|
|
||||||
|
|
||||||
//Step UV horizontally
|
|
||||||
u += _dudx;
|
|
||||||
v += _dvdx;
|
|
||||||
//range over?
|
|
||||||
if ((uint32_t)v >= image->h) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Step along both edges
|
|
||||||
_xa += _dxdya;
|
|
||||||
_xb += _dxdyb;
|
|
||||||
_ua += _dudya;
|
|
||||||
_va += _dvdya;
|
|
||||||
|
|
||||||
if (!region && spanIdx >= image->rle->size) break;
|
|
||||||
|
|
||||||
++y;
|
|
||||||
}
|
|
||||||
xa = _xa;
|
|
||||||
xb = _xb;
|
|
||||||
ua = _ua;
|
|
||||||
va = _va;
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue