1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16/**
17* @brief Defines scanline renderer
18* @since 1.0
19* @version 1.0
20*/
21
22#include "render_scanline.h"
23
24namespace OHOS {
25void RenderScanlinesAntiAliasSolid(RasterizerScanlineAntialias& raster, GeometryScanline& scanline,
26                                   RenderBase& renBase, const Rgba8T& color)
27{
28    if (!raster.RewindScanlines()) {
29        return;
30    }
31    scanline.Reset(raster.GetMinX(), raster.GetMaxX());
32    while (raster.SweepScanline(scanline)) {
33        int32_t y = scanline.GetYLevel();
34        uint32_t numSpans = scanline.NumSpans();
35        GeometryScanline::ConstIterator span = scanline.Begin();
36        while (true) {
37            int32_t x = span->x;
38            if (span->spanLength > 0) {
39                renBase.BlendSolidHSpan(x, y, static_cast<uint32_t>(span->spanLength),
40                                        color, span->covers);
41            } else {
42                renBase.BlendHLine(x, y, static_cast<uint32_t>(x - span->spanLength - 1),
43                                   color, *(span->covers));
44            }
45            if (--numSpans == 0) {
46                break;
47            }
48            ++span;
49        }
50    }
51}
52
53void RenderScanlinesAntiAlias(RasterizerScanlineAntialias& raster, GeometryScanline& scanline,
54                              RenderBase& renBase, FillBase& alloc, SpanBase& spanGen)
55{
56    if (!raster.RewindScanlines()) {
57        return;
58    }
59    scanline.Reset(raster.GetMinX(), raster.GetMaxX());
60    spanGen.Prepare(); // Segment generator preparation
61    alloc.Resize(raster.GetMaxX()-raster.GetMinX());
62    while (raster.SweepScanline(scanline)) {
63        int32_t y = scanline.GetYLevel();
64        uint32_t numSpans = scanline.NumSpans();
65        GeometryScanline::ConstIterator span = scanline.Begin();
66        while (true) {
67            int32_t x = span->x;
68            int32_t len = span->spanLength;
69            const uint8_t* covers = span->covers;
70
71            if (len < 0) {
72                len = -len;
73            }
74
75            spanGen.Generate(alloc.GetSpanPtr(), x, y, len);
76            renBase.BlendColorHSpan(x, y, len, alloc.GetSpanPtr(),
77                                    (span->spanLength < 0) ? 0 : covers, *covers);
78
79            if (--numSpans == 0) {
80                break;
81            }
82            ++span;
83        }
84    }
85}
86
87void BlendScanLine(GlobalCompositeOperation op, RasterizerScanlineAntialias& raster1,
88                   RasterizerScanlineAntialias& raster2, GeometryScanline& sl1, GeometryScanline& sl2,
89                   RenderBase& renBase, FillBase& alloc, SpanBase& spanGen1, SpanBase& spanGen2)
90{
91    switch (op) {
92        case SOURCE_OVER:
93            BlendSourceOver(raster2, raster1, sl2, sl1, renBase, alloc, spanGen2, spanGen1);
94            break;
95        case SOURCE_ATOP:
96            BlendSourceAtop(raster1, raster2, sl1, sl2, renBase, alloc, spanGen1, spanGen2);
97            break;
98        case SOURCE_IN:
99            BlendSourceIn(raster1, raster2, sl1, sl2, renBase, alloc, spanGen1);
100            break;
101        case SOURCE_OUT:
102            BlendSourceOut(raster1, raster2, sl1, sl2, renBase, alloc, spanGen1);
103            break;
104        case DESTINATION_OVER:
105            BlendSourceOver(raster1, raster2, sl1, sl2, renBase, alloc, spanGen1, spanGen2);
106            break;
107        case DESTINATION_ATOP:
108            BlendSourceAtop(raster2, raster1, sl2, sl1, renBase, alloc, spanGen2, spanGen1);
109            break;
110        case DESTINATION_IN:
111            BlendSourceIn(raster2, raster1, sl2, sl1, renBase, alloc, spanGen2);
112            break;
113        case DESTINATION_OUT:
114            BlendSourceOut(raster2, raster1, sl2, sl1, renBase, alloc, spanGen2);
115            break;
116        case LIGHTER:
117            BlendLIGHTER(raster1, raster2, sl1, sl2, renBase, alloc, spanGen1, spanGen2);
118            break;
119        case COPY:
120            RenderScanlinesAntiAlias(raster1, sl1, renBase, alloc, spanGen1);
121            break;
122        case XOR:
123            BlendXOR(raster1, raster2, sl1, sl2, renBase, alloc, spanGen1, spanGen2);
124            break;
125        default:
126            break;
127    }
128}
129
130void BlendSourceAtop(RasterizerScanlineAntialias& raster1, RasterizerScanlineAntialias& raster2,
131                     GeometryScanline& scanline1, GeometryScanline& scanline2, RenderBase& renBase,
132                     FillBase& alloc, SpanBase& spanGen1, SpanBase& spanGen2)
133{
134    if ((!raster1.RewindScanlines()) || (!raster2.RewindScanlines())) {
135        return;
136    }
137    scanline1.Reset(raster1.GetMinX(), raster1.GetMaxX());
138    scanline2.Reset(raster2.GetMinX(), raster2.GetMaxX());
139    int16_t allocMinx = (raster1.GetMinX() > raster2.GetMinX()) ? raster2.GetMinX() : raster1.GetMinX();
140    int16_t allocMaxX = (raster1.GetMaxX() > raster2.GetMaxX()) ? raster1.GetMaxX() : raster2.GetMaxX();
141    alloc.Resize(allocMaxX - allocMinx);
142    int32_t y1 = 0;
143    if (raster1.SweepScanline(scanline1)) {
144        y1 = scanline1.GetYLevel();
145        spanGen1.Prepare(); // Segment generator preparation
146    }
147    while (raster2.SweepScanline(scanline2)) {
148        spanGen2.Prepare();
149        int32_t y2 = scanline2.GetYLevel();
150        uint32_t numSpans2 = scanline2.NumSpans();
151        GeometryScanline::ConstIterator span2 = scanline2.Begin();
152        GeometryScanline::ConstIterator span1 = scanline1.Begin();
153        if (y2 > y1) {
154            while (raster1.SweepScanline(scanline1)) {
155                y1 = scanline1.GetYLevel();
156                if (y1 == y2) {
157                    span1 = scanline1.Begin();
158                    break;
159                }
160            }
161        }
162        while (true) {
163            int32_t x2 = span2->x;
164            if (y1 == y2) {
165                int32_t x1 = span1->x;
166                if (span2->spanLength > 0) {
167                    if (span1->spanLength > 0) {
168                        spanGen2.Generate(alloc.GetSpanPtr(), x2, y2, span2->spanLength);
169                        renBase.BlendColorHSpan(x2, y2, (uint32_t)span2->spanLength,
170                                                alloc.GetSpanPtr(), span2->covers);
171                        if ((x1 <= x2) && ((x2 + span2->spanLength) < (x1 + span1->spanLength))) {
172                            spanGen1.Generate(alloc.GetSpanPtr(), x2, y2, span2->spanLength);
173                            renBase.BlendColorHSpan(x2, y2, (uint32_t)span2->spanLength,
174                                                    alloc.GetSpanPtr(),
175                                                    span2->covers);
176                        } else if ((x1 >= x2) && ((x1 + span1->spanLength) <= (x2 + span2->spanLength))) {
177                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span1->spanLength);
178                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span1->spanLength,
179                                                    alloc.GetSpanPtr(),
180                                                    span1->covers);
181                        } else if ((x1 > x2) && (x1 < (x2 + span2->spanLength)) &&
182                                   ((x1 + span1->spanLength) >= (x2 + span2->spanLength))) {
183                            GeometryScanline scanline3;
184                            CalcinterScanline(scanline3, x1, x2, span1, span2);
185                            GeometryScanline::ConstIterator span3 = scanline3.Begin();
186                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span3->spanLength);
187                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span3->spanLength,
188                                                    alloc.GetSpanPtr(),
189                                                    span3->covers);
190                        } else if ((x1 < x2) && ((x1 + span1->spanLength) > x2) &&
191                                   ((x1 + span1->spanLength) <= (x2 + span2->spanLength))) {
192                            GeometryScanline scanline3;
193                            CalcinterScanline(scanline3, x2, x1, span2, span1);
194                            GeometryScanline::ConstIterator span3 = scanline3.Begin();
195                            spanGen1.Generate(alloc.GetSpanPtr(), x2, y2, span3->spanLength);
196                            renBase.BlendColorHSpan(x2, y2, (uint32_t)span3->spanLength,
197                                                    alloc.GetSpanPtr(),
198                                                    span3->covers);
199                        }
200                    }
201                }
202                ++span1;
203                } else {
204                    if (span2->spanLength > 0) {
205                        spanGen2.Generate(alloc.GetSpanPtr(), x2, y2, span2->spanLength);
206                        renBase.BlendColorHSpan(x2, y2, (uint32_t)span2->spanLength,
207                                                alloc.GetSpanPtr(),
208                                                span2->covers);
209                    }
210                }
211            if (--numSpans2 == 0) {
212                break;
213            }
214            ++span2;
215        }
216        if (y1 == y2) {
217            raster1.SweepScanline(scanline1);
218            y1 = scanline1.GetYLevel();
219        }
220    }
221}
222
223void BlendSourceIn(RasterizerScanlineAntialias& raster1, RasterizerScanlineAntialias& raster2,
224                   GeometryScanline& scanline1, GeometryScanline& scanline2, RenderBase& renBase,
225                   FillBase& alloc, SpanBase& spanGen1)
226{
227    if (!raster1.RewindScanlines() || !raster2.RewindScanlines()) {
228        return;
229    }
230
231    scanline1.Reset(raster1.GetMinX(), raster1.GetMaxX());
232    scanline2.Reset(raster2.GetMinX(), raster2.GetMaxX());
233
234    int16_t allocMinx = (raster1.GetMinX() > raster2.GetMinX()) ? raster2.GetMinX() : raster1.GetMinX();
235    int16_t allocMaxX = (raster1.GetMaxX() > raster2.GetMaxX()) ? raster1.GetMaxX() : raster2.GetMaxX();
236    alloc.Resize(allocMaxX-allocMinx);
237    int32_t y1 = 0;
238    if (raster1.SweepScanline(scanline1)) {
239        y1 = scanline1.GetYLevel();
240        spanGen1.Prepare();
241    }
242    while (raster2.SweepScanline(scanline2)) {
243        BlendSourceInLoop(raster1, scanline1, scanline2, spanGen1, renBase, alloc, y1);
244    }
245}
246
247void BlendSourceOut(RasterizerScanlineAntialias& raster1, RasterizerScanlineAntialias& raster2,
248                    GeometryScanline& scanline1, GeometryScanline& scanline2,
249                    RenderBase& renBase, FillBase& alloc, SpanBase& spanGen1)
250{
251    if (!raster1.RewindScanlines() || !raster2.RewindScanlines()) {
252        return;
253    }
254    scanline1.Reset(raster1.GetMinX(), raster1.GetMaxX());
255    scanline2.Reset(raster2.GetMinX(), raster2.GetMaxX());
256    int16_t allocMinx = (raster1.GetMinX() > raster2.GetMinX()) ? raster2.GetMinX() : raster1.GetMinX();
257    int16_t allocMaxX = (raster1.GetMaxX() > raster2.GetMaxX()) ? raster1.GetMaxX() : raster2.GetMaxX();
258    alloc.Resize(allocMaxX-allocMinx);
259    int32_t y1 = 0;
260    if (raster1.SweepScanline(scanline1)) {
261        y1 = scanline1.GetYLevel();
262        spanGen1.Prepare();
263    }
264    if (raster1.GetMinY() < raster2.GetMinY()) {
265        do {
266            y1 = scanline1.GetYLevel();
267            if (y1 == raster2.GetMinY()) {
268                break;
269            }
270            BlendSourceOutWhile(y1, scanline1, renBase, alloc, spanGen1);
271        } while (raster1.SweepScanline(scanline1));
272    }
273    while (raster2.SweepScanline(scanline2)) {
274        int32_t y2 = scanline2.GetYLevel();
275        uint32_t numSpans2 = scanline2.NumSpans();
276        GeometryScanline::ConstIterator span2 = scanline2.Begin();
277        GeometryScanline::ConstIterator span1 = scanline1.Begin();
278        while (true) {
279            int32_t x2 = span2->x;
280            if (y1 == y2) {
281                int32_t x1 = span1->x;
282                if (span2->spanLength > 0) {
283                    if (span1->spanLength > 0) {
284                        if ((x1 < x2) && (x2 + span2->spanLength) < (x1 + span1->spanLength)) {
285                            GeometryScanline scanline3;
286                            CalcOutScanlineAll(scanline3, x2, x1, span2, span1);
287                            GeometryScanline::ConstIterator span3 = scanline3.Begin();
288                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span3->spanLength);
289                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span3->spanLength,
290                                                    alloc.GetSpanPtr(),
291                                                    span3->covers);
292                        } else if ((x1 >= x2) && x1 < x2 + span2->spanLength &&
293                                   ((x1 + span1->spanLength) >= (x2 + span2->spanLength))) {
294                            GeometryScanline scanline4;
295                            CalcOutScanlineLeft(scanline4, x1, x2, span1, span2);
296                            GeometryScanline::ConstIterator span4 = scanline4.Begin();
297                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span4->spanLength);
298                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span4->spanLength,
299                                                    alloc.GetSpanPtr(),
300                                                    span4->covers);
301                        } else if ((x1 <= x2) && (x1 + span1->spanLength) >= x2 &&
302                                   ((x1 + span1->spanLength) <= (x2 + span2->spanLength))) {
303                            GeometryScanline scanline3;
304                            CalcOutScanlineRight(scanline3, x2, x1, span2, span1);
305                            GeometryScanline::ConstIterator span3 = scanline3.Begin();
306                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span3->spanLength);
307                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span3->spanLength,
308                                                    alloc.GetSpanPtr(), span3->covers);
309                        } else if (((x1 + span1->spanLength) < x2) || ((x2 + span2->spanLength) < x1)) {
310                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span1->spanLength);
311                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span1->spanLength,
312                                                    alloc.GetSpanPtr(),
313                                                    span1->covers);
314                        }
315                    }
316                }
317                ++span1;
318            }
319            if (--numSpans2 == 0) {
320                break;
321            }
322            ++span2;
323        }
324        if (y1 == y2 && y1 < raster2.GetMaxY() - 1) {
325            if (raster1.SweepScanline(scanline1)) {
326                y1 = scanline1.GetYLevel();
327            }
328        }
329    }
330    BlendSourceOutDrawResetRaster(raster1, scanline1, renBase, alloc, spanGen1);
331}
332
333void BlendSourceOutWhile(int32_t y1, GeometryScanline& scanline1, RenderBase& renBase,
334                         FillBase& alloc, SpanBase& spanGen1)
335{
336    uint32_t numSpans = scanline1.NumSpans();
337    typename GeometryScanline::ConstIterator span = scanline1.Begin();
338    while (true) {
339        int32_t x = span->x;
340        if (span->spanLength > 0) {
341            spanGen1.Generate(alloc.GetSpanPtr(), x, y1, span->spanLength);
342            renBase.BlendColorHSpan(x, y1, (uint32_t)span->spanLength,
343                                    alloc.GetSpanPtr(),
344                                    span->covers);
345        }
346        if (--numSpans == 0) {
347            break;
348        }
349        ++span;
350    }
351}
352
353void BlendSourceOutDrawResetRaster(RasterizerScanlineAntialias& raster1, GeometryScanline& scanline1,
354                                   RenderBase& renBase, FillBase& alloc, SpanBase& spanGen1)
355{
356    while (raster1.SweepScanline(scanline1)) {
357        int32_t y = scanline1.GetYLevel();
358        uint32_t numSpans = scanline1.NumSpans();
359        GeometryScanline::ConstIterator span = scanline1.Begin();
360        while (true) {
361            int32_t x = span->x;
362            if (span->spanLength > 0) {
363                spanGen1.Generate(alloc.GetSpanPtr(), x, y, span->spanLength);
364                renBase.BlendColorHSpan(x, y, (uint32_t)span->spanLength,
365                                        alloc.GetSpanPtr(),
366                                        span->covers);
367            }
368            if (--numSpans == 0) {
369                break;
370            }
371            ++span;
372        }
373    }
374}
375
376void BlendSourceOver(RasterizerScanlineAntialias &raster1,
377                     RasterizerScanlineAntialias &raster2,
378                     GeometryScanline &scanline1,
379                     GeometryScanline &scanline2,
380                     RenderBase &renBase,
381                     FillBase &alloc,
382                     SpanBase&&spanGen1,
383                     SpanBase &spanGen2)
384{
385    RenderScanlinesAntiAlias(raster1, scanline1, renBase, alloc, spanGen1);
386    RenderScanlinesAntiAlias(raster2, scanline2, renBase, alloc, spanGen2);
387}
388
389void BlendXOR(RasterizerScanlineAntialias& raster1, RasterizerScanlineAntialias& raster2,
390              GeometryScanline& scanline1, GeometryScanline& scanline2,
391              RenderBase& renBase, FillBase& alloc, SpanBase& spanGen1, SpanBase& spanGen2)
392{
393    if (!raster1.RewindScanlines() || !raster2.RewindScanlines()) {
394        return;
395    }
396    scanline1.Reset(raster1.GetMinX(), raster1.GetMaxX());
397    scanline2.Reset(raster2.GetMinX(), raster2.GetMaxX());
398    int16_t allocMinx = raster1.GetMinX() > raster2.GetMinX() ? raster2.GetMinX() : raster1.GetMinX();
399    int16_t allocMaxX = raster1.GetMaxX() > raster2.GetMaxX() ? raster1.GetMaxX() : raster2.GetMaxX();
400    alloc.Resize(allocMaxX-allocMinx);
401    int32_t y1 = 0;
402    if (raster1.SweepScanline(scanline1)) {
403        y1 = scanline1.GetYLevel();
404        spanGen1.Prepare();
405    }
406    BlendXORColorHspan(y1, raster1, raster2, scanline1, renBase, alloc, spanGen1);
407    while (raster2.SweepScanline(scanline2)) {
408        int32_t y2 = scanline2.GetYLevel();
409        spanGen2.Prepare();
410        uint32_t numSpans2 = scanline2.NumSpans();
411        GeometryScanline::ConstIterator span2 = scanline2.Begin();
412        GeometryScanline::ConstIterator span1 = scanline1.Begin();
413        while (true) {
414            int32_t x2 = span2->x;
415            if (y1 == y2) {
416                {
417                int32_t x1 = span1->x;
418                if (span2->spanLength > 0) {
419                    if (span1->spanLength > 0) {
420                        if ((x1 >= x2) && ((x1 + span1->spanLength) <= (x2 + span2->spanLength))) {
421                            GeometryScanline scanline3;
422                            CalcOutScanlineAll(scanline3, x1, x2, span1, span2);
423                            GeometryScanline::ConstIterator span3 = scanline3.Begin();
424                            spanGen2.Generate(alloc.GetSpanPtr(), x2, y2, span3->spanLength);
425                            renBase.BlendColorHSpan(x2, y2, (uint32_t)span3->spanLength,
426                                                    alloc.GetSpanPtr(),
427                                                    span3->covers);
428                        } else if (((x1 < x2) && ((x2 + span2->spanLength) < (x1 + span1->spanLength)))) {
429                            GeometryScanline scanline3;
430                            CalcOutScanlineAll(scanline3, x2, x1, span2, span1);
431                            GeometryScanline::ConstIterator span3 = scanline3.Begin();
432                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span3->spanLength);
433                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span3->spanLength,
434                                                    alloc.GetSpanPtr(),
435                                                    span3->covers);
436                        } else if ((x1 >= x2) && (x1 < x2 + span2->spanLength) &&
437                            (x1 + span1->spanLength >= x2 + span2->spanLength)) {
438                            GeometryScanline scanline3;
439                            CalcOutScanlineRight(scanline3, x1, x2, span1, span2);
440                            GeometryScanline::ConstIterator span3 = scanline3.Begin();
441                            spanGen2.Generate(alloc.GetSpanPtr(), x2, y2, span3->spanLength);
442                            renBase.BlendColorHSpan(x2, y2, (uint32_t)span3->spanLength,
443                                                    alloc.GetSpanPtr(),
444                                                    span3->covers);
445                            GeometryScanline scanline4;
446                            CalcOutScanlineLeft(scanline4, x1, x2, span1, span2);
447                            GeometryScanline::ConstIterator span4 = scanline4.Begin();
448                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span4->spanLength);
449                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span4->spanLength,
450                                                    alloc.GetSpanPtr(),
451                                                    span4->covers);
452                        } else if ((x1 <= x2) && (x1 + span1->spanLength >= x2) &&
453                            (x1 + span1->spanLength <= x2 + span2->spanLength)) {
454                            GeometryScanline scanline3;
455                            CalcOutScanlineRight(scanline3, x2, x1, span2, span1);
456                            GeometryScanline::ConstIterator span3 = scanline3.Begin();
457                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span3->spanLength);
458                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span3->spanLength,
459                                                    alloc.GetSpanPtr(), span3->covers);
460                            GeometryScanline scanline4;
461                            CalcOutScanlineLeft(scanline4, x2, x1, span2, span1);
462                            GeometryScanline::ConstIterator span4 = scanline4.Begin();
463                            spanGen2.Generate(alloc.GetSpanPtr(), x2, y2, span4->spanLength);
464                            renBase.BlendColorHSpan(x2, y2, (uint32_t)span4->spanLength,
465                                                    alloc.GetSpanPtr(), span4->covers);
466                        } else if ((x1 + span1->spanLength < x2)|| (x2+span2->spanLength < x1)) {
467                            spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span1->spanLength);
468                            renBase.BlendColorHSpan(x1, y2, (uint32_t)span1->spanLength,
469                                                    alloc.GetSpanPtr(), span1->covers);
470                            spanGen2.Generate(alloc.GetSpanPtr(), x2, y2, span2->spanLength);
471                            renBase.BlendColorHSpan(x2, y2, (uint32_t)span2->spanLength,
472                                                    alloc.GetSpanPtr(), span2->covers);
473                        }
474                    }
475                }
476                    ++span1;
477                }
478            } else if (span2->spanLength > 0) {
479                spanGen2.Generate(alloc.GetSpanPtr(), x2, y2, span2->spanLength);
480                renBase.BlendColorHSpan(x2, y2, (uint32_t)span2->spanLength, alloc.GetSpanPtr(), span2->covers);
481            }
482            if (--numSpans2 == 0) {
483                break;
484            }
485            ++span2;
486        }
487        if (y1 == y2 && y1 < raster2.GetMaxY() - 1) {
488            if (raster1.SweepScanline(scanline1)) {
489                y1 = scanline1.GetYLevel();
490            }
491        }
492    }
493    // Draw the rest of raster1
494    BlendXORDrawResetRaster(raster1, scanline1, renBase, alloc, spanGen1);
495}
496
497void BlendXORDrawResetRaster(RasterizerScanlineAntialias& raster1, GeometryScanline& scanline1,
498                             RenderBase& renBase, FillBase& alloc, SpanBase& spanGen1)
499
500{
501    while (raster1.SweepScanline(scanline1)) {
502        int32_t y = scanline1.GetYLevel();
503        uint32_t numSpans = scanline1.NumSpans();
504        GeometryScanline::ConstIterator span = scanline1.Begin();
505        while (true) {
506            int32_t x = span->x;
507            if (span->spanLength > 0) {
508                spanGen1.Generate(alloc.GetSpanPtr(), x, y, span->spanLength);
509                renBase.BlendColorHSpan(x, y, (uint32_t)span->spanLength, alloc.GetSpanPtr(), span->covers);
510            }
511            if (--numSpans == 0) {
512                break;
513            }
514            ++span;
515        }
516    }
517}
518
519void BlendXORColorHspan(int32_t& y1, RasterizerScanlineAntialias& raster1, RasterizerScanlineAntialias& raster2,
520                        GeometryScanline& scanline1, RenderBase& renBase, FillBase& alloc, SpanBase& spanGen1)
521{
522    if (raster1.GetMinY() > raster2.GetMinY()) {
523        return;
524    }
525    do {
526        y1 = scanline1.GetYLevel();
527        if (y1 == raster2.GetMinY()) {
528            break;
529        }
530        uint32_t numSpans = scanline1.NumSpans();
531        GeometryScanline::ConstIterator span = scanline1.Begin();
532        while (true) {
533            int32_t x = span->x;
534            if (span->spanLength > 0) {
535                spanGen1.Generate(alloc.GetSpanPtr(), x, y1, span->spanLength);
536                renBase.BlendColorHSpan(x, y1, (uint32_t)span->spanLength,
537                                        alloc.GetSpanPtr(), span->covers);
538            }
539            if (--numSpans == 0) {
540                break;
541            }
542            ++span;
543        }
544    } while (raster1.SweepScanline(scanline1));
545}
546
547void BlendLIGHTER(RasterizerScanlineAntialias& raster1, RasterizerScanlineAntialias& raster2,
548                  GeometryScanline& scanline1, GeometryScanline& scanline2,
549                  RenderBase& renBase, FillBase& alloc, SpanBase& spanGen1, SpanBase& spanGen2)
550{
551    BlendXOR(raster1, raster2, scanline1, scanline2, renBase, alloc, spanGen1, spanGen2);
552    SpanBlendColor spanBlendColor(spanGen1, spanGen2);
553    BlendSourceIn(raster1, raster2, scanline1, scanline2, renBase, alloc, spanBlendColor);
554}
555
556void BlendSourceInLoop(RasterizerScanlineAntialias& raster1, GeometryScanline& scanline1, GeometryScanline& scanline2,
557                       SpanBase& spanGen1, RenderBase& renBase, FillBase& alloc, int32_t& y1)
558{
559    int32_t y2 = scanline2.GetYLevel();
560    uint32_t numSpans2 = scanline2.NumSpans();
561    GeometryScanline::ConstIterator span2 = scanline2.Begin();
562    GeometryScanline::ConstIterator span1 = scanline1.Begin();
563
564    if (y2 > y1) {
565        while (raster1.SweepScanline(scanline1)) {
566            y1 = scanline1.GetYLevel();
567            if (y1 == y2) {
568                span1 = scanline1.Begin();
569                break;
570            }
571        }
572    }
573    while (true) {
574        int32_t x2 = span2->x;
575        if (y1 == y2) {
576            int32_t x1 = span1->x;
577            if (span2->spanLength > 0) {
578                if (span1->spanLength > 0) {
579                    if (x1<=x2 && x2+span2->spanLength < x1+span1->spanLength) {
580                        spanGen1.Generate(alloc.GetSpanPtr(), x2, y2, span2->spanLength);
581                        renBase.BlendColorHSpan(x2, y2, (uint32_t)span2->spanLength,
582                                                alloc.GetSpanPtr(), span2->covers);
583                    } else if ((x1 >= x2) && (x1 + span1->spanLength <= x2+span2->spanLength)) {
584                        spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span1->spanLength);
585                        renBase.BlendColorHSpan(x1, y2, (uint32_t)span1->spanLength,
586                                                alloc.GetSpanPtr(), span1->covers);
587                    } else if ((x1 > x2) && (x1 < x2 + span2->spanLength) &&
588                        (x1 + span1->spanLength >= x2 + span2->spanLength)) {
589                        GeometryScanline scanline3;
590                        CalcinterScanline(scanline3, x1, x2, span1, span2);
591                        GeometryScanline::ConstIterator span3 = scanline3.Begin();
592                        spanGen1.Generate(alloc.GetSpanPtr(), x1, y2, span3->spanLength);
593                        renBase.BlendColorHSpan(x1, y2, (uint32_t)span3->spanLength,
594                                                alloc.GetSpanPtr(), span3->covers);
595                    } else if ((x1 < x2) && (x1 + span1->spanLength > x2) &&
596                        (x1 + span1->spanLength <= x2 + span2->spanLength)) {
597                        GeometryScanline scanline3;
598                        CalcinterScanline(scanline3, x2, x1, span2, span1);
599                        GeometryScanline::ConstIterator span3 = scanline3.Begin();
600                        spanGen1.Generate(alloc.GetSpanPtr(), x2, y2, span3->spanLength);
601                        renBase.BlendColorHSpan(x2, y2, (uint32_t)span3->spanLength,
602                                                alloc.GetSpanPtr(), span3->covers);
603                    }
604                }
605            }
606            ++span1;
607        }
608        if (--numSpans2 == 0) {
609            break;
610        }
611        ++span2;
612    }
613    if (y1 == y2) {
614        raster1.SweepScanline(scanline1);
615        y1 = scanline1.GetYLevel();
616    }
617}
618
619void BlendSourceOver(RasterizerScanlineAntialias& raster1, RasterizerScanlineAntialias& raster2,
620                     GeometryScanline& scanline1, GeometryScanline& scanline2,
621                     RenderBase& renBase, FillBase& alloc, SpanBase& spanGen1, SpanBase& spanGen2)
622{
623    RenderScanlinesAntiAlias(raster1, scanline1, renBase, alloc, spanGen1);
624    RenderScanlinesAntiAlias(raster2, scanline2, renBase, alloc, spanGen2);
625}
626
627void CalcinterScanline(GeometryScanline& scanline3, int32_t x1, int32_t x2,
628                       GeometryScanline::ConstIterator span1, GeometryScanline::ConstIterator span2)
629{
630    scanline3.Reset(x1, x2 + span2->spanLength);
631    uint32_t len3 = x2 + span2->spanLength - x1;
632    uint8_t* cover1 = span1->covers;
633    uint8_t* cover2 = span2->covers + (x1 - x2);
634    int32_t x3 = x1;
635    for (uint32_t i = 0; i < len3; i++, cover1++, cover2++) {
636        if (*(cover1) != COVER_FULL) {
637            scanline3.AddCell(x3++, *cover1);
638        } else {
639            scanline3.AddCell(x3++, *cover2);
640        }
641    }
642}
643
644void CalcOutScanlineRight(GeometryScanline& scanline, int32_t x1, int32_t x2,
645                          GeometryScanline::ConstIterator span1, GeometryScanline::ConstIterator span2)
646{
647    uint8_t* cover1 = span1->covers;
648    uint8_t* cover2 = span2->covers;
649    scanline.Reset(x2, x2 + span2->spanLength);
650    for (int32_t i = 1; i <= span2->spanLength; i++, cover2++) {
651        if (x1 == x2) {
652            scanline.AddCell(x2++, COVER_FULL - (*cover1));
653            x1++;
654            cover1++;
655        } else {
656            scanline.AddCell(x2++, *cover2);
657        }
658    }
659}
660
661void CalcOutScanlineLeft(GeometryScanline& scanline, int32_t x1, int32_t x2,
662                         GeometryScanline::ConstIterator span1, GeometryScanline::ConstIterator span2)
663{
664    uint8_t* cover2 = span2->covers + (x1 - x2);
665    scanline.Reset(x1, x1 + span1->spanLength);
666    int32_t len1 = span2->spanLength - (x1 - x2); // Length of intersection
667    int32_t len2 = span1->spanLength - len1;      // Length of intersection
668    uint8_t* cover1 = span1->covers + len1;
669    for (int32_t i = 0; i < len1; i++, cover2++) {
670        scanline.AddCell(x1++, COVER_FULL - (*cover2));
671    }
672
673    for (int32_t i = 0; i < len2; i++, cover1++) {
674        scanline.AddCell(x1++, *cover1);
675    }
676}
677
678void CalcOutScanlineAll(GeometryScanline& scanline, int32_t x1, int32_t x2,
679                        GeometryScanline::ConstIterator span1, GeometryScanline::ConstIterator span2)
680{
681    uint8_t* cover1 = span1->covers;
682    uint8_t* cover2 = span2->covers;
683    int32_t x3 = x1;
684    scanline.Reset(x2, x2 + span2->spanLength);
685    for (int32_t i = 0; i < span2->spanLength; i++, cover2++) {
686        if (x3 == x2 && x3 <= x1 + span1->spanLength - 1) {
687            scanline.AddCell(x2++, COVER_FULL - (*cover1));
688            x3++;
689            cover1++;
690        } else {
691            scanline.AddCell(x2++, *cover2);
692        }
693    }
694}
695} // namespace OHOS
696