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 
24 namespace OHOS {
RenderScanlinesAntiAliasSolid(RasterizerScanlineAntialias & raster,GeometryScanline & scanline,RenderBase & renBase,const Rgba8T & color)25 void 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 
RenderScanlinesAntiAlias(RasterizerScanlineAntialias & raster,GeometryScanline & scanline,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen)53 void 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 
BlendScanLine(GlobalCompositeOperation op,RasterizerScanlineAntialias & raster1,RasterizerScanlineAntialias & raster2,GeometryScanline & sl1,GeometryScanline & sl2,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1,SpanBase & spanGen2)87 void 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 
BlendSourceAtop(RasterizerScanlineAntialias & raster1,RasterizerScanlineAntialias & raster2,GeometryScanline & scanline1,GeometryScanline & scanline2,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1,SpanBase & spanGen2)130 void 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 
BlendSourceIn(RasterizerScanlineAntialias & raster1,RasterizerScanlineAntialias & raster2,GeometryScanline & scanline1,GeometryScanline & scanline2,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1)223 void 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 
BlendSourceOut(RasterizerScanlineAntialias & raster1,RasterizerScanlineAntialias & raster2,GeometryScanline & scanline1,GeometryScanline & scanline2,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1)247 void 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 
BlendSourceOutWhile(int32_t y1,GeometryScanline & scanline1,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1)333 void 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 
BlendSourceOutDrawResetRaster(RasterizerScanlineAntialias & raster1,GeometryScanline & scanline1,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1)353 void 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 
BlendSourceOver(RasterizerScanlineAntialias & raster1,RasterizerScanlineAntialias & raster2,GeometryScanline & scanline1,GeometryScanline & scanline2,RenderBase & renBase,FillBase & alloc,SpanBase && spanGen1,SpanBase & spanGen2)376 void 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 
BlendXOR(RasterizerScanlineAntialias & raster1,RasterizerScanlineAntialias & raster2,GeometryScanline & scanline1,GeometryScanline & scanline2,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1,SpanBase & spanGen2)389 void 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 
BlendXORDrawResetRaster(RasterizerScanlineAntialias & raster1,GeometryScanline & scanline1,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1)497 void 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 
BlendXORColorHspan(int32_t & y1,RasterizerScanlineAntialias & raster1,RasterizerScanlineAntialias & raster2,GeometryScanline & scanline1,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1)519 void 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 
BlendLIGHTER(RasterizerScanlineAntialias & raster1,RasterizerScanlineAntialias & raster2,GeometryScanline & scanline1,GeometryScanline & scanline2,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1,SpanBase & spanGen2)547 void 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 
BlendSourceInLoop(RasterizerScanlineAntialias & raster1,GeometryScanline & scanline1,GeometryScanline & scanline2,SpanBase & spanGen1,RenderBase & renBase,FillBase & alloc,int32_t & y1)556 void 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 
BlendSourceOver(RasterizerScanlineAntialias & raster1,RasterizerScanlineAntialias & raster2,GeometryScanline & scanline1,GeometryScanline & scanline2,RenderBase & renBase,FillBase & alloc,SpanBase & spanGen1,SpanBase & spanGen2)619 void 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 
CalcinterScanline(GeometryScanline & scanline3,int32_t x1,int32_t x2,GeometryScanline::ConstIterator span1,GeometryScanline::ConstIterator span2)627 void 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 
CalcOutScanlineRight(GeometryScanline & scanline,int32_t x1,int32_t x2,GeometryScanline::ConstIterator span1,GeometryScanline::ConstIterator span2)644 void 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 
CalcOutScanlineLeft(GeometryScanline & scanline,int32_t x1,int32_t x2,GeometryScanline::ConstIterator span1,GeometryScanline::ConstIterator span2)661 void 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 
CalcOutScanlineAll(GeometryScanline & scanline,int32_t x1,int32_t x2,GeometryScanline::ConstIterator span1,GeometryScanline::ConstIterator span2)678 void 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