2 * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 float _dudx = dudx, _dvdx = dvdx;
25 float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
26 float _xa = xa, _xb = xb, _ua = ua, _va = va;
27 auto sbuf = image->data;
28 auto dbuf = surface->buffer;
29 int32_t sw = static_cast<int32_t>(image->stride);
30 int32_t sh = image->h;
31 int32_t dw = surface->stride;
32 int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay;
33 int32_t vv = 0, uu = 0;
34 int32_t minx = INT32_MAX, maxx = INT32_MIN;
37 SwSpan* span = nullptr; //used only when rle based.
43 if (!_arrange(image, region, yStart, yEnd)) return;
45 //Loop through all lines in the segment
52 span = image->rle->spans;
53 while (span->y < yStart) {
68 //one single row, could be consisted of multiple spans.
69 while (span->y == y && spanIdx < image->rle->size) {
70 if (minx > span->x) minx = span->x;
71 if (maxx < span->x + span->len) maxx = span->x + span->len;
76 if (x1 < minx) x1 = minx;
77 if (x2 > maxx) x2 = maxx;
79 //Anti-Aliasing frames
80 ay = y - aaSpans->yStart;
81 if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1;
82 if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2;
85 if ((x2 - x1) < 1 || (x1 >= maxx) || (x2 <= minx)) goto next;
87 //Perform subtexel pre-stepping on UV
92 buf = dbuf + ((y * dw) + x1);
97 cmp = &surface->compositor->image.data[y * surface->compositor->image.stride + x1];
99 //Draw horizontal line
104 ar = (int)(255 * (1 - modff(u, &iptr)));
105 ab = (int)(255 * (1 - modff(v, &iptr)));
109 if (vv >= sh) continue;
111 px = *(sbuf + (vv * sw) + uu);
113 /* horizontal interpolate */
116 int px2 = *(sbuf + (vv * sw) + iru);
117 px = INTERPOLATE(ar, px, px2);
119 /* vertical interpolate */
122 int px2 = *(sbuf + (irv * sw) + uu);
124 /* horizontal interpolate */
126 /* bottom right pixel */
127 int px3 = *(sbuf + (irv * sw) + iru);
128 px2 = INTERPOLATE(ar, px2, px3);
130 px = INTERPOLATE(ab, px, px2);
132 #if defined(TEXMAP_MASKING) && defined(TEXMAP_TRANSLUCENT)
133 auto src = ALPHA_BLEND(px, _multiplyAlpha(opacity, blendMethod(*cmp)));
134 #elif defined(TEXMAP_MASKING)
135 auto src = ALPHA_BLEND(px, blendMethod(*cmp));
136 #elif defined(TEXMAP_TRANSLUCENT)
137 auto src = ALPHA_BLEND(px, opacity);
141 *buf = src + ALPHA_BLEND(*buf, _ialpha(src));
143 #ifdef TEXMAP_MASKING
146 //Step UV horizontally
150 if ((uint32_t)v >= image->h) break;
153 //Step along both edges
159 if (!region && spanIdx >= image->rle->size) break;