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