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