1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fxcodec/fx_codec.h" 8 #include "core/fxge/cfx_gemodule.h" 9 #include "core/fxge/dib/dib_int.h" 10 #include "core/fxge/ge/cfx_cliprgn.h" 11 12 namespace { 13 14 const uint8_t color_sqrt[256] = { 15 0x00, 0x03, 0x07, 0x0B, 0x0F, 0x12, 0x16, 0x19, 0x1D, 0x20, 0x23, 0x26, 16 0x29, 0x2C, 0x2F, 0x32, 0x35, 0x37, 0x3A, 0x3C, 0x3F, 0x41, 0x43, 0x46, 17 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x57, 0x59, 0x5B, 0x5C, 18 0x5E, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 19 0x6E, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 20 0x7B, 0x7C, 0x7D, 0x7E, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 21 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x91, 22 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 23 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5, 24 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE, 25 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7, 26 0xB7, 0xB8, 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBE, 0xBF, 27 0xC0, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7, 28 0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCE, 29 0xCF, 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6, 30 0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, 31 0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE2, 0xE3, 0xE4, 32 0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, 33 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE, 0xEF, 0xF0, 0xF0, 0xF1, 34 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7, 35 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 36 0xFD, 0xFE, 0xFE, 0xFF}; 37 38 int Blend(int blend_mode, int back_color, int src_color) { 39 switch (blend_mode) { 40 case FXDIB_BLEND_NORMAL: 41 return src_color; 42 case FXDIB_BLEND_MULTIPLY: 43 return src_color * back_color / 255; 44 case FXDIB_BLEND_SCREEN: 45 return src_color + back_color - src_color * back_color / 255; 46 case FXDIB_BLEND_OVERLAY: 47 return Blend(FXDIB_BLEND_HARDLIGHT, src_color, back_color); 48 case FXDIB_BLEND_DARKEN: 49 return src_color < back_color ? src_color : back_color; 50 case FXDIB_BLEND_LIGHTEN: 51 return src_color > back_color ? src_color : back_color; 52 case FXDIB_BLEND_COLORDODGE: { 53 if (src_color == 255) { 54 return src_color; 55 } 56 int result = back_color * 255 / (255 - src_color); 57 if (result > 255) { 58 return 255; 59 } 60 return result; 61 } 62 case FXDIB_BLEND_COLORBURN: { 63 if (src_color == 0) { 64 return src_color; 65 } 66 int result = (255 - back_color) * 255 / src_color; 67 if (result > 255) { 68 result = 255; 69 } 70 return 255 - result; 71 } 72 case FXDIB_BLEND_HARDLIGHT: 73 if (src_color < 128) { 74 return (src_color * back_color * 2) / 255; 75 } 76 return Blend(FXDIB_BLEND_SCREEN, back_color, 2 * src_color - 255); 77 case FXDIB_BLEND_SOFTLIGHT: { 78 if (src_color < 128) { 79 return back_color - 80 (255 - 2 * src_color) * back_color * (255 - back_color) / 255 / 81 255; 82 } 83 return back_color + 84 (2 * src_color - 255) * (color_sqrt[back_color] - back_color) / 85 255; 86 } 87 case FXDIB_BLEND_DIFFERENCE: 88 return back_color < src_color ? src_color - back_color 89 : back_color - src_color; 90 case FXDIB_BLEND_EXCLUSION: 91 return back_color + src_color - 2 * back_color * src_color / 255; 92 } 93 return src_color; 94 } 95 96 struct RGB { 97 int red; 98 int green; 99 int blue; 100 }; 101 102 int Lum(RGB color) { 103 return (color.red * 30 + color.green * 59 + color.blue * 11) / 100; 104 } 105 106 RGB ClipColor(RGB color) { 107 int l = Lum(color); 108 int n = color.red; 109 if (color.green < n) { 110 n = color.green; 111 } 112 if (color.blue < n) { 113 n = color.blue; 114 } 115 int x = color.red; 116 if (color.green > x) { 117 x = color.green; 118 } 119 if (color.blue > x) { 120 x = color.blue; 121 } 122 if (n < 0) { 123 color.red = l + ((color.red - l) * l / (l - n)); 124 color.green = l + ((color.green - l) * l / (l - n)); 125 color.blue = l + ((color.blue - l) * l / (l - n)); 126 } 127 if (x > 255) { 128 color.red = l + ((color.red - l) * (255 - l) / (x - l)); 129 color.green = l + ((color.green - l) * (255 - l) / (x - l)); 130 color.blue = l + ((color.blue - l) * (255 - l) / (x - l)); 131 } 132 return color; 133 } 134 135 RGB SetLum(RGB color, int l) { 136 int d = l - Lum(color); 137 color.red += d; 138 color.green += d; 139 color.blue += d; 140 return ClipColor(color); 141 } 142 143 int Sat(RGB color) { 144 int n = color.red; 145 if (color.green < n) { 146 n = color.green; 147 } 148 if (color.blue < n) { 149 n = color.blue; 150 } 151 int x = color.red; 152 if (color.green > x) { 153 x = color.green; 154 } 155 if (color.blue > x) { 156 x = color.blue; 157 } 158 return x - n; 159 } 160 161 RGB SetSat(RGB color, int s) { 162 int* max = &color.red; 163 int* mid = &color.red; 164 int* min = &color.red; 165 if (color.green > *max) { 166 max = &color.green; 167 } 168 if (color.blue > *max) { 169 max = &color.blue; 170 } 171 if (color.green < *min) { 172 min = &color.green; 173 } 174 if (color.blue < *min) { 175 min = &color.blue; 176 } 177 if (*max == *min) { 178 color.red = 0; 179 color.green = 0; 180 color.blue = 0; 181 return color; 182 } 183 if (max == &color.red) { 184 if (min == &color.green) { 185 mid = &color.blue; 186 } else { 187 mid = &color.green; 188 } 189 } else if (max == &color.green) { 190 if (min == &color.red) { 191 mid = &color.blue; 192 } else { 193 mid = &color.red; 194 } 195 } else { 196 if (min == &color.green) { 197 mid = &color.red; 198 } else { 199 mid = &color.green; 200 } 201 } 202 if (*max > *min) { 203 *mid = (*mid - *min) * s / (*max - *min); 204 *max = s; 205 *min = 0; 206 } 207 return color; 208 } 209 210 void RGB_Blend(int blend_mode, 211 const uint8_t* src_scan, 212 uint8_t* dest_scan, 213 int results[3]) { 214 RGB src; 215 RGB back; 216 RGB result = {0, 0, 0}; 217 src.red = src_scan[2]; 218 src.green = src_scan[1]; 219 src.blue = src_scan[0]; 220 back.red = dest_scan[2]; 221 back.green = dest_scan[1]; 222 back.blue = dest_scan[0]; 223 switch (blend_mode) { 224 case FXDIB_BLEND_HUE: 225 result = SetLum(SetSat(src, Sat(back)), Lum(back)); 226 break; 227 case FXDIB_BLEND_SATURATION: 228 result = SetLum(SetSat(back, Sat(src)), Lum(back)); 229 break; 230 case FXDIB_BLEND_COLOR: 231 result = SetLum(src, Lum(back)); 232 break; 233 case FXDIB_BLEND_LUMINOSITY: 234 result = SetLum(back, Lum(src)); 235 break; 236 } 237 results[0] = result.blue; 238 results[1] = result.green; 239 results[2] = result.red; 240 } 241 242 void CompositeRow_Argb2Mask(uint8_t* dest_scan, 243 const uint8_t* src_scan, 244 int pixel_count, 245 const uint8_t* clip_scan) { 246 src_scan += 3; 247 for (int col = 0; col < pixel_count; col++) { 248 int src_alpha = *src_scan; 249 if (clip_scan) { 250 src_alpha = clip_scan[col] * src_alpha / 255; 251 } 252 uint8_t back_alpha = *dest_scan; 253 if (!back_alpha) { 254 *dest_scan = src_alpha; 255 } else if (src_alpha) { 256 *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; 257 } 258 dest_scan++; 259 src_scan += 4; 260 } 261 } 262 263 void CompositeRow_Rgba2Mask(uint8_t* dest_scan, 264 const uint8_t* src_alpha_scan, 265 int pixel_count, 266 const uint8_t* clip_scan) { 267 for (int col = 0; col < pixel_count; col++) { 268 int src_alpha = *src_alpha_scan++; 269 if (clip_scan) { 270 src_alpha = clip_scan[col] * src_alpha / 255; 271 } 272 uint8_t back_alpha = *dest_scan; 273 if (!back_alpha) { 274 *dest_scan = src_alpha; 275 } else if (src_alpha) { 276 *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; 277 } 278 dest_scan++; 279 } 280 } 281 282 void CompositeRow_Rgb2Mask(uint8_t* dest_scan, 283 const uint8_t* src_scan, 284 int width, 285 const uint8_t* clip_scan) { 286 if (clip_scan) { 287 for (int i = 0; i < width; i++) { 288 *dest_scan = FXDIB_ALPHA_UNION(*dest_scan, *clip_scan); 289 dest_scan++; 290 clip_scan++; 291 } 292 } else { 293 FXSYS_memset(dest_scan, 0xff, width); 294 } 295 } 296 297 void CompositeRow_Argb2Graya(uint8_t* dest_scan, 298 const uint8_t* src_scan, 299 int pixel_count, 300 int blend_type, 301 const uint8_t* clip_scan, 302 const uint8_t* src_alpha_scan, 303 uint8_t* dst_alpha_scan, 304 void* pIccTransform) { 305 CCodec_IccModule* pIccModule = nullptr; 306 if (pIccTransform) 307 pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 308 309 if (blend_type) { 310 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 311 if (src_alpha_scan) { 312 for (int col = 0; col < pixel_count; col++) { 313 uint8_t back_alpha = *dst_alpha_scan; 314 if (back_alpha == 0) { 315 int src_alpha = *src_alpha_scan++; 316 if (clip_scan) 317 src_alpha = clip_scan[col] * src_alpha / 255; 318 319 if (src_alpha) { 320 if (pIccTransform) { 321 pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 322 1); 323 } else { 324 *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 325 } 326 *dst_alpha_scan = src_alpha; 327 } 328 dest_scan++; 329 dst_alpha_scan++; 330 src_scan += 3; 331 continue; 332 } 333 uint8_t src_alpha = *src_alpha_scan++; 334 if (clip_scan) 335 src_alpha = clip_scan[col] * src_alpha / 255; 336 337 if (src_alpha == 0) { 338 dest_scan++; 339 dst_alpha_scan++; 340 src_scan += 3; 341 continue; 342 } 343 *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); 344 int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); 345 uint8_t gray; 346 if (pIccTransform) { 347 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 348 } else { 349 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 350 } 351 if (bNonseparableBlend) 352 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 353 else 354 gray = Blend(blend_type, *dest_scan, gray); 355 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 356 dest_scan++; 357 dst_alpha_scan++; 358 src_scan += 3; 359 } 360 } else { 361 for (int col = 0; col < pixel_count; col++) { 362 uint8_t back_alpha = *dst_alpha_scan; 363 if (back_alpha == 0) { 364 int src_alpha = src_scan[3]; 365 if (clip_scan) 366 src_alpha = clip_scan[col] * src_alpha / 255; 367 368 if (src_alpha) { 369 if (pIccTransform) { 370 pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 371 1); 372 } else { 373 *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 374 } 375 *dst_alpha_scan = src_alpha; 376 } 377 dest_scan++; 378 dst_alpha_scan++; 379 src_scan += 4; 380 continue; 381 } 382 uint8_t src_alpha = src_scan[3]; 383 if (clip_scan) 384 src_alpha = clip_scan[col] * src_alpha / 255; 385 386 if (src_alpha == 0) { 387 dest_scan++; 388 dst_alpha_scan++; 389 src_scan += 4; 390 continue; 391 } 392 *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); 393 int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); 394 uint8_t gray; 395 if (pIccTransform) 396 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 397 else 398 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 399 400 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 401 dest_scan++; 402 dst_alpha_scan++; 403 src_scan += 4; 404 } 405 } 406 return; 407 } 408 if (src_alpha_scan) { 409 for (int col = 0; col < pixel_count; col++) { 410 uint8_t back_alpha = *dst_alpha_scan; 411 if (back_alpha == 0) { 412 int src_alpha = *src_alpha_scan++; 413 if (clip_scan) 414 src_alpha = clip_scan[col] * src_alpha / 255; 415 416 if (src_alpha) { 417 if (pIccTransform) { 418 pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 419 1); 420 } else { 421 *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 422 } 423 *dst_alpha_scan = src_alpha; 424 } 425 dest_scan++; 426 dst_alpha_scan++; 427 src_scan += 3; 428 continue; 429 } 430 uint8_t src_alpha = *src_alpha_scan++; 431 if (clip_scan) 432 src_alpha = clip_scan[col] * src_alpha / 255; 433 434 if (src_alpha == 0) { 435 dest_scan++; 436 dst_alpha_scan++; 437 src_scan += 3; 438 continue; 439 } 440 *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); 441 int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); 442 uint8_t gray; 443 if (pIccTransform) 444 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 445 else 446 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 447 448 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 449 dest_scan++; 450 dst_alpha_scan++; 451 src_scan += 3; 452 } 453 } else { 454 for (int col = 0; col < pixel_count; col++) { 455 uint8_t back_alpha = *dst_alpha_scan; 456 if (back_alpha == 0) { 457 int src_alpha = src_scan[3]; 458 if (clip_scan) 459 src_alpha = clip_scan[col] * src_alpha / 255; 460 461 if (src_alpha) { 462 if (pIccTransform) { 463 pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 464 1); 465 } else { 466 *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 467 } 468 *dst_alpha_scan = src_alpha; 469 } 470 dest_scan++; 471 dst_alpha_scan++; 472 src_scan += 4; 473 continue; 474 } 475 uint8_t src_alpha = src_scan[3]; 476 if (clip_scan) 477 src_alpha = clip_scan[col] * src_alpha / 255; 478 479 if (src_alpha == 0) { 480 dest_scan++; 481 dst_alpha_scan++; 482 src_scan += 4; 483 continue; 484 } 485 *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); 486 int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); 487 uint8_t gray; 488 if (pIccTransform) 489 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 490 else 491 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 492 493 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 494 dest_scan++; 495 dst_alpha_scan++; 496 src_scan += 4; 497 } 498 } 499 } 500 501 void CompositeRow_Argb2Gray(uint8_t* dest_scan, 502 const uint8_t* src_scan, 503 int pixel_count, 504 int blend_type, 505 const uint8_t* clip_scan, 506 const uint8_t* src_alpha_scan, 507 void* pIccTransform) { 508 CCodec_IccModule* pIccModule = nullptr; 509 uint8_t gray; 510 if (pIccTransform) 511 pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 512 513 if (blend_type) { 514 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 515 if (src_alpha_scan) { 516 for (int col = 0; col < pixel_count; col++) { 517 int src_alpha = *src_alpha_scan++; 518 if (clip_scan) 519 src_alpha = clip_scan[col] * src_alpha / 255; 520 521 if (src_alpha) { 522 if (pIccTransform) 523 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 524 else 525 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 526 527 if (bNonseparableBlend) 528 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 529 else 530 gray = Blend(blend_type, *dest_scan, gray); 531 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 532 } 533 dest_scan++; 534 src_scan += 3; 535 } 536 } else { 537 for (int col = 0; col < pixel_count; col++) { 538 int src_alpha = src_scan[3]; 539 if (clip_scan) 540 src_alpha = clip_scan[col] * src_alpha / 255; 541 542 if (src_alpha) { 543 if (pIccTransform) 544 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 545 else 546 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 547 548 if (bNonseparableBlend) 549 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 550 else 551 gray = Blend(blend_type, *dest_scan, gray); 552 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 553 } 554 dest_scan++; 555 src_scan += 4; 556 } 557 } 558 return; 559 } 560 if (src_alpha_scan) { 561 for (int col = 0; col < pixel_count; col++) { 562 int src_alpha = *src_alpha_scan++; 563 if (clip_scan) 564 src_alpha = clip_scan[col] * src_alpha / 255; 565 566 if (src_alpha) { 567 if (pIccTransform) 568 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 569 else 570 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 571 572 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 573 } 574 dest_scan++; 575 src_scan += 3; 576 } 577 } else { 578 for (int col = 0; col < pixel_count; col++) { 579 int src_alpha = src_scan[3]; 580 if (clip_scan) 581 src_alpha = clip_scan[col] * src_alpha / 255; 582 583 if (src_alpha) { 584 if (pIccTransform) 585 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 586 else 587 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 588 589 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 590 } 591 dest_scan++; 592 src_scan += 4; 593 } 594 } 595 } 596 597 void CompositeRow_Rgb2Gray(uint8_t* dest_scan, 598 const uint8_t* src_scan, 599 int src_Bpp, 600 int pixel_count, 601 int blend_type, 602 const uint8_t* clip_scan, 603 void* pIccTransform) { 604 CCodec_IccModule* pIccModule = nullptr; 605 uint8_t gray; 606 if (pIccTransform) { 607 pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 608 } 609 if (blend_type) { 610 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 611 for (int col = 0; col < pixel_count; col++) { 612 if (pIccTransform) { 613 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 614 } else { 615 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 616 } 617 if (bNonseparableBlend) 618 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 619 else 620 gray = Blend(blend_type, *dest_scan, gray); 621 if (clip_scan && clip_scan[col] < 255) { 622 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 623 } else { 624 *dest_scan = gray; 625 } 626 dest_scan++; 627 src_scan += src_Bpp; 628 } 629 return; 630 } 631 for (int col = 0; col < pixel_count; col++) { 632 if (pIccTransform) { 633 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 634 } else { 635 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 636 } 637 if (clip_scan && clip_scan[col] < 255) { 638 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 639 } else { 640 *dest_scan = gray; 641 } 642 dest_scan++; 643 src_scan += src_Bpp; 644 } 645 } 646 647 void CompositeRow_Rgb2Graya(uint8_t* dest_scan, 648 const uint8_t* src_scan, 649 int src_Bpp, 650 int pixel_count, 651 int blend_type, 652 const uint8_t* clip_scan, 653 uint8_t* dest_alpha_scan, 654 void* pIccTransform) { 655 CCodec_IccModule* pIccModule = nullptr; 656 if (pIccTransform) { 657 pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 658 } 659 if (blend_type) { 660 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 661 for (int col = 0; col < pixel_count; col++) { 662 int back_alpha = *dest_alpha_scan; 663 if (back_alpha == 0) { 664 if (pIccTransform) { 665 pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1); 666 } else { 667 *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 668 } 669 dest_scan++; 670 dest_alpha_scan++; 671 src_scan += src_Bpp; 672 continue; 673 } 674 int src_alpha = 255; 675 if (clip_scan) { 676 src_alpha = clip_scan[col]; 677 } 678 if (src_alpha == 0) { 679 dest_scan++; 680 dest_alpha_scan++; 681 src_scan += src_Bpp; 682 continue; 683 } 684 uint8_t dest_alpha = 685 back_alpha + src_alpha - back_alpha * src_alpha / 255; 686 *dest_alpha_scan++ = dest_alpha; 687 int alpha_ratio = src_alpha * 255 / dest_alpha; 688 uint8_t gray; 689 if (pIccTransform) { 690 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 691 } else { 692 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 693 } 694 if (bNonseparableBlend) 695 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 696 else 697 gray = Blend(blend_type, *dest_scan, gray); 698 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 699 dest_scan++; 700 src_scan += src_Bpp; 701 } 702 return; 703 } 704 for (int col = 0; col < pixel_count; col++) { 705 int src_alpha = 255; 706 if (clip_scan) { 707 src_alpha = clip_scan[col]; 708 } 709 if (src_alpha == 255) { 710 if (pIccTransform) { 711 pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1); 712 } else { 713 *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 714 } 715 dest_scan++; 716 *dest_alpha_scan++ = 255; 717 src_scan += src_Bpp; 718 continue; 719 } 720 if (src_alpha == 0) { 721 dest_scan++; 722 dest_alpha_scan++; 723 src_scan += src_Bpp; 724 continue; 725 } 726 int back_alpha = *dest_alpha_scan; 727 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 728 *dest_alpha_scan++ = dest_alpha; 729 int alpha_ratio = src_alpha * 255 / dest_alpha; 730 uint8_t gray; 731 if (pIccTransform) { 732 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); 733 } else { 734 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 735 } 736 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 737 dest_scan++; 738 src_scan += src_Bpp; 739 } 740 } 741 742 void CompositeRow_Argb2Argb(uint8_t* dest_scan, 743 const uint8_t* src_scan, 744 int pixel_count, 745 int blend_type, 746 const uint8_t* clip_scan, 747 uint8_t* dest_alpha_scan, 748 const uint8_t* src_alpha_scan) { 749 int blended_colors[3]; 750 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 751 if (!dest_alpha_scan) { 752 if (!src_alpha_scan) { 753 uint8_t back_alpha = 0; 754 for (int col = 0; col < pixel_count; col++) { 755 back_alpha = dest_scan[3]; 756 if (back_alpha == 0) { 757 if (clip_scan) { 758 int src_alpha = clip_scan[col] * src_scan[3] / 255; 759 FXARGB_SETDIB(dest_scan, (FXARGB_GETDIB(src_scan) & 0xffffff) | 760 (src_alpha << 24)); 761 } else { 762 FXARGB_COPY(dest_scan, src_scan); 763 } 764 dest_scan += 4; 765 src_scan += 4; 766 continue; 767 } 768 uint8_t src_alpha; 769 if (clip_scan) { 770 src_alpha = clip_scan[col] * src_scan[3] / 255; 771 } else { 772 src_alpha = src_scan[3]; 773 } 774 if (src_alpha == 0) { 775 dest_scan += 4; 776 src_scan += 4; 777 continue; 778 } 779 uint8_t dest_alpha = 780 back_alpha + src_alpha - back_alpha * src_alpha / 255; 781 dest_scan[3] = dest_alpha; 782 int alpha_ratio = src_alpha * 255 / dest_alpha; 783 if (bNonseparableBlend) { 784 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 785 } 786 for (int color = 0; color < 3; color++) { 787 if (blend_type) { 788 int blended = bNonseparableBlend 789 ? blended_colors[color] 790 : Blend(blend_type, *dest_scan, *src_scan); 791 blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); 792 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 793 } else { 794 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); 795 } 796 dest_scan++; 797 src_scan++; 798 } 799 dest_scan++; 800 src_scan++; 801 } 802 } else { 803 for (int col = 0; col < pixel_count; col++) { 804 uint8_t back_alpha = dest_scan[3]; 805 if (back_alpha == 0) { 806 if (clip_scan) { 807 int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255; 808 FXARGB_SETDIB(dest_scan, FXARGB_MAKE((src_alpha << 24), src_scan[2], 809 src_scan[1], *src_scan)); 810 } else { 811 FXARGB_SETDIB(dest_scan, 812 FXARGB_MAKE((*src_alpha_scan << 24), src_scan[2], 813 src_scan[1], *src_scan)); 814 } 815 dest_scan += 4; 816 src_scan += 3; 817 src_alpha_scan++; 818 continue; 819 } 820 uint8_t src_alpha; 821 if (clip_scan) { 822 src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255; 823 } else { 824 src_alpha = *src_alpha_scan++; 825 } 826 if (src_alpha == 0) { 827 dest_scan += 4; 828 src_scan += 3; 829 continue; 830 } 831 uint8_t dest_alpha = 832 back_alpha + src_alpha - back_alpha * src_alpha / 255; 833 dest_scan[3] = dest_alpha; 834 int alpha_ratio = src_alpha * 255 / dest_alpha; 835 if (bNonseparableBlend) { 836 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 837 } 838 for (int color = 0; color < 3; color++) { 839 if (blend_type) { 840 int blended = bNonseparableBlend 841 ? blended_colors[color] 842 : Blend(blend_type, *dest_scan, *src_scan); 843 blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); 844 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 845 } else { 846 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); 847 } 848 dest_scan++; 849 src_scan++; 850 } 851 dest_scan++; 852 } 853 } 854 } else { 855 if (src_alpha_scan) { 856 for (int col = 0; col < pixel_count; col++) { 857 uint8_t back_alpha = *dest_alpha_scan; 858 if (back_alpha == 0) { 859 if (clip_scan) { 860 int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255; 861 *dest_alpha_scan = src_alpha; 862 *dest_scan++ = *src_scan++; 863 *dest_scan++ = *src_scan++; 864 *dest_scan++ = *src_scan++; 865 } else { 866 *dest_alpha_scan = *src_alpha_scan; 867 *dest_scan++ = *src_scan++; 868 *dest_scan++ = *src_scan++; 869 *dest_scan++ = *src_scan++; 870 } 871 dest_alpha_scan++; 872 src_alpha_scan++; 873 continue; 874 } 875 uint8_t src_alpha; 876 if (clip_scan) { 877 src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255; 878 } else { 879 src_alpha = *src_alpha_scan++; 880 } 881 if (src_alpha == 0) { 882 dest_scan += 3; 883 src_scan += 3; 884 dest_alpha_scan++; 885 continue; 886 } 887 uint8_t dest_alpha = 888 back_alpha + src_alpha - back_alpha * src_alpha / 255; 889 *dest_alpha_scan++ = dest_alpha; 890 int alpha_ratio = src_alpha * 255 / dest_alpha; 891 if (bNonseparableBlend) { 892 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 893 } 894 for (int color = 0; color < 3; color++) { 895 if (blend_type) { 896 int blended = bNonseparableBlend 897 ? blended_colors[color] 898 : Blend(blend_type, *dest_scan, *src_scan); 899 blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); 900 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 901 } else { 902 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); 903 } 904 dest_scan++; 905 src_scan++; 906 } 907 } 908 } else { 909 for (int col = 0; col < pixel_count; col++) { 910 uint8_t back_alpha = *dest_alpha_scan; 911 if (back_alpha == 0) { 912 if (clip_scan) { 913 int src_alpha = clip_scan[col] * src_scan[3] / 255; 914 *dest_alpha_scan = src_alpha; 915 *dest_scan++ = *src_scan++; 916 *dest_scan++ = *src_scan++; 917 *dest_scan++ = *src_scan++; 918 } else { 919 *dest_alpha_scan = src_scan[3]; 920 *dest_scan++ = *src_scan++; 921 *dest_scan++ = *src_scan++; 922 *dest_scan++ = *src_scan++; 923 } 924 dest_alpha_scan++; 925 src_scan++; 926 continue; 927 } 928 uint8_t src_alpha; 929 if (clip_scan) { 930 src_alpha = clip_scan[col] * src_scan[3] / 255; 931 } else { 932 src_alpha = src_scan[3]; 933 } 934 if (src_alpha == 0) { 935 dest_scan += 3; 936 src_scan += 4; 937 dest_alpha_scan++; 938 continue; 939 } 940 uint8_t dest_alpha = 941 back_alpha + src_alpha - back_alpha * src_alpha / 255; 942 *dest_alpha_scan++ = dest_alpha; 943 int alpha_ratio = src_alpha * 255 / dest_alpha; 944 if (bNonseparableBlend) { 945 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 946 } 947 for (int color = 0; color < 3; color++) { 948 if (blend_type) { 949 int blended = bNonseparableBlend 950 ? blended_colors[color] 951 : Blend(blend_type, *dest_scan, *src_scan); 952 blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); 953 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 954 } else { 955 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); 956 } 957 dest_scan++; 958 src_scan++; 959 } 960 src_scan++; 961 } 962 } 963 } 964 } 965 966 void CompositeRow_Rgb2Argb_Blend_NoClip(uint8_t* dest_scan, 967 const uint8_t* src_scan, 968 int width, 969 int blend_type, 970 int src_Bpp, 971 uint8_t* dest_alpha_scan) { 972 int blended_colors[3]; 973 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 974 int src_gap = src_Bpp - 3; 975 if (dest_alpha_scan) { 976 for (int col = 0; col < width; col++) { 977 uint8_t back_alpha = *dest_alpha_scan; 978 if (back_alpha == 0) { 979 *dest_scan++ = *src_scan++; 980 *dest_scan++ = *src_scan++; 981 *dest_scan++ = *src_scan++; 982 *dest_alpha_scan++ = 0xff; 983 src_scan += src_gap; 984 continue; 985 } 986 *dest_alpha_scan++ = 0xff; 987 if (bNonseparableBlend) { 988 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 989 } 990 for (int color = 0; color < 3; color++) { 991 int src_color = *src_scan; 992 int blended = bNonseparableBlend 993 ? blended_colors[color] 994 : Blend(blend_type, *dest_scan, src_color); 995 *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 996 dest_scan++; 997 src_scan++; 998 } 999 src_scan += src_gap; 1000 } 1001 } else { 1002 for (int col = 0; col < width; col++) { 1003 uint8_t back_alpha = dest_scan[3]; 1004 if (back_alpha == 0) { 1005 if (src_Bpp == 4) { 1006 FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); 1007 } else { 1008 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], 1009 src_scan[0])); 1010 } 1011 dest_scan += 4; 1012 src_scan += src_Bpp; 1013 continue; 1014 } 1015 dest_scan[3] = 0xff; 1016 if (bNonseparableBlend) { 1017 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 1018 } 1019 for (int color = 0; color < 3; color++) { 1020 int src_color = *src_scan; 1021 int blended = bNonseparableBlend 1022 ? blended_colors[color] 1023 : Blend(blend_type, *dest_scan, src_color); 1024 *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 1025 dest_scan++; 1026 src_scan++; 1027 } 1028 dest_scan++; 1029 src_scan += src_gap; 1030 } 1031 } 1032 } 1033 1034 void CompositeRow_Rgb2Argb_Blend_Clip(uint8_t* dest_scan, 1035 const uint8_t* src_scan, 1036 int width, 1037 int blend_type, 1038 int src_Bpp, 1039 const uint8_t* clip_scan, 1040 uint8_t* dest_alpha_scan) { 1041 int blended_colors[3]; 1042 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1043 int src_gap = src_Bpp - 3; 1044 if (dest_alpha_scan) { 1045 for (int col = 0; col < width; col++) { 1046 int src_alpha = *clip_scan++; 1047 uint8_t back_alpha = *dest_alpha_scan; 1048 if (back_alpha == 0) { 1049 *dest_scan++ = *src_scan++; 1050 *dest_scan++ = *src_scan++; 1051 *dest_scan++ = *src_scan++; 1052 src_scan += src_gap; 1053 dest_alpha_scan++; 1054 continue; 1055 } 1056 if (src_alpha == 0) { 1057 dest_scan += 3; 1058 dest_alpha_scan++; 1059 src_scan += src_Bpp; 1060 continue; 1061 } 1062 uint8_t dest_alpha = 1063 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1064 *dest_alpha_scan++ = dest_alpha; 1065 int alpha_ratio = src_alpha * 255 / dest_alpha; 1066 if (bNonseparableBlend) { 1067 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 1068 } 1069 for (int color = 0; color < 3; color++) { 1070 int src_color = *src_scan; 1071 int blended = bNonseparableBlend 1072 ? blended_colors[color] 1073 : Blend(blend_type, *dest_scan, src_color); 1074 blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 1075 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1076 dest_scan++; 1077 src_scan++; 1078 } 1079 src_scan += src_gap; 1080 } 1081 } else { 1082 for (int col = 0; col < width; col++) { 1083 int src_alpha = *clip_scan++; 1084 uint8_t back_alpha = dest_scan[3]; 1085 if (back_alpha == 0) { 1086 *dest_scan++ = *src_scan++; 1087 *dest_scan++ = *src_scan++; 1088 *dest_scan++ = *src_scan++; 1089 src_scan += src_gap; 1090 dest_scan++; 1091 continue; 1092 } 1093 if (src_alpha == 0) { 1094 dest_scan += 4; 1095 src_scan += src_Bpp; 1096 continue; 1097 } 1098 uint8_t dest_alpha = 1099 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1100 dest_scan[3] = dest_alpha; 1101 int alpha_ratio = src_alpha * 255 / dest_alpha; 1102 if (bNonseparableBlend) { 1103 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 1104 } 1105 for (int color = 0; color < 3; color++) { 1106 int src_color = *src_scan; 1107 int blended = bNonseparableBlend 1108 ? blended_colors[color] 1109 : Blend(blend_type, *dest_scan, src_color); 1110 blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 1111 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1112 dest_scan++; 1113 src_scan++; 1114 } 1115 dest_scan++; 1116 src_scan += src_gap; 1117 } 1118 } 1119 } 1120 1121 void CompositeRow_Rgb2Argb_NoBlend_Clip(uint8_t* dest_scan, 1122 const uint8_t* src_scan, 1123 int width, 1124 int src_Bpp, 1125 const uint8_t* clip_scan, 1126 uint8_t* dest_alpha_scan) { 1127 int src_gap = src_Bpp - 3; 1128 if (dest_alpha_scan) { 1129 for (int col = 0; col < width; col++) { 1130 int src_alpha = clip_scan[col]; 1131 if (src_alpha == 255) { 1132 *dest_scan++ = *src_scan++; 1133 *dest_scan++ = *src_scan++; 1134 *dest_scan++ = *src_scan++; 1135 *dest_alpha_scan++ = 255; 1136 src_scan += src_gap; 1137 continue; 1138 } 1139 if (src_alpha == 0) { 1140 dest_scan += 3; 1141 dest_alpha_scan++; 1142 src_scan += src_Bpp; 1143 continue; 1144 } 1145 int back_alpha = *dest_alpha_scan; 1146 uint8_t dest_alpha = 1147 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1148 *dest_alpha_scan++ = dest_alpha; 1149 int alpha_ratio = src_alpha * 255 / dest_alpha; 1150 for (int color = 0; color < 3; color++) { 1151 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); 1152 dest_scan++; 1153 src_scan++; 1154 } 1155 src_scan += src_gap; 1156 } 1157 } else { 1158 for (int col = 0; col < width; col++) { 1159 int src_alpha = clip_scan[col]; 1160 if (src_alpha == 255) { 1161 *dest_scan++ = *src_scan++; 1162 *dest_scan++ = *src_scan++; 1163 *dest_scan++ = *src_scan++; 1164 *dest_scan++ = 255; 1165 src_scan += src_gap; 1166 continue; 1167 } 1168 if (src_alpha == 0) { 1169 dest_scan += 4; 1170 src_scan += src_Bpp; 1171 continue; 1172 } 1173 int back_alpha = dest_scan[3]; 1174 uint8_t dest_alpha = 1175 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1176 dest_scan[3] = dest_alpha; 1177 int alpha_ratio = src_alpha * 255 / dest_alpha; 1178 for (int color = 0; color < 3; color++) { 1179 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); 1180 dest_scan++; 1181 src_scan++; 1182 } 1183 dest_scan++; 1184 src_scan += src_gap; 1185 } 1186 } 1187 } 1188 1189 void CompositeRow_Rgb2Argb_NoBlend_NoClip(uint8_t* dest_scan, 1190 const uint8_t* src_scan, 1191 int width, 1192 int src_Bpp, 1193 uint8_t* dest_alpha_scan) { 1194 if (dest_alpha_scan) { 1195 int src_gap = src_Bpp - 3; 1196 for (int col = 0; col < width; col++) { 1197 *dest_scan++ = *src_scan++; 1198 *dest_scan++ = *src_scan++; 1199 *dest_scan++ = *src_scan++; 1200 *dest_alpha_scan++ = 0xff; 1201 src_scan += src_gap; 1202 } 1203 } else { 1204 for (int col = 0; col < width; col++) { 1205 if (src_Bpp == 4) { 1206 FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); 1207 } else { 1208 FXARGB_SETDIB(dest_scan, 1209 FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0])); 1210 } 1211 dest_scan += 4; 1212 src_scan += src_Bpp; 1213 } 1214 } 1215 } 1216 1217 void CompositeRow_Argb2Rgb_Blend(uint8_t* dest_scan, 1218 const uint8_t* src_scan, 1219 int width, 1220 int blend_type, 1221 int dest_Bpp, 1222 const uint8_t* clip_scan, 1223 const uint8_t* src_alpha_scan) { 1224 int blended_colors[3]; 1225 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1226 int dest_gap = dest_Bpp - 3; 1227 if (src_alpha_scan) { 1228 for (int col = 0; col < width; col++) { 1229 uint8_t src_alpha; 1230 if (clip_scan) { 1231 src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; 1232 } else { 1233 src_alpha = *src_alpha_scan++; 1234 } 1235 if (src_alpha == 0) { 1236 dest_scan += dest_Bpp; 1237 src_scan += 3; 1238 continue; 1239 } 1240 if (bNonseparableBlend) { 1241 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 1242 } 1243 for (int color = 0; color < 3; color++) { 1244 int back_color = *dest_scan; 1245 int blended = bNonseparableBlend 1246 ? blended_colors[color] 1247 : Blend(blend_type, back_color, *src_scan); 1248 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 1249 dest_scan++; 1250 src_scan++; 1251 } 1252 dest_scan += dest_gap; 1253 } 1254 } else { 1255 for (int col = 0; col < width; col++) { 1256 uint8_t src_alpha; 1257 if (clip_scan) { 1258 src_alpha = src_scan[3] * (*clip_scan++) / 255; 1259 } else { 1260 src_alpha = src_scan[3]; 1261 } 1262 if (src_alpha == 0) { 1263 dest_scan += dest_Bpp; 1264 src_scan += 4; 1265 continue; 1266 } 1267 if (bNonseparableBlend) { 1268 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 1269 } 1270 for (int color = 0; color < 3; color++) { 1271 int back_color = *dest_scan; 1272 int blended = bNonseparableBlend 1273 ? blended_colors[color] 1274 : Blend(blend_type, back_color, *src_scan); 1275 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 1276 dest_scan++; 1277 src_scan++; 1278 } 1279 dest_scan += dest_gap; 1280 src_scan++; 1281 } 1282 } 1283 } 1284 1285 void CompositeRow_Argb2Rgb_NoBlend(uint8_t* dest_scan, 1286 const uint8_t* src_scan, 1287 int width, 1288 int dest_Bpp, 1289 const uint8_t* clip_scan, 1290 const uint8_t* src_alpha_scan) { 1291 int dest_gap = dest_Bpp - 3; 1292 if (src_alpha_scan) { 1293 for (int col = 0; col < width; col++) { 1294 uint8_t src_alpha; 1295 if (clip_scan) { 1296 src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; 1297 } else { 1298 src_alpha = *src_alpha_scan++; 1299 } 1300 if (src_alpha == 255) { 1301 *dest_scan++ = *src_scan++; 1302 *dest_scan++ = *src_scan++; 1303 *dest_scan++ = *src_scan++; 1304 dest_scan += dest_gap; 1305 continue; 1306 } 1307 if (src_alpha == 0) { 1308 dest_scan += dest_Bpp; 1309 src_scan += 3; 1310 continue; 1311 } 1312 for (int color = 0; color < 3; color++) { 1313 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 1314 dest_scan++; 1315 src_scan++; 1316 } 1317 dest_scan += dest_gap; 1318 } 1319 } else { 1320 for (int col = 0; col < width; col++) { 1321 uint8_t src_alpha; 1322 if (clip_scan) { 1323 src_alpha = src_scan[3] * (*clip_scan++) / 255; 1324 } else { 1325 src_alpha = src_scan[3]; 1326 } 1327 if (src_alpha == 255) { 1328 *dest_scan++ = *src_scan++; 1329 *dest_scan++ = *src_scan++; 1330 *dest_scan++ = *src_scan++; 1331 dest_scan += dest_gap; 1332 src_scan++; 1333 continue; 1334 } 1335 if (src_alpha == 0) { 1336 dest_scan += dest_Bpp; 1337 src_scan += 4; 1338 continue; 1339 } 1340 for (int color = 0; color < 3; color++) { 1341 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 1342 dest_scan++; 1343 src_scan++; 1344 } 1345 dest_scan += dest_gap; 1346 src_scan++; 1347 } 1348 } 1349 } 1350 1351 void CompositeRow_Rgb2Rgb_Blend_NoClip(uint8_t* dest_scan, 1352 const uint8_t* src_scan, 1353 int width, 1354 int blend_type, 1355 int dest_Bpp, 1356 int src_Bpp) { 1357 int blended_colors[3]; 1358 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1359 int dest_gap = dest_Bpp - 3; 1360 int src_gap = src_Bpp - 3; 1361 for (int col = 0; col < width; col++) { 1362 if (bNonseparableBlend) { 1363 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 1364 } 1365 for (int color = 0; color < 3; color++) { 1366 int back_color = *dest_scan; 1367 int src_color = *src_scan; 1368 int blended = bNonseparableBlend 1369 ? blended_colors[color] 1370 : Blend(blend_type, back_color, src_color); 1371 *dest_scan = blended; 1372 dest_scan++; 1373 src_scan++; 1374 } 1375 dest_scan += dest_gap; 1376 src_scan += src_gap; 1377 } 1378 } 1379 1380 void CompositeRow_Rgb2Rgb_Blend_Clip(uint8_t* dest_scan, 1381 const uint8_t* src_scan, 1382 int width, 1383 int blend_type, 1384 int dest_Bpp, 1385 int src_Bpp, 1386 const uint8_t* clip_scan) { 1387 int blended_colors[3]; 1388 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1389 int dest_gap = dest_Bpp - 3; 1390 int src_gap = src_Bpp - 3; 1391 for (int col = 0; col < width; col++) { 1392 uint8_t src_alpha = *clip_scan++; 1393 if (src_alpha == 0) { 1394 dest_scan += dest_Bpp; 1395 src_scan += src_Bpp; 1396 continue; 1397 } 1398 if (bNonseparableBlend) { 1399 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 1400 } 1401 for (int color = 0; color < 3; color++) { 1402 int src_color = *src_scan; 1403 int back_color = *dest_scan; 1404 int blended = bNonseparableBlend 1405 ? blended_colors[color] 1406 : Blend(blend_type, back_color, src_color); 1407 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 1408 dest_scan++; 1409 src_scan++; 1410 } 1411 dest_scan += dest_gap; 1412 src_scan += src_gap; 1413 } 1414 } 1415 1416 void CompositeRow_Rgb2Rgb_NoBlend_NoClip(uint8_t* dest_scan, 1417 const uint8_t* src_scan, 1418 int width, 1419 int dest_Bpp, 1420 int src_Bpp) { 1421 if (dest_Bpp == src_Bpp) { 1422 FXSYS_memcpy(dest_scan, src_scan, width * dest_Bpp); 1423 return; 1424 } 1425 for (int col = 0; col < width; col++) { 1426 dest_scan[0] = src_scan[0]; 1427 dest_scan[1] = src_scan[1]; 1428 dest_scan[2] = src_scan[2]; 1429 dest_scan += dest_Bpp; 1430 src_scan += src_Bpp; 1431 } 1432 } 1433 1434 void CompositeRow_Rgb2Rgb_NoBlend_Clip(uint8_t* dest_scan, 1435 const uint8_t* src_scan, 1436 int width, 1437 int dest_Bpp, 1438 int src_Bpp, 1439 const uint8_t* clip_scan) { 1440 for (int col = 0; col < width; col++) { 1441 int src_alpha = clip_scan[col]; 1442 if (src_alpha == 255) { 1443 dest_scan[0] = src_scan[0]; 1444 dest_scan[1] = src_scan[1]; 1445 dest_scan[2] = src_scan[2]; 1446 } else if (src_alpha) { 1447 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 1448 dest_scan++; 1449 src_scan++; 1450 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 1451 dest_scan++; 1452 src_scan++; 1453 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 1454 dest_scan += dest_Bpp - 2; 1455 src_scan += src_Bpp - 2; 1456 continue; 1457 } 1458 dest_scan += dest_Bpp; 1459 src_scan += src_Bpp; 1460 } 1461 } 1462 1463 void CompositeRow_Argb2Argb_Transform(uint8_t* dest_scan, 1464 const uint8_t* src_scan, 1465 int pixel_count, 1466 int blend_type, 1467 const uint8_t* clip_scan, 1468 uint8_t* dest_alpha_scan, 1469 const uint8_t* src_alpha_scan, 1470 uint8_t* src_cache_scan, 1471 void* pIccTransform) { 1472 uint8_t* dp = src_cache_scan; 1473 CCodec_IccModule* pIccModule = 1474 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1475 if (src_alpha_scan) { 1476 if (dest_alpha_scan) { 1477 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, pixel_count); 1478 } else { 1479 for (int col = 0; col < pixel_count; col++) { 1480 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1481 dp[3] = *src_alpha_scan++; 1482 src_scan += 3; 1483 dp += 4; 1484 } 1485 src_alpha_scan = nullptr; 1486 } 1487 } else { 1488 if (dest_alpha_scan) { 1489 int blended_colors[3]; 1490 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1491 for (int col = 0; col < pixel_count; col++) { 1492 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1493 1); 1494 uint8_t back_alpha = *dest_alpha_scan; 1495 if (back_alpha == 0) { 1496 if (clip_scan) { 1497 int src_alpha = clip_scan[col] * src_scan[3] / 255; 1498 *dest_alpha_scan = src_alpha; 1499 *dest_scan++ = *src_cache_scan++; 1500 *dest_scan++ = *src_cache_scan++; 1501 *dest_scan++ = *src_cache_scan++; 1502 } else { 1503 *dest_alpha_scan = src_scan[3]; 1504 *dest_scan++ = *src_cache_scan++; 1505 *dest_scan++ = *src_cache_scan++; 1506 *dest_scan++ = *src_cache_scan++; 1507 } 1508 dest_alpha_scan++; 1509 src_scan += 4; 1510 continue; 1511 } 1512 uint8_t src_alpha; 1513 if (clip_scan) { 1514 src_alpha = clip_scan[col] * src_scan[3] / 255; 1515 } else { 1516 src_alpha = src_scan[3]; 1517 } 1518 src_scan += 4; 1519 if (src_alpha == 0) { 1520 dest_scan += 3; 1521 src_cache_scan += 3; 1522 dest_alpha_scan++; 1523 continue; 1524 } 1525 uint8_t dest_alpha = 1526 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1527 *dest_alpha_scan++ = dest_alpha; 1528 int alpha_ratio = src_alpha * 255 / dest_alpha; 1529 if (bNonseparableBlend) { 1530 RGB_Blend(blend_type, src_cache_scan, dest_scan, blended_colors); 1531 } 1532 for (int color = 0; color < 3; color++) { 1533 if (blend_type) { 1534 int blended = bNonseparableBlend 1535 ? blended_colors[color] 1536 : Blend(blend_type, *dest_scan, *src_cache_scan); 1537 blended = FXDIB_ALPHA_MERGE(*src_cache_scan, blended, back_alpha); 1538 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1539 } else { 1540 *dest_scan = 1541 FXDIB_ALPHA_MERGE(*dest_scan, *src_cache_scan, alpha_ratio); 1542 } 1543 dest_scan++; 1544 src_cache_scan++; 1545 } 1546 } 1547 return; 1548 } 1549 for (int col = 0; col < pixel_count; col++) { 1550 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1551 dp[3] = src_scan[3]; 1552 src_scan += 4; 1553 dp += 4; 1554 } 1555 } 1556 CompositeRow_Argb2Argb(dest_scan, src_cache_scan, pixel_count, blend_type, 1557 clip_scan, dest_alpha_scan, src_alpha_scan); 1558 } 1559 1560 void CompositeRow_Rgb2Argb_Blend_NoClip_Transform(uint8_t* dest_scan, 1561 const uint8_t* src_scan, 1562 int width, 1563 int blend_type, 1564 int src_Bpp, 1565 uint8_t* dest_alpha_scan, 1566 uint8_t* src_cache_scan, 1567 void* pIccTransform) { 1568 CCodec_IccModule* pIccModule = 1569 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1570 if (src_Bpp == 3) { 1571 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1572 width); 1573 } else { 1574 uint8_t* dp = src_cache_scan; 1575 for (int col = 0; col < width; col++) { 1576 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1577 src_scan += 4; 1578 dp += 3; 1579 } 1580 } 1581 CompositeRow_Rgb2Argb_Blend_NoClip(dest_scan, src_cache_scan, width, 1582 blend_type, 3, dest_alpha_scan); 1583 } 1584 1585 void CompositeRow_Rgb2Argb_Blend_Clip_Transform(uint8_t* dest_scan, 1586 const uint8_t* src_scan, 1587 int width, 1588 int blend_type, 1589 int src_Bpp, 1590 const uint8_t* clip_scan, 1591 uint8_t* dest_alpha_scan, 1592 uint8_t* src_cache_scan, 1593 void* pIccTransform) { 1594 CCodec_IccModule* pIccModule = 1595 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1596 if (src_Bpp == 3) { 1597 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1598 width); 1599 } else { 1600 uint8_t* dp = src_cache_scan; 1601 for (int col = 0; col < width; col++) { 1602 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1603 src_scan += 4; 1604 dp += 3; 1605 } 1606 } 1607 CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_cache_scan, width, blend_type, 1608 3, clip_scan, dest_alpha_scan); 1609 } 1610 1611 void CompositeRow_Rgb2Argb_NoBlend_Clip_Transform(uint8_t* dest_scan, 1612 const uint8_t* src_scan, 1613 int width, 1614 int src_Bpp, 1615 const uint8_t* clip_scan, 1616 uint8_t* dest_alpha_scan, 1617 uint8_t* src_cache_scan, 1618 void* pIccTransform) { 1619 CCodec_IccModule* pIccModule = 1620 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1621 if (src_Bpp == 3) { 1622 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1623 width); 1624 } else { 1625 uint8_t* dp = src_cache_scan; 1626 for (int col = 0; col < width; col++) { 1627 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1628 src_scan += 4; 1629 dp += 3; 1630 } 1631 } 1632 CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_cache_scan, width, 3, 1633 clip_scan, dest_alpha_scan); 1634 } 1635 1636 void CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform(uint8_t* dest_scan, 1637 const uint8_t* src_scan, 1638 int width, 1639 int src_Bpp, 1640 uint8_t* dest_alpha_scan, 1641 uint8_t* src_cache_scan, 1642 void* pIccTransform) { 1643 CCodec_IccModule* pIccModule = 1644 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1645 if (src_Bpp == 3) { 1646 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1647 width); 1648 } else { 1649 uint8_t* dp = src_cache_scan; 1650 for (int col = 0; col < width; col++) { 1651 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1652 src_scan += 4; 1653 dp += 3; 1654 } 1655 } 1656 CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_cache_scan, width, 3, 1657 dest_alpha_scan); 1658 } 1659 1660 void CompositeRow_Argb2Rgb_Blend_Transform(uint8_t* dest_scan, 1661 const uint8_t* src_scan, 1662 int width, 1663 int blend_type, 1664 int dest_Bpp, 1665 const uint8_t* clip_scan, 1666 const uint8_t* src_alpha_scan, 1667 uint8_t* src_cache_scan, 1668 void* pIccTransform) { 1669 CCodec_IccModule* pIccModule = 1670 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1671 if (src_alpha_scan) { 1672 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1673 width); 1674 } else { 1675 int blended_colors[3]; 1676 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1677 int dest_gap = dest_Bpp - 3; 1678 for (int col = 0; col < width; col++) { 1679 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1); 1680 uint8_t src_alpha; 1681 if (clip_scan) { 1682 src_alpha = src_scan[3] * (*clip_scan++) / 255; 1683 } else { 1684 src_alpha = src_scan[3]; 1685 } 1686 src_scan += 4; 1687 if (src_alpha == 0) { 1688 dest_scan += dest_Bpp; 1689 src_cache_scan += 3; 1690 continue; 1691 } 1692 if (bNonseparableBlend) { 1693 RGB_Blend(blend_type, src_cache_scan, dest_scan, blended_colors); 1694 } 1695 for (int color = 0; color < 3; color++) { 1696 int back_color = *dest_scan; 1697 int blended = bNonseparableBlend 1698 ? blended_colors[color] 1699 : Blend(blend_type, back_color, *src_cache_scan); 1700 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 1701 dest_scan++; 1702 src_cache_scan++; 1703 } 1704 dest_scan += dest_gap; 1705 } 1706 return; 1707 } 1708 CompositeRow_Argb2Rgb_Blend(dest_scan, src_cache_scan, width, blend_type, 1709 dest_Bpp, clip_scan, src_alpha_scan); 1710 } 1711 1712 void CompositeRow_Argb2Rgb_NoBlend_Transform(uint8_t* dest_scan, 1713 const uint8_t* src_scan, 1714 int width, 1715 int dest_Bpp, 1716 const uint8_t* clip_scan, 1717 const uint8_t* src_alpha_scan, 1718 uint8_t* src_cache_scan, 1719 void* pIccTransform) { 1720 CCodec_IccModule* pIccModule = 1721 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1722 if (src_alpha_scan) { 1723 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1724 width); 1725 } else { 1726 int dest_gap = dest_Bpp - 3; 1727 for (int col = 0; col < width; col++) { 1728 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1); 1729 uint8_t src_alpha; 1730 if (clip_scan) { 1731 src_alpha = src_scan[3] * (*clip_scan++) / 255; 1732 } else { 1733 src_alpha = src_scan[3]; 1734 } 1735 src_scan += 4; 1736 if (src_alpha == 255) { 1737 *dest_scan++ = *src_cache_scan++; 1738 *dest_scan++ = *src_cache_scan++; 1739 *dest_scan++ = *src_cache_scan++; 1740 dest_scan += dest_gap; 1741 continue; 1742 } 1743 if (src_alpha == 0) { 1744 dest_scan += dest_Bpp; 1745 src_cache_scan += 3; 1746 continue; 1747 } 1748 for (int color = 0; color < 3; color++) { 1749 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_cache_scan, src_alpha); 1750 dest_scan++; 1751 src_cache_scan++; 1752 } 1753 dest_scan += dest_gap; 1754 } 1755 return; 1756 } 1757 CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_cache_scan, width, dest_Bpp, 1758 clip_scan, src_alpha_scan); 1759 } 1760 1761 void CompositeRow_Rgb2Rgb_Blend_NoClip_Transform(uint8_t* dest_scan, 1762 const uint8_t* src_scan, 1763 int width, 1764 int blend_type, 1765 int dest_Bpp, 1766 int src_Bpp, 1767 uint8_t* src_cache_scan, 1768 void* pIccTransform) { 1769 CCodec_IccModule* pIccModule = 1770 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1771 if (src_Bpp == 3) { 1772 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1773 width); 1774 } else { 1775 uint8_t* dp = src_cache_scan; 1776 for (int col = 0; col < width; col++) { 1777 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1778 src_scan += 4; 1779 dp += 3; 1780 } 1781 } 1782 CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_cache_scan, width, 1783 blend_type, dest_Bpp, 3); 1784 } 1785 1786 void CompositeRow_Rgb2Rgb_Blend_Clip_Transform(uint8_t* dest_scan, 1787 const uint8_t* src_scan, 1788 int width, 1789 int blend_type, 1790 int dest_Bpp, 1791 int src_Bpp, 1792 const uint8_t* clip_scan, 1793 uint8_t* src_cache_scan, 1794 void* pIccTransform) { 1795 CCodec_IccModule* pIccModule = 1796 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1797 if (src_Bpp == 3) { 1798 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1799 width); 1800 } else { 1801 uint8_t* dp = src_cache_scan; 1802 for (int col = 0; col < width; col++) { 1803 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1804 src_scan += 4; 1805 dp += 3; 1806 } 1807 } 1808 CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_cache_scan, width, blend_type, 1809 dest_Bpp, 3, clip_scan); 1810 } 1811 1812 void CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform(uint8_t* dest_scan, 1813 const uint8_t* src_scan, 1814 int width, 1815 int dest_Bpp, 1816 int src_Bpp, 1817 uint8_t* src_cache_scan, 1818 void* pIccTransform) { 1819 CCodec_IccModule* pIccModule = 1820 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1821 if (src_Bpp == 3) { 1822 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1823 width); 1824 } else { 1825 uint8_t* dp = src_cache_scan; 1826 for (int col = 0; col < width; col++) { 1827 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1828 src_scan += 4; 1829 dp += 3; 1830 } 1831 } 1832 CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_cache_scan, width, 1833 dest_Bpp, 3); 1834 } 1835 1836 void CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform(uint8_t* dest_scan, 1837 const uint8_t* src_scan, 1838 int width, 1839 int dest_Bpp, 1840 int src_Bpp, 1841 const uint8_t* clip_scan, 1842 uint8_t* src_cache_scan, 1843 void* pIccTransform) { 1844 CCodec_IccModule* pIccModule = 1845 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 1846 if (src_Bpp == 3) { 1847 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1848 width); 1849 } else { 1850 uint8_t* dp = src_cache_scan; 1851 for (int col = 0; col < width; col++) { 1852 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); 1853 src_scan += 4; 1854 dp += 3; 1855 } 1856 } 1857 CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_cache_scan, width, dest_Bpp, 1858 3, clip_scan); 1859 } 1860 1861 void CompositeRow_8bppPal2Gray(uint8_t* dest_scan, 1862 const uint8_t* src_scan, 1863 const uint8_t* pPalette, 1864 int pixel_count, 1865 int blend_type, 1866 const uint8_t* clip_scan, 1867 const uint8_t* src_alpha_scan) { 1868 if (src_alpha_scan) { 1869 if (blend_type) { 1870 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1871 for (int col = 0; col < pixel_count; col++) { 1872 uint8_t gray = pPalette[*src_scan]; 1873 int src_alpha = *src_alpha_scan++; 1874 if (clip_scan) { 1875 src_alpha = clip_scan[col] * src_alpha / 255; 1876 } 1877 if (bNonseparableBlend) 1878 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 1879 else 1880 gray = Blend(blend_type, *dest_scan, gray); 1881 if (src_alpha) { 1882 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 1883 } else { 1884 *dest_scan = gray; 1885 } 1886 dest_scan++; 1887 src_scan++; 1888 } 1889 return; 1890 } 1891 for (int col = 0; col < pixel_count; col++) { 1892 uint8_t gray = pPalette[*src_scan]; 1893 int src_alpha = *src_alpha_scan++; 1894 if (clip_scan) { 1895 src_alpha = clip_scan[col] * src_alpha / 255; 1896 } 1897 if (src_alpha) { 1898 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 1899 } else { 1900 *dest_scan = gray; 1901 } 1902 dest_scan++; 1903 src_scan++; 1904 } 1905 } else { 1906 if (blend_type) { 1907 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1908 for (int col = 0; col < pixel_count; col++) { 1909 uint8_t gray = pPalette[*src_scan]; 1910 if (bNonseparableBlend) 1911 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 1912 else 1913 gray = Blend(blend_type, *dest_scan, gray); 1914 if (clip_scan && clip_scan[col] < 255) { 1915 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 1916 } else { 1917 *dest_scan = gray; 1918 } 1919 dest_scan++; 1920 src_scan++; 1921 } 1922 return; 1923 } 1924 for (int col = 0; col < pixel_count; col++) { 1925 uint8_t gray = pPalette[*src_scan]; 1926 if (clip_scan && clip_scan[col] < 255) { 1927 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 1928 } else { 1929 *dest_scan = gray; 1930 } 1931 dest_scan++; 1932 src_scan++; 1933 } 1934 } 1935 } 1936 1937 void CompositeRow_8bppPal2Graya(uint8_t* dest_scan, 1938 const uint8_t* src_scan, 1939 const uint8_t* pPalette, 1940 int pixel_count, 1941 int blend_type, 1942 const uint8_t* clip_scan, 1943 uint8_t* dest_alpha_scan, 1944 const uint8_t* src_alpha_scan) { 1945 if (src_alpha_scan) { 1946 if (blend_type) { 1947 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1948 for (int col = 0; col < pixel_count; col++) { 1949 uint8_t gray = pPalette[*src_scan]; 1950 src_scan++; 1951 uint8_t back_alpha = *dest_alpha_scan; 1952 if (back_alpha == 0) { 1953 int src_alpha = *src_alpha_scan++; 1954 if (clip_scan) { 1955 src_alpha = clip_scan[col] * src_alpha / 255; 1956 } 1957 if (src_alpha) { 1958 *dest_scan = gray; 1959 *dest_alpha_scan = src_alpha; 1960 } 1961 dest_scan++; 1962 dest_alpha_scan++; 1963 continue; 1964 } 1965 uint8_t src_alpha = *src_alpha_scan++; 1966 if (clip_scan) { 1967 src_alpha = clip_scan[col] * src_alpha / 255; 1968 } 1969 if (src_alpha == 0) { 1970 dest_scan++; 1971 dest_alpha_scan++; 1972 continue; 1973 } 1974 *dest_alpha_scan = 1975 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1976 int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan); 1977 if (bNonseparableBlend) 1978 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 1979 else 1980 gray = Blend(blend_type, *dest_scan, gray); 1981 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 1982 dest_alpha_scan++; 1983 dest_scan++; 1984 } 1985 return; 1986 } 1987 for (int col = 0; col < pixel_count; col++) { 1988 uint8_t gray = pPalette[*src_scan]; 1989 src_scan++; 1990 uint8_t back_alpha = *dest_alpha_scan; 1991 if (back_alpha == 0) { 1992 int src_alpha = *src_alpha_scan++; 1993 if (clip_scan) { 1994 src_alpha = clip_scan[col] * src_alpha / 255; 1995 } 1996 if (src_alpha) { 1997 *dest_scan = gray; 1998 *dest_alpha_scan = src_alpha; 1999 } 2000 dest_scan++; 2001 dest_alpha_scan++; 2002 continue; 2003 } 2004 uint8_t src_alpha = *src_alpha_scan++; 2005 if (clip_scan) { 2006 src_alpha = clip_scan[col] * src_alpha / 255; 2007 } 2008 if (src_alpha == 0) { 2009 dest_scan++; 2010 dest_alpha_scan++; 2011 continue; 2012 } 2013 *dest_alpha_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2014 int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan); 2015 dest_alpha_scan++; 2016 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 2017 dest_scan++; 2018 } 2019 } else { 2020 if (blend_type) { 2021 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2022 for (int col = 0; col < pixel_count; col++) { 2023 uint8_t gray = pPalette[*src_scan]; 2024 src_scan++; 2025 if (!clip_scan || clip_scan[col] == 255) { 2026 *dest_scan++ = gray; 2027 *dest_alpha_scan++ = 255; 2028 continue; 2029 } 2030 int src_alpha = clip_scan[col]; 2031 if (src_alpha == 0) { 2032 dest_scan++; 2033 dest_alpha_scan++; 2034 continue; 2035 } 2036 int back_alpha = *dest_alpha_scan; 2037 uint8_t dest_alpha = 2038 back_alpha + src_alpha - back_alpha * src_alpha / 255; 2039 *dest_alpha_scan++ = dest_alpha; 2040 int alpha_ratio = src_alpha * 255 / dest_alpha; 2041 if (bNonseparableBlend) 2042 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 2043 else 2044 gray = Blend(blend_type, *dest_scan, gray); 2045 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 2046 dest_scan++; 2047 } 2048 return; 2049 } 2050 for (int col = 0; col < pixel_count; col++) { 2051 uint8_t gray = pPalette[*src_scan]; 2052 src_scan++; 2053 if (!clip_scan || clip_scan[col] == 255) { 2054 *dest_scan++ = gray; 2055 *dest_alpha_scan++ = 255; 2056 continue; 2057 } 2058 int src_alpha = clip_scan[col]; 2059 if (src_alpha == 0) { 2060 dest_scan++; 2061 dest_alpha_scan++; 2062 continue; 2063 } 2064 int back_alpha = *dest_alpha_scan; 2065 uint8_t dest_alpha = 2066 back_alpha + src_alpha - back_alpha * src_alpha / 255; 2067 *dest_alpha_scan++ = dest_alpha; 2068 int alpha_ratio = src_alpha * 255 / dest_alpha; 2069 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 2070 dest_scan++; 2071 } 2072 } 2073 } 2074 2075 void CompositeRow_1bppPal2Gray(uint8_t* dest_scan, 2076 const uint8_t* src_scan, 2077 int src_left, 2078 const uint8_t* pPalette, 2079 int pixel_count, 2080 int blend_type, 2081 const uint8_t* clip_scan) { 2082 int reset_gray = pPalette[0]; 2083 int set_gray = pPalette[1]; 2084 if (blend_type) { 2085 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2086 for (int col = 0; col < pixel_count; col++) { 2087 uint8_t gray = 2088 (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) 2089 ? set_gray 2090 : reset_gray; 2091 if (bNonseparableBlend) 2092 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 2093 else 2094 gray = Blend(blend_type, *dest_scan, gray); 2095 if (clip_scan && clip_scan[col] < 255) { 2096 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 2097 } else { 2098 *dest_scan = gray; 2099 } 2100 dest_scan++; 2101 } 2102 return; 2103 } 2104 for (int col = 0; col < pixel_count; col++) { 2105 uint8_t gray = 2106 (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) 2107 ? set_gray 2108 : reset_gray; 2109 if (clip_scan && clip_scan[col] < 255) { 2110 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 2111 } else { 2112 *dest_scan = gray; 2113 } 2114 dest_scan++; 2115 } 2116 } 2117 2118 void CompositeRow_1bppPal2Graya(uint8_t* dest_scan, 2119 const uint8_t* src_scan, 2120 int src_left, 2121 const uint8_t* pPalette, 2122 int pixel_count, 2123 int blend_type, 2124 const uint8_t* clip_scan, 2125 uint8_t* dest_alpha_scan) { 2126 int reset_gray = pPalette[0]; 2127 int set_gray = pPalette[1]; 2128 if (blend_type) { 2129 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2130 for (int col = 0; col < pixel_count; col++) { 2131 uint8_t gray = 2132 (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) 2133 ? set_gray 2134 : reset_gray; 2135 if (!clip_scan || clip_scan[col] == 255) { 2136 *dest_scan++ = gray; 2137 *dest_alpha_scan++ = 255; 2138 continue; 2139 } 2140 int src_alpha = clip_scan[col]; 2141 if (src_alpha == 0) { 2142 dest_scan++; 2143 dest_alpha_scan++; 2144 continue; 2145 } 2146 int back_alpha = *dest_alpha_scan; 2147 uint8_t dest_alpha = 2148 back_alpha + src_alpha - back_alpha * src_alpha / 255; 2149 *dest_alpha_scan++ = dest_alpha; 2150 int alpha_ratio = src_alpha * 255 / dest_alpha; 2151 if (bNonseparableBlend) 2152 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 2153 else 2154 gray = Blend(blend_type, *dest_scan, gray); 2155 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 2156 dest_scan++; 2157 } 2158 return; 2159 } 2160 for (int col = 0; col < pixel_count; col++) { 2161 uint8_t gray = 2162 (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) 2163 ? set_gray 2164 : reset_gray; 2165 if (!clip_scan || clip_scan[col] == 255) { 2166 *dest_scan++ = gray; 2167 *dest_alpha_scan++ = 255; 2168 continue; 2169 } 2170 int src_alpha = clip_scan[col]; 2171 if (src_alpha == 0) { 2172 dest_scan++; 2173 dest_alpha_scan++; 2174 continue; 2175 } 2176 int back_alpha = *dest_alpha_scan; 2177 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2178 *dest_alpha_scan++ = dest_alpha; 2179 int alpha_ratio = src_alpha * 255 / dest_alpha; 2180 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 2181 dest_scan++; 2182 } 2183 } 2184 2185 void CompositeRow_8bppRgb2Rgb_NoBlend(uint8_t* dest_scan, 2186 const uint8_t* src_scan, 2187 uint32_t* pPalette, 2188 int pixel_count, 2189 int DestBpp, 2190 const uint8_t* clip_scan, 2191 const uint8_t* src_alpha_scan) { 2192 if (src_alpha_scan) { 2193 int dest_gap = DestBpp - 3; 2194 FX_ARGB argb = 0; 2195 for (int col = 0; col < pixel_count; col++) { 2196 argb = pPalette[*src_scan]; 2197 int src_r = FXARGB_R(argb); 2198 int src_g = FXARGB_G(argb); 2199 int src_b = FXARGB_B(argb); 2200 src_scan++; 2201 uint8_t src_alpha = 0; 2202 if (clip_scan) { 2203 src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; 2204 } else { 2205 src_alpha = *src_alpha_scan++; 2206 } 2207 if (src_alpha == 255) { 2208 *dest_scan++ = src_b; 2209 *dest_scan++ = src_g; 2210 *dest_scan++ = src_r; 2211 dest_scan += dest_gap; 2212 continue; 2213 } 2214 if (src_alpha == 0) { 2215 dest_scan += DestBpp; 2216 continue; 2217 } 2218 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); 2219 dest_scan++; 2220 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); 2221 dest_scan++; 2222 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); 2223 dest_scan++; 2224 dest_scan += dest_gap; 2225 } 2226 } else { 2227 FX_ARGB argb = 0; 2228 for (int col = 0; col < pixel_count; col++) { 2229 argb = pPalette[*src_scan]; 2230 int src_r = FXARGB_R(argb); 2231 int src_g = FXARGB_G(argb); 2232 int src_b = FXARGB_B(argb); 2233 if (clip_scan && clip_scan[col] < 255) { 2234 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]); 2235 dest_scan++; 2236 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]); 2237 dest_scan++; 2238 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]); 2239 dest_scan++; 2240 } else { 2241 *dest_scan++ = src_b; 2242 *dest_scan++ = src_g; 2243 *dest_scan++ = src_r; 2244 } 2245 if (DestBpp == 4) { 2246 dest_scan++; 2247 } 2248 src_scan++; 2249 } 2250 } 2251 } 2252 2253 void CompositeRow_1bppRgb2Rgb_NoBlend(uint8_t* dest_scan, 2254 const uint8_t* src_scan, 2255 int src_left, 2256 uint32_t* pPalette, 2257 int pixel_count, 2258 int DestBpp, 2259 const uint8_t* clip_scan) { 2260 int reset_r, reset_g, reset_b; 2261 int set_r, set_g, set_b; 2262 reset_r = FXARGB_R(pPalette[0]); 2263 reset_g = FXARGB_G(pPalette[0]); 2264 reset_b = FXARGB_B(pPalette[0]); 2265 set_r = FXARGB_R(pPalette[1]); 2266 set_g = FXARGB_G(pPalette[1]); 2267 set_b = FXARGB_B(pPalette[1]); 2268 for (int col = 0; col < pixel_count; col++) { 2269 int src_r, src_g, src_b; 2270 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 2271 src_r = set_r; 2272 src_g = set_g; 2273 src_b = set_b; 2274 } else { 2275 src_r = reset_r; 2276 src_g = reset_g; 2277 src_b = reset_b; 2278 } 2279 if (clip_scan && clip_scan[col] < 255) { 2280 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]); 2281 dest_scan++; 2282 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]); 2283 dest_scan++; 2284 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]); 2285 dest_scan++; 2286 } else { 2287 *dest_scan++ = src_b; 2288 *dest_scan++ = src_g; 2289 *dest_scan++ = src_r; 2290 } 2291 if (DestBpp == 4) { 2292 dest_scan++; 2293 } 2294 } 2295 } 2296 2297 void CompositeRow_8bppRgb2Argb_NoBlend(uint8_t* dest_scan, 2298 const uint8_t* src_scan, 2299 int width, 2300 uint32_t* pPalette, 2301 const uint8_t* clip_scan, 2302 const uint8_t* src_alpha_scan) { 2303 if (src_alpha_scan) { 2304 for (int col = 0; col < width; col++) { 2305 FX_ARGB argb = pPalette[*src_scan]; 2306 src_scan++; 2307 int src_r = FXARGB_R(argb); 2308 int src_g = FXARGB_G(argb); 2309 int src_b = FXARGB_B(argb); 2310 uint8_t back_alpha = dest_scan[3]; 2311 if (back_alpha == 0) { 2312 if (clip_scan) { 2313 int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255; 2314 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 2315 } else { 2316 FXARGB_SETDIB(dest_scan, 2317 FXARGB_MAKE(*src_alpha_scan, src_r, src_g, src_b)); 2318 } 2319 dest_scan += 4; 2320 src_alpha_scan++; 2321 continue; 2322 } 2323 uint8_t src_alpha; 2324 if (clip_scan) { 2325 src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255; 2326 } else { 2327 src_alpha = *src_alpha_scan++; 2328 } 2329 if (src_alpha == 0) { 2330 dest_scan += 4; 2331 continue; 2332 } 2333 uint8_t dest_alpha = 2334 back_alpha + src_alpha - back_alpha * src_alpha / 255; 2335 dest_scan[3] = dest_alpha; 2336 int alpha_ratio = src_alpha * 255 / dest_alpha; 2337 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 2338 dest_scan++; 2339 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 2340 dest_scan++; 2341 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 2342 dest_scan++; 2343 dest_scan++; 2344 } 2345 } else { 2346 for (int col = 0; col < width; col++) { 2347 FX_ARGB argb = pPalette[*src_scan]; 2348 int src_r = FXARGB_R(argb); 2349 int src_g = FXARGB_G(argb); 2350 int src_b = FXARGB_B(argb); 2351 if (!clip_scan || clip_scan[col] == 255) { 2352 *dest_scan++ = src_b; 2353 *dest_scan++ = src_g; 2354 *dest_scan++ = src_r; 2355 *dest_scan++ = 255; 2356 src_scan++; 2357 continue; 2358 } 2359 int src_alpha = clip_scan[col]; 2360 if (src_alpha == 0) { 2361 dest_scan += 4; 2362 src_scan++; 2363 continue; 2364 } 2365 int back_alpha = dest_scan[3]; 2366 uint8_t dest_alpha = 2367 back_alpha + src_alpha - back_alpha * src_alpha / 255; 2368 dest_scan[3] = dest_alpha; 2369 int alpha_ratio = src_alpha * 255 / dest_alpha; 2370 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 2371 dest_scan++; 2372 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 2373 dest_scan++; 2374 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 2375 dest_scan++; 2376 dest_scan++; 2377 src_scan++; 2378 } 2379 } 2380 } 2381 2382 void CompositeRow_1bppRgb2Argb_NoBlend(uint8_t* dest_scan, 2383 const uint8_t* src_scan, 2384 int src_left, 2385 int width, 2386 uint32_t* pPalette, 2387 const uint8_t* clip_scan) { 2388 int reset_r, reset_g, reset_b; 2389 int set_r, set_g, set_b; 2390 reset_r = FXARGB_R(pPalette[0]); 2391 reset_g = FXARGB_G(pPalette[0]); 2392 reset_b = FXARGB_B(pPalette[0]); 2393 set_r = FXARGB_R(pPalette[1]); 2394 set_g = FXARGB_G(pPalette[1]); 2395 set_b = FXARGB_B(pPalette[1]); 2396 for (int col = 0; col < width; col++) { 2397 int src_r, src_g, src_b; 2398 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 2399 src_r = set_r; 2400 src_g = set_g; 2401 src_b = set_b; 2402 } else { 2403 src_r = reset_r; 2404 src_g = reset_g; 2405 src_b = reset_b; 2406 } 2407 if (!clip_scan || clip_scan[col] == 255) { 2408 *dest_scan++ = src_b; 2409 *dest_scan++ = src_g; 2410 *dest_scan++ = src_r; 2411 *dest_scan++ = 255; 2412 continue; 2413 } 2414 int src_alpha = clip_scan[col]; 2415 if (src_alpha == 0) { 2416 dest_scan += 4; 2417 continue; 2418 } 2419 int back_alpha = dest_scan[3]; 2420 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2421 dest_scan[3] = dest_alpha; 2422 int alpha_ratio = src_alpha * 255 / dest_alpha; 2423 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 2424 dest_scan++; 2425 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 2426 dest_scan++; 2427 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 2428 dest_scan++; 2429 dest_scan++; 2430 } 2431 } 2432 2433 void CompositeRow_1bppRgb2Rgba_NoBlend(uint8_t* dest_scan, 2434 const uint8_t* src_scan, 2435 int src_left, 2436 int width, 2437 uint32_t* pPalette, 2438 const uint8_t* clip_scan, 2439 uint8_t* dest_alpha_scan) { 2440 int reset_r, reset_g, reset_b; 2441 int set_r, set_g, set_b; 2442 reset_r = FXARGB_R(pPalette[0]); 2443 reset_g = FXARGB_G(pPalette[0]); 2444 reset_b = FXARGB_B(pPalette[0]); 2445 set_r = FXARGB_R(pPalette[1]); 2446 set_g = FXARGB_G(pPalette[1]); 2447 set_b = FXARGB_B(pPalette[1]); 2448 for (int col = 0; col < width; col++) { 2449 int src_r, src_g, src_b; 2450 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 2451 src_r = set_r; 2452 src_g = set_g; 2453 src_b = set_b; 2454 } else { 2455 src_r = reset_r; 2456 src_g = reset_g; 2457 src_b = reset_b; 2458 } 2459 if (!clip_scan || clip_scan[col] == 255) { 2460 *dest_scan++ = src_b; 2461 *dest_scan++ = src_g; 2462 *dest_scan++ = src_r; 2463 *dest_alpha_scan++ = 255; 2464 continue; 2465 } 2466 int src_alpha = clip_scan[col]; 2467 if (src_alpha == 0) { 2468 dest_scan += 3; 2469 dest_alpha_scan++; 2470 continue; 2471 } 2472 int back_alpha = *dest_alpha_scan; 2473 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2474 *dest_alpha_scan++ = dest_alpha; 2475 int alpha_ratio = src_alpha * 255 / dest_alpha; 2476 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 2477 dest_scan++; 2478 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 2479 dest_scan++; 2480 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 2481 dest_scan++; 2482 } 2483 } 2484 2485 void CompositeRow_ByteMask2Argb(uint8_t* dest_scan, 2486 const uint8_t* src_scan, 2487 int mask_alpha, 2488 int src_r, 2489 int src_g, 2490 int src_b, 2491 int pixel_count, 2492 int blend_type, 2493 const uint8_t* clip_scan) { 2494 for (int col = 0; col < pixel_count; col++) { 2495 int src_alpha; 2496 if (clip_scan) { 2497 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 2498 } else { 2499 src_alpha = mask_alpha * src_scan[col] / 255; 2500 } 2501 uint8_t back_alpha = dest_scan[3]; 2502 if (back_alpha == 0) { 2503 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 2504 dest_scan += 4; 2505 continue; 2506 } 2507 if (src_alpha == 0) { 2508 dest_scan += 4; 2509 continue; 2510 } 2511 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2512 dest_scan[3] = dest_alpha; 2513 int alpha_ratio = src_alpha * 255 / dest_alpha; 2514 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 2515 int blended_colors[3]; 2516 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 2517 static_cast<uint8_t>(src_g), 2518 static_cast<uint8_t>(src_r)}; 2519 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 2520 *dest_scan = 2521 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); 2522 dest_scan++; 2523 *dest_scan = 2524 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); 2525 dest_scan++; 2526 *dest_scan = 2527 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); 2528 } else if (blend_type) { 2529 int blended = Blend(blend_type, *dest_scan, src_b); 2530 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 2531 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 2532 dest_scan++; 2533 blended = Blend(blend_type, *dest_scan, src_g); 2534 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 2535 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 2536 dest_scan++; 2537 blended = Blend(blend_type, *dest_scan, src_r); 2538 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 2539 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 2540 } else { 2541 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 2542 dest_scan++; 2543 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 2544 dest_scan++; 2545 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 2546 } 2547 dest_scan += 2; 2548 } 2549 } 2550 2551 void CompositeRow_ByteMask2Rgba(uint8_t* dest_scan, 2552 const uint8_t* src_scan, 2553 int mask_alpha, 2554 int src_r, 2555 int src_g, 2556 int src_b, 2557 int pixel_count, 2558 int blend_type, 2559 const uint8_t* clip_scan, 2560 uint8_t* dest_alpha_scan) { 2561 for (int col = 0; col < pixel_count; col++) { 2562 int src_alpha; 2563 if (clip_scan) { 2564 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 2565 } else { 2566 src_alpha = mask_alpha * src_scan[col] / 255; 2567 } 2568 uint8_t back_alpha = *dest_alpha_scan; 2569 if (back_alpha == 0) { 2570 *dest_scan++ = src_b; 2571 *dest_scan++ = src_g; 2572 *dest_scan++ = src_r; 2573 *dest_alpha_scan++ = src_alpha; 2574 continue; 2575 } 2576 if (src_alpha == 0) { 2577 dest_scan += 3; 2578 dest_alpha_scan++; 2579 continue; 2580 } 2581 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2582 *dest_alpha_scan++ = dest_alpha; 2583 int alpha_ratio = src_alpha * 255 / dest_alpha; 2584 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 2585 int blended_colors[3]; 2586 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 2587 static_cast<uint8_t>(src_g), 2588 static_cast<uint8_t>(src_r)}; 2589 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 2590 *dest_scan = 2591 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); 2592 dest_scan++; 2593 *dest_scan = 2594 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); 2595 dest_scan++; 2596 *dest_scan = 2597 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); 2598 dest_scan++; 2599 } else if (blend_type) { 2600 int blended = Blend(blend_type, *dest_scan, src_b); 2601 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 2602 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 2603 dest_scan++; 2604 blended = Blend(blend_type, *dest_scan, src_g); 2605 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 2606 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 2607 dest_scan++; 2608 blended = Blend(blend_type, *dest_scan, src_r); 2609 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 2610 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 2611 dest_scan++; 2612 } else { 2613 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 2614 dest_scan++; 2615 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 2616 dest_scan++; 2617 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 2618 dest_scan++; 2619 } 2620 } 2621 } 2622 2623 void CompositeRow_ByteMask2Rgb(uint8_t* dest_scan, 2624 const uint8_t* src_scan, 2625 int mask_alpha, 2626 int src_r, 2627 int src_g, 2628 int src_b, 2629 int pixel_count, 2630 int blend_type, 2631 int Bpp, 2632 const uint8_t* clip_scan) { 2633 for (int col = 0; col < pixel_count; col++) { 2634 int src_alpha; 2635 if (clip_scan) { 2636 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 2637 } else { 2638 src_alpha = mask_alpha * src_scan[col] / 255; 2639 } 2640 if (src_alpha == 0) { 2641 dest_scan += Bpp; 2642 continue; 2643 } 2644 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 2645 int blended_colors[3]; 2646 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 2647 static_cast<uint8_t>(src_g), 2648 static_cast<uint8_t>(src_r)}; 2649 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 2650 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha); 2651 dest_scan++; 2652 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha); 2653 dest_scan++; 2654 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha); 2655 } else if (blend_type) { 2656 int blended = Blend(blend_type, *dest_scan, src_b); 2657 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 2658 dest_scan++; 2659 blended = Blend(blend_type, *dest_scan, src_g); 2660 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 2661 dest_scan++; 2662 blended = Blend(blend_type, *dest_scan, src_r); 2663 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 2664 } else { 2665 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); 2666 dest_scan++; 2667 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); 2668 dest_scan++; 2669 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); 2670 } 2671 dest_scan += Bpp - 2; 2672 } 2673 } 2674 2675 void CompositeRow_ByteMask2Mask(uint8_t* dest_scan, 2676 const uint8_t* src_scan, 2677 int mask_alpha, 2678 int pixel_count, 2679 const uint8_t* clip_scan) { 2680 for (int col = 0; col < pixel_count; col++) { 2681 int src_alpha; 2682 if (clip_scan) { 2683 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 2684 } else { 2685 src_alpha = mask_alpha * src_scan[col] / 255; 2686 } 2687 uint8_t back_alpha = *dest_scan; 2688 if (!back_alpha) { 2689 *dest_scan = src_alpha; 2690 } else if (src_alpha) { 2691 *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2692 } 2693 dest_scan++; 2694 } 2695 } 2696 2697 void CompositeRow_ByteMask2Gray(uint8_t* dest_scan, 2698 const uint8_t* src_scan, 2699 int mask_alpha, 2700 int src_gray, 2701 int pixel_count, 2702 const uint8_t* clip_scan) { 2703 for (int col = 0; col < pixel_count; col++) { 2704 int src_alpha; 2705 if (clip_scan) { 2706 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 2707 } else { 2708 src_alpha = mask_alpha * src_scan[col] / 255; 2709 } 2710 if (src_alpha) { 2711 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha); 2712 } 2713 dest_scan++; 2714 } 2715 } 2716 2717 void CompositeRow_ByteMask2Graya(uint8_t* dest_scan, 2718 const uint8_t* src_scan, 2719 int mask_alpha, 2720 int src_gray, 2721 int pixel_count, 2722 const uint8_t* clip_scan, 2723 uint8_t* dest_alpha_scan) { 2724 for (int col = 0; col < pixel_count; col++) { 2725 int src_alpha; 2726 if (clip_scan) { 2727 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 2728 } else { 2729 src_alpha = mask_alpha * src_scan[col] / 255; 2730 } 2731 uint8_t back_alpha = *dest_alpha_scan; 2732 if (back_alpha == 0) { 2733 *dest_scan++ = src_gray; 2734 *dest_alpha_scan++ = src_alpha; 2735 continue; 2736 } 2737 if (src_alpha == 0) { 2738 dest_scan++; 2739 dest_alpha_scan++; 2740 continue; 2741 } 2742 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2743 *dest_alpha_scan++ = dest_alpha; 2744 int alpha_ratio = src_alpha * 255 / dest_alpha; 2745 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio); 2746 dest_scan++; 2747 } 2748 } 2749 2750 void CompositeRow_BitMask2Argb(uint8_t* dest_scan, 2751 const uint8_t* src_scan, 2752 int mask_alpha, 2753 int src_r, 2754 int src_g, 2755 int src_b, 2756 int src_left, 2757 int pixel_count, 2758 int blend_type, 2759 const uint8_t* clip_scan) { 2760 if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { 2761 FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b); 2762 for (int col = 0; col < pixel_count; col++) { 2763 if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { 2764 FXARGB_SETDIB(dest_scan, argb); 2765 } 2766 dest_scan += 4; 2767 } 2768 return; 2769 } 2770 for (int col = 0; col < pixel_count; col++) { 2771 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 2772 dest_scan += 4; 2773 continue; 2774 } 2775 int src_alpha; 2776 if (clip_scan) { 2777 src_alpha = mask_alpha * clip_scan[col] / 255; 2778 } else { 2779 src_alpha = mask_alpha; 2780 } 2781 uint8_t back_alpha = dest_scan[3]; 2782 if (back_alpha == 0) { 2783 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 2784 dest_scan += 4; 2785 continue; 2786 } 2787 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2788 dest_scan[3] = dest_alpha; 2789 int alpha_ratio = src_alpha * 255 / dest_alpha; 2790 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 2791 int blended_colors[3]; 2792 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 2793 static_cast<uint8_t>(src_g), 2794 static_cast<uint8_t>(src_r)}; 2795 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 2796 *dest_scan = 2797 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); 2798 dest_scan++; 2799 *dest_scan = 2800 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); 2801 dest_scan++; 2802 *dest_scan = 2803 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); 2804 } else if (blend_type) { 2805 int blended = Blend(blend_type, *dest_scan, src_b); 2806 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 2807 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 2808 dest_scan++; 2809 blended = Blend(blend_type, *dest_scan, src_g); 2810 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 2811 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 2812 dest_scan++; 2813 blended = Blend(blend_type, *dest_scan, src_r); 2814 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 2815 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 2816 } else { 2817 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 2818 dest_scan++; 2819 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 2820 dest_scan++; 2821 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 2822 } 2823 dest_scan += 2; 2824 } 2825 } 2826 2827 void CompositeRow_BitMask2Rgb(uint8_t* dest_scan, 2828 const uint8_t* src_scan, 2829 int mask_alpha, 2830 int src_r, 2831 int src_g, 2832 int src_b, 2833 int src_left, 2834 int pixel_count, 2835 int blend_type, 2836 int Bpp, 2837 const uint8_t* clip_scan) { 2838 if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { 2839 for (int col = 0; col < pixel_count; col++) { 2840 if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { 2841 dest_scan[2] = src_r; 2842 dest_scan[1] = src_g; 2843 dest_scan[0] = src_b; 2844 } 2845 dest_scan += Bpp; 2846 } 2847 return; 2848 } 2849 for (int col = 0; col < pixel_count; col++) { 2850 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 2851 dest_scan += Bpp; 2852 continue; 2853 } 2854 int src_alpha; 2855 if (clip_scan) { 2856 src_alpha = mask_alpha * clip_scan[col] / 255; 2857 } else { 2858 src_alpha = mask_alpha; 2859 } 2860 if (src_alpha == 0) { 2861 dest_scan += Bpp; 2862 continue; 2863 } 2864 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 2865 int blended_colors[3]; 2866 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 2867 static_cast<uint8_t>(src_g), 2868 static_cast<uint8_t>(src_r)}; 2869 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 2870 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha); 2871 dest_scan++; 2872 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha); 2873 dest_scan++; 2874 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha); 2875 } else if (blend_type) { 2876 int blended = Blend(blend_type, *dest_scan, src_b); 2877 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 2878 dest_scan++; 2879 blended = Blend(blend_type, *dest_scan, src_g); 2880 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 2881 dest_scan++; 2882 blended = Blend(blend_type, *dest_scan, src_r); 2883 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 2884 } else { 2885 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); 2886 dest_scan++; 2887 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); 2888 dest_scan++; 2889 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); 2890 } 2891 dest_scan += Bpp - 2; 2892 } 2893 } 2894 2895 void CompositeRow_BitMask2Mask(uint8_t* dest_scan, 2896 const uint8_t* src_scan, 2897 int mask_alpha, 2898 int src_left, 2899 int pixel_count, 2900 const uint8_t* clip_scan) { 2901 for (int col = 0; col < pixel_count; col++) { 2902 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 2903 dest_scan++; 2904 continue; 2905 } 2906 int src_alpha; 2907 if (clip_scan) { 2908 src_alpha = mask_alpha * clip_scan[col] / 255; 2909 } else { 2910 src_alpha = mask_alpha; 2911 } 2912 uint8_t back_alpha = *dest_scan; 2913 if (!back_alpha) { 2914 *dest_scan = src_alpha; 2915 } else if (src_alpha) { 2916 *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2917 } 2918 dest_scan++; 2919 } 2920 } 2921 2922 void CompositeRow_BitMask2Gray(uint8_t* dest_scan, 2923 const uint8_t* src_scan, 2924 int mask_alpha, 2925 int src_gray, 2926 int src_left, 2927 int pixel_count, 2928 const uint8_t* clip_scan) { 2929 for (int col = 0; col < pixel_count; col++) { 2930 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 2931 dest_scan++; 2932 continue; 2933 } 2934 int src_alpha; 2935 if (clip_scan) { 2936 src_alpha = mask_alpha * clip_scan[col] / 255; 2937 } else { 2938 src_alpha = mask_alpha; 2939 } 2940 if (src_alpha) { 2941 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha); 2942 } 2943 dest_scan++; 2944 } 2945 } 2946 2947 void CompositeRow_BitMask2Graya(uint8_t* dest_scan, 2948 const uint8_t* src_scan, 2949 int mask_alpha, 2950 int src_gray, 2951 int src_left, 2952 int pixel_count, 2953 const uint8_t* clip_scan, 2954 uint8_t* dest_alpha_scan) { 2955 for (int col = 0; col < pixel_count; col++) { 2956 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 2957 dest_scan++; 2958 dest_alpha_scan++; 2959 continue; 2960 } 2961 int src_alpha; 2962 if (clip_scan) { 2963 src_alpha = mask_alpha * clip_scan[col] / 255; 2964 } else { 2965 src_alpha = mask_alpha; 2966 } 2967 uint8_t back_alpha = *dest_alpha_scan; 2968 if (back_alpha == 0) { 2969 *dest_scan++ = src_gray; 2970 *dest_alpha_scan++ = src_alpha; 2971 continue; 2972 } 2973 if (src_alpha == 0) { 2974 dest_scan++; 2975 dest_alpha_scan++; 2976 continue; 2977 } 2978 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2979 *dest_alpha_scan++ = dest_alpha; 2980 int alpha_ratio = src_alpha * 255 / dest_alpha; 2981 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio); 2982 dest_scan++; 2983 } 2984 } 2985 2986 void CompositeRow_Argb2Argb_RgbByteOrder(uint8_t* dest_scan, 2987 const uint8_t* src_scan, 2988 int pixel_count, 2989 int blend_type, 2990 const uint8_t* clip_scan) { 2991 int blended_colors[3]; 2992 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2993 for (int col = 0; col < pixel_count; col++) { 2994 uint8_t back_alpha = dest_scan[3]; 2995 if (back_alpha == 0) { 2996 if (clip_scan) { 2997 int src_alpha = clip_scan[col] * src_scan[3] / 255; 2998 dest_scan[3] = src_alpha; 2999 dest_scan[0] = src_scan[2]; 3000 dest_scan[1] = src_scan[1]; 3001 dest_scan[2] = src_scan[0]; 3002 } else { 3003 FXARGB_RGBORDERCOPY(dest_scan, src_scan); 3004 } 3005 dest_scan += 4; 3006 src_scan += 4; 3007 continue; 3008 } 3009 uint8_t src_alpha; 3010 if (clip_scan) { 3011 src_alpha = clip_scan[col] * src_scan[3] / 255; 3012 } else { 3013 src_alpha = src_scan[3]; 3014 } 3015 if (src_alpha == 0) { 3016 dest_scan += 4; 3017 src_scan += 4; 3018 continue; 3019 } 3020 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 3021 dest_scan[3] = dest_alpha; 3022 int alpha_ratio = src_alpha * 255 / dest_alpha; 3023 if (bNonseparableBlend) { 3024 uint8_t dest_scan_o[3]; 3025 dest_scan_o[0] = dest_scan[2]; 3026 dest_scan_o[1] = dest_scan[1]; 3027 dest_scan_o[2] = dest_scan[0]; 3028 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 3029 } 3030 for (int color = 0; color < 3; color++) { 3031 int index = 2 - color; 3032 if (blend_type) { 3033 int blended = bNonseparableBlend 3034 ? blended_colors[color] 3035 : Blend(blend_type, dest_scan[index], *src_scan); 3036 blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); 3037 dest_scan[index] = 3038 FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio); 3039 } else { 3040 dest_scan[index] = 3041 FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio); 3042 } 3043 src_scan++; 3044 } 3045 dest_scan += 4; 3046 src_scan++; 3047 } 3048 } 3049 3050 void CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan, 3051 const uint8_t* src_scan, 3052 int width, 3053 int blend_type, 3054 int src_Bpp) { 3055 int blended_colors[3]; 3056 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 3057 int src_gap = src_Bpp - 3; 3058 for (int col = 0; col < width; col++) { 3059 uint8_t back_alpha = dest_scan[3]; 3060 if (back_alpha == 0) { 3061 if (src_Bpp == 4) { 3062 FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); 3063 } else { 3064 FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], 3065 src_scan[1], src_scan[0])); 3066 } 3067 dest_scan += 4; 3068 src_scan += src_Bpp; 3069 continue; 3070 } 3071 dest_scan[3] = 0xff; 3072 if (bNonseparableBlend) { 3073 uint8_t dest_scan_o[3]; 3074 dest_scan_o[0] = dest_scan[2]; 3075 dest_scan_o[1] = dest_scan[1]; 3076 dest_scan_o[2] = dest_scan[0]; 3077 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 3078 } 3079 for (int color = 0; color < 3; color++) { 3080 int index = 2 - color; 3081 int src_color = *src_scan; 3082 int blended = bNonseparableBlend 3083 ? blended_colors[color] 3084 : Blend(blend_type, dest_scan[index], src_color); 3085 dest_scan[index] = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 3086 src_scan++; 3087 } 3088 dest_scan += 4; 3089 src_scan += src_gap; 3090 } 3091 } 3092 3093 void CompositeRow_Argb2Rgb_Blend_RgbByteOrder(uint8_t* dest_scan, 3094 const uint8_t* src_scan, 3095 int width, 3096 int blend_type, 3097 int dest_Bpp, 3098 const uint8_t* clip_scan) { 3099 int blended_colors[3]; 3100 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 3101 for (int col = 0; col < width; col++) { 3102 uint8_t src_alpha; 3103 if (clip_scan) { 3104 src_alpha = src_scan[3] * (*clip_scan++) / 255; 3105 } else { 3106 src_alpha = src_scan[3]; 3107 } 3108 if (src_alpha == 0) { 3109 dest_scan += dest_Bpp; 3110 src_scan += 4; 3111 continue; 3112 } 3113 if (bNonseparableBlend) { 3114 uint8_t dest_scan_o[3]; 3115 dest_scan_o[0] = dest_scan[2]; 3116 dest_scan_o[1] = dest_scan[1]; 3117 dest_scan_o[2] = dest_scan[0]; 3118 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 3119 } 3120 for (int color = 0; color < 3; color++) { 3121 int index = 2 - color; 3122 int back_color = dest_scan[index]; 3123 int blended = bNonseparableBlend 3124 ? blended_colors[color] 3125 : Blend(blend_type, back_color, *src_scan); 3126 dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 3127 src_scan++; 3128 } 3129 dest_scan += dest_Bpp; 3130 src_scan++; 3131 } 3132 } 3133 3134 void CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan, 3135 const uint8_t* src_scan, 3136 int width, 3137 int src_Bpp) { 3138 for (int col = 0; col < width; col++) { 3139 if (src_Bpp == 4) { 3140 FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); 3141 } else { 3142 FXARGB_SETRGBORDERDIB( 3143 dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0])); 3144 } 3145 dest_scan += 4; 3146 src_scan += src_Bpp; 3147 } 3148 } 3149 3150 void CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan, 3151 const uint8_t* src_scan, 3152 int width, 3153 int blend_type, 3154 int dest_Bpp, 3155 int src_Bpp) { 3156 int blended_colors[3]; 3157 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 3158 int src_gap = src_Bpp - 3; 3159 for (int col = 0; col < width; col++) { 3160 if (bNonseparableBlend) { 3161 uint8_t dest_scan_o[3]; 3162 dest_scan_o[0] = dest_scan[2]; 3163 dest_scan_o[1] = dest_scan[1]; 3164 dest_scan_o[2] = dest_scan[0]; 3165 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 3166 } 3167 for (int color = 0; color < 3; color++) { 3168 int index = 2 - color; 3169 int back_color = dest_scan[index]; 3170 int src_color = *src_scan; 3171 int blended = bNonseparableBlend 3172 ? blended_colors[color] 3173 : Blend(blend_type, back_color, src_color); 3174 dest_scan[index] = blended; 3175 src_scan++; 3176 } 3177 dest_scan += dest_Bpp; 3178 src_scan += src_gap; 3179 } 3180 } 3181 3182 void CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 3183 const uint8_t* src_scan, 3184 int width, 3185 int dest_Bpp, 3186 const uint8_t* clip_scan) { 3187 for (int col = 0; col < width; col++) { 3188 uint8_t src_alpha; 3189 if (clip_scan) { 3190 src_alpha = src_scan[3] * (*clip_scan++) / 255; 3191 } else { 3192 src_alpha = src_scan[3]; 3193 } 3194 if (src_alpha == 255) { 3195 dest_scan[2] = *src_scan++; 3196 dest_scan[1] = *src_scan++; 3197 dest_scan[0] = *src_scan++; 3198 dest_scan += dest_Bpp; 3199 src_scan++; 3200 continue; 3201 } 3202 if (src_alpha == 0) { 3203 dest_scan += dest_Bpp; 3204 src_scan += 4; 3205 continue; 3206 } 3207 for (int color = 0; color < 3; color++) { 3208 int index = 2 - color; 3209 dest_scan[index] = 3210 FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, src_alpha); 3211 src_scan++; 3212 } 3213 dest_scan += dest_Bpp; 3214 src_scan++; 3215 } 3216 } 3217 3218 void CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan, 3219 const uint8_t* src_scan, 3220 int width, 3221 int dest_Bpp, 3222 int src_Bpp) { 3223 for (int col = 0; col < width; col++) { 3224 dest_scan[2] = src_scan[0]; 3225 dest_scan[1] = src_scan[1]; 3226 dest_scan[0] = src_scan[2]; 3227 dest_scan += dest_Bpp; 3228 src_scan += src_Bpp; 3229 } 3230 } 3231 3232 void CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan, 3233 const uint8_t* src_scan, 3234 int width, 3235 int blend_type, 3236 int src_Bpp, 3237 const uint8_t* clip_scan) { 3238 int blended_colors[3]; 3239 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 3240 int src_gap = src_Bpp - 3; 3241 for (int col = 0; col < width; col++) { 3242 int src_alpha = *clip_scan++; 3243 uint8_t back_alpha = dest_scan[3]; 3244 if (back_alpha == 0) { 3245 dest_scan[2] = *src_scan++; 3246 dest_scan[1] = *src_scan++; 3247 dest_scan[0] = *src_scan++; 3248 src_scan += src_gap; 3249 dest_scan += 4; 3250 continue; 3251 } 3252 if (src_alpha == 0) { 3253 dest_scan += 4; 3254 src_scan += src_Bpp; 3255 continue; 3256 } 3257 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 3258 dest_scan[3] = dest_alpha; 3259 int alpha_ratio = src_alpha * 255 / dest_alpha; 3260 if (bNonseparableBlend) { 3261 uint8_t dest_scan_o[3]; 3262 dest_scan_o[0] = dest_scan[2]; 3263 dest_scan_o[1] = dest_scan[1]; 3264 dest_scan_o[2] = dest_scan[0]; 3265 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 3266 } 3267 for (int color = 0; color < 3; color++) { 3268 int index = 2 - color; 3269 int src_color = *src_scan; 3270 int blended = bNonseparableBlend 3271 ? blended_colors[color] 3272 : Blend(blend_type, dest_scan[index], src_color); 3273 blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 3274 dest_scan[index] = 3275 FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio); 3276 src_scan++; 3277 } 3278 dest_scan += 4; 3279 src_scan += src_gap; 3280 } 3281 } 3282 3283 void CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan, 3284 const uint8_t* src_scan, 3285 int width, 3286 int blend_type, 3287 int dest_Bpp, 3288 int src_Bpp, 3289 const uint8_t* clip_scan) { 3290 int blended_colors[3]; 3291 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 3292 int src_gap = src_Bpp - 3; 3293 for (int col = 0; col < width; col++) { 3294 uint8_t src_alpha = *clip_scan++; 3295 if (src_alpha == 0) { 3296 dest_scan += dest_Bpp; 3297 src_scan += src_Bpp; 3298 continue; 3299 } 3300 if (bNonseparableBlend) { 3301 uint8_t dest_scan_o[3]; 3302 dest_scan_o[0] = dest_scan[2]; 3303 dest_scan_o[1] = dest_scan[1]; 3304 dest_scan_o[2] = dest_scan[0]; 3305 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 3306 } 3307 for (int color = 0; color < 3; color++) { 3308 int index = 2 - color; 3309 int src_color = *src_scan; 3310 int back_color = dest_scan[index]; 3311 int blended = bNonseparableBlend 3312 ? blended_colors[color] 3313 : Blend(blend_type, back_color, src_color); 3314 dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 3315 src_scan++; 3316 } 3317 dest_scan += dest_Bpp; 3318 src_scan += src_gap; 3319 } 3320 } 3321 3322 void CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan, 3323 const uint8_t* src_scan, 3324 int width, 3325 int src_Bpp, 3326 const uint8_t* clip_scan) { 3327 int src_gap = src_Bpp - 3; 3328 for (int col = 0; col < width; col++) { 3329 int src_alpha = clip_scan[col]; 3330 if (src_alpha == 255) { 3331 dest_scan[2] = *src_scan++; 3332 dest_scan[1] = *src_scan++; 3333 dest_scan[0] = *src_scan++; 3334 dest_scan[3] = 255; 3335 dest_scan += 4; 3336 src_scan += src_gap; 3337 continue; 3338 } 3339 if (src_alpha == 0) { 3340 dest_scan += 4; 3341 src_scan += src_Bpp; 3342 continue; 3343 } 3344 int back_alpha = dest_scan[3]; 3345 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 3346 dest_scan[3] = dest_alpha; 3347 int alpha_ratio = src_alpha * 255 / dest_alpha; 3348 for (int color = 0; color < 3; color++) { 3349 int index = 2 - color; 3350 dest_scan[index] = 3351 FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio); 3352 src_scan++; 3353 } 3354 dest_scan += 4; 3355 src_scan += src_gap; 3356 } 3357 } 3358 3359 void CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan, 3360 const uint8_t* src_scan, 3361 int width, 3362 int dest_Bpp, 3363 int src_Bpp, 3364 const uint8_t* clip_scan) { 3365 for (int col = 0; col < width; col++) { 3366 int src_alpha = clip_scan[col]; 3367 if (src_alpha == 255) { 3368 dest_scan[2] = src_scan[0]; 3369 dest_scan[1] = src_scan[1]; 3370 dest_scan[0] = src_scan[2]; 3371 } else if (src_alpha) { 3372 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], *src_scan, src_alpha); 3373 src_scan++; 3374 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], *src_scan, src_alpha); 3375 src_scan++; 3376 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], *src_scan, src_alpha); 3377 dest_scan += dest_Bpp; 3378 src_scan += src_Bpp - 2; 3379 continue; 3380 } 3381 dest_scan += dest_Bpp; 3382 src_scan += src_Bpp; 3383 } 3384 } 3385 3386 void CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 3387 const uint8_t* src_scan, 3388 FX_ARGB* pPalette, 3389 int pixel_count, 3390 int DestBpp, 3391 const uint8_t* clip_scan) { 3392 for (int col = 0; col < pixel_count; col++) { 3393 FX_ARGB argb = pPalette ? pPalette[*src_scan] : (*src_scan) * 0x010101; 3394 int src_r = FXARGB_R(argb); 3395 int src_g = FXARGB_G(argb); 3396 int src_b = FXARGB_B(argb); 3397 if (clip_scan && clip_scan[col] < 255) { 3398 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]); 3399 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]); 3400 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]); 3401 } else { 3402 dest_scan[2] = src_b; 3403 dest_scan[1] = src_g; 3404 dest_scan[0] = src_r; 3405 } 3406 dest_scan += DestBpp; 3407 src_scan++; 3408 } 3409 } 3410 3411 void CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 3412 const uint8_t* src_scan, 3413 int src_left, 3414 FX_ARGB* pPalette, 3415 int pixel_count, 3416 int DestBpp, 3417 const uint8_t* clip_scan) { 3418 int reset_r, reset_g, reset_b; 3419 int set_r, set_g, set_b; 3420 if (pPalette) { 3421 reset_r = FXARGB_R(pPalette[0]); 3422 reset_g = FXARGB_G(pPalette[0]); 3423 reset_b = FXARGB_B(pPalette[0]); 3424 set_r = FXARGB_R(pPalette[1]); 3425 set_g = FXARGB_G(pPalette[1]); 3426 set_b = FXARGB_B(pPalette[1]); 3427 } else { 3428 reset_r = reset_g = reset_b = 0; 3429 set_r = set_g = set_b = 255; 3430 } 3431 for (int col = 0; col < pixel_count; col++) { 3432 int src_r, src_g, src_b; 3433 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 3434 src_r = set_r; 3435 src_g = set_g; 3436 src_b = set_b; 3437 } else { 3438 src_r = reset_r; 3439 src_g = reset_g; 3440 src_b = reset_b; 3441 } 3442 if (clip_scan && clip_scan[col] < 255) { 3443 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]); 3444 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]); 3445 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]); 3446 } else { 3447 dest_scan[2] = src_b; 3448 dest_scan[1] = src_g; 3449 dest_scan[0] = src_r; 3450 } 3451 dest_scan += DestBpp; 3452 } 3453 } 3454 3455 void CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 3456 const uint8_t* src_scan, 3457 int width, 3458 FX_ARGB* pPalette, 3459 const uint8_t* clip_scan) { 3460 for (int col = 0; col < width; col++) { 3461 int src_r, src_g, src_b; 3462 if (pPalette) { 3463 FX_ARGB argb = pPalette[*src_scan]; 3464 src_r = FXARGB_R(argb); 3465 src_g = FXARGB_G(argb); 3466 src_b = FXARGB_B(argb); 3467 } else { 3468 src_r = src_g = src_b = *src_scan; 3469 } 3470 if (!clip_scan || clip_scan[col] == 255) { 3471 dest_scan[2] = src_b; 3472 dest_scan[1] = src_g; 3473 dest_scan[0] = src_r; 3474 dest_scan[3] = 255; 3475 src_scan++; 3476 dest_scan += 4; 3477 continue; 3478 } 3479 int src_alpha = clip_scan[col]; 3480 if (src_alpha == 0) { 3481 dest_scan += 4; 3482 src_scan++; 3483 continue; 3484 } 3485 int back_alpha = dest_scan[3]; 3486 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 3487 dest_scan[3] = dest_alpha; 3488 int alpha_ratio = src_alpha * 255 / dest_alpha; 3489 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); 3490 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); 3491 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); 3492 dest_scan += 4; 3493 src_scan++; 3494 } 3495 } 3496 3497 void CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 3498 const uint8_t* src_scan, 3499 int src_left, 3500 int width, 3501 FX_ARGB* pPalette, 3502 const uint8_t* clip_scan) { 3503 int reset_r, reset_g, reset_b; 3504 int set_r, set_g, set_b; 3505 if (pPalette) { 3506 reset_r = FXARGB_R(pPalette[0]); 3507 reset_g = FXARGB_G(pPalette[0]); 3508 reset_b = FXARGB_B(pPalette[0]); 3509 set_r = FXARGB_R(pPalette[1]); 3510 set_g = FXARGB_G(pPalette[1]); 3511 set_b = FXARGB_B(pPalette[1]); 3512 } else { 3513 reset_r = reset_g = reset_b = 0; 3514 set_r = set_g = set_b = 255; 3515 } 3516 for (int col = 0; col < width; col++) { 3517 int src_r, src_g, src_b; 3518 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 3519 src_r = set_r; 3520 src_g = set_g; 3521 src_b = set_b; 3522 } else { 3523 src_r = reset_r; 3524 src_g = reset_g; 3525 src_b = reset_b; 3526 } 3527 if (!clip_scan || clip_scan[col] == 255) { 3528 dest_scan[2] = src_b; 3529 dest_scan[1] = src_g; 3530 dest_scan[0] = src_r; 3531 dest_scan[3] = 255; 3532 dest_scan += 4; 3533 continue; 3534 } 3535 int src_alpha = clip_scan[col]; 3536 if (src_alpha == 0) { 3537 dest_scan += 4; 3538 continue; 3539 } 3540 int back_alpha = dest_scan[3]; 3541 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 3542 dest_scan[3] = dest_alpha; 3543 int alpha_ratio = src_alpha * 255 / dest_alpha; 3544 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); 3545 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); 3546 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); 3547 dest_scan += 4; 3548 } 3549 } 3550 3551 void CompositeRow_ByteMask2Argb_RgbByteOrder(uint8_t* dest_scan, 3552 const uint8_t* src_scan, 3553 int mask_alpha, 3554 int src_r, 3555 int src_g, 3556 int src_b, 3557 int pixel_count, 3558 int blend_type, 3559 const uint8_t* clip_scan) { 3560 for (int col = 0; col < pixel_count; col++) { 3561 int src_alpha; 3562 if (clip_scan) { 3563 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 3564 } else { 3565 src_alpha = mask_alpha * src_scan[col] / 255; 3566 } 3567 uint8_t back_alpha = dest_scan[3]; 3568 if (back_alpha == 0) { 3569 FXARGB_SETRGBORDERDIB(dest_scan, 3570 FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 3571 dest_scan += 4; 3572 continue; 3573 } 3574 if (src_alpha == 0) { 3575 dest_scan += 4; 3576 continue; 3577 } 3578 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 3579 dest_scan[3] = dest_alpha; 3580 int alpha_ratio = src_alpha * 255 / dest_alpha; 3581 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 3582 int blended_colors[3]; 3583 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 3584 static_cast<uint8_t>(src_g), 3585 static_cast<uint8_t>(src_r)}; 3586 uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; 3587 RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); 3588 dest_scan[2] = 3589 FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio); 3590 dest_scan[1] = 3591 FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio); 3592 dest_scan[0] = 3593 FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio); 3594 } else if (blend_type) { 3595 int blended = Blend(blend_type, dest_scan[2], src_b); 3596 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 3597 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio); 3598 blended = Blend(blend_type, dest_scan[1], src_g); 3599 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 3600 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio); 3601 blended = Blend(blend_type, dest_scan[0], src_r); 3602 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 3603 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio); 3604 } else { 3605 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); 3606 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); 3607 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); 3608 } 3609 dest_scan += 4; 3610 } 3611 } 3612 3613 void CompositeRow_ByteMask2Rgb_RgbByteOrder(uint8_t* dest_scan, 3614 const uint8_t* src_scan, 3615 int mask_alpha, 3616 int src_r, 3617 int src_g, 3618 int src_b, 3619 int pixel_count, 3620 int blend_type, 3621 int Bpp, 3622 const uint8_t* clip_scan) { 3623 for (int col = 0; col < pixel_count; col++) { 3624 int src_alpha; 3625 if (clip_scan) { 3626 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 3627 } else { 3628 src_alpha = mask_alpha * src_scan[col] / 255; 3629 } 3630 if (src_alpha == 0) { 3631 dest_scan += Bpp; 3632 continue; 3633 } 3634 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 3635 int blended_colors[3]; 3636 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 3637 static_cast<uint8_t>(src_g), 3638 static_cast<uint8_t>(src_r)}; 3639 uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; 3640 RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); 3641 dest_scan[2] = 3642 FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha); 3643 dest_scan[1] = 3644 FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha); 3645 dest_scan[0] = 3646 FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha); 3647 } else if (blend_type) { 3648 int blended = Blend(blend_type, dest_scan[2], src_b); 3649 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha); 3650 blended = Blend(blend_type, dest_scan[1], src_g); 3651 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha); 3652 blended = Blend(blend_type, dest_scan[0], src_r); 3653 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha); 3654 } else { 3655 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha); 3656 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha); 3657 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha); 3658 } 3659 dest_scan += Bpp; 3660 } 3661 } 3662 3663 void CompositeRow_BitMask2Argb_RgbByteOrder(uint8_t* dest_scan, 3664 const uint8_t* src_scan, 3665 int mask_alpha, 3666 int src_r, 3667 int src_g, 3668 int src_b, 3669 int src_left, 3670 int pixel_count, 3671 int blend_type, 3672 const uint8_t* clip_scan) { 3673 if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { 3674 FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b); 3675 for (int col = 0; col < pixel_count; col++) { 3676 if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { 3677 FXARGB_SETRGBORDERDIB(dest_scan, argb); 3678 } 3679 dest_scan += 4; 3680 } 3681 return; 3682 } 3683 for (int col = 0; col < pixel_count; col++) { 3684 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 3685 dest_scan += 4; 3686 continue; 3687 } 3688 int src_alpha; 3689 if (clip_scan) { 3690 src_alpha = mask_alpha * clip_scan[col] / 255; 3691 } else { 3692 src_alpha = mask_alpha; 3693 } 3694 uint8_t back_alpha = dest_scan[3]; 3695 if (back_alpha == 0) { 3696 FXARGB_SETRGBORDERDIB(dest_scan, 3697 FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 3698 dest_scan += 4; 3699 continue; 3700 } 3701 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 3702 dest_scan[3] = dest_alpha; 3703 int alpha_ratio = src_alpha * 255 / dest_alpha; 3704 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 3705 int blended_colors[3]; 3706 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 3707 static_cast<uint8_t>(src_g), 3708 static_cast<uint8_t>(src_r)}; 3709 uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; 3710 RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); 3711 dest_scan[2] = 3712 FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio); 3713 dest_scan[1] = 3714 FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio); 3715 dest_scan[0] = 3716 FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio); 3717 } else if (blend_type) { 3718 int blended = Blend(blend_type, dest_scan[2], src_b); 3719 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 3720 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio); 3721 blended = Blend(blend_type, dest_scan[1], src_g); 3722 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 3723 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio); 3724 blended = Blend(blend_type, dest_scan[0], src_r); 3725 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 3726 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio); 3727 } else { 3728 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); 3729 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); 3730 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); 3731 } 3732 dest_scan += 4; 3733 } 3734 } 3735 3736 void CompositeRow_BitMask2Rgb_RgbByteOrder(uint8_t* dest_scan, 3737 const uint8_t* src_scan, 3738 int mask_alpha, 3739 int src_r, 3740 int src_g, 3741 int src_b, 3742 int src_left, 3743 int pixel_count, 3744 int blend_type, 3745 int Bpp, 3746 const uint8_t* clip_scan) { 3747 if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { 3748 for (int col = 0; col < pixel_count; col++) { 3749 if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { 3750 dest_scan[2] = src_b; 3751 dest_scan[1] = src_g; 3752 dest_scan[0] = src_r; 3753 } 3754 dest_scan += Bpp; 3755 } 3756 return; 3757 } 3758 for (int col = 0; col < pixel_count; col++) { 3759 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 3760 dest_scan += Bpp; 3761 continue; 3762 } 3763 int src_alpha; 3764 if (clip_scan) { 3765 src_alpha = mask_alpha * clip_scan[col] / 255; 3766 } else { 3767 src_alpha = mask_alpha; 3768 } 3769 if (src_alpha == 0) { 3770 dest_scan += Bpp; 3771 continue; 3772 } 3773 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 3774 int blended_colors[3]; 3775 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 3776 static_cast<uint8_t>(src_g), 3777 static_cast<uint8_t>(src_r)}; 3778 uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; 3779 RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); 3780 dest_scan[2] = 3781 FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha); 3782 dest_scan[1] = 3783 FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha); 3784 dest_scan[0] = 3785 FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha); 3786 } else if (blend_type) { 3787 int back_color = dest_scan[2]; 3788 int blended = Blend(blend_type, back_color, src_b); 3789 dest_scan[2] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 3790 back_color = dest_scan[1]; 3791 blended = Blend(blend_type, back_color, src_g); 3792 dest_scan[1] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 3793 back_color = dest_scan[0]; 3794 blended = Blend(blend_type, back_color, src_r); 3795 dest_scan[0] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 3796 } else { 3797 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha); 3798 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha); 3799 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha); 3800 } 3801 dest_scan += Bpp; 3802 } 3803 } 3804 3805 bool ScanlineCompositor_InitSourceMask(FXDIB_Format dest_format, 3806 int alpha_flag, 3807 uint32_t mask_color, 3808 int& mask_alpha, 3809 int& mask_red, 3810 int& mask_green, 3811 int& mask_blue, 3812 int& mask_black, 3813 CCodec_IccModule* pIccModule, 3814 void* pIccTransform) { 3815 if (alpha_flag >> 8) { 3816 mask_alpha = alpha_flag & 0xff; 3817 mask_red = FXSYS_GetCValue(mask_color); 3818 mask_green = FXSYS_GetMValue(mask_color); 3819 mask_blue = FXSYS_GetYValue(mask_color); 3820 mask_black = FXSYS_GetKValue(mask_color); 3821 } else { 3822 mask_alpha = FXARGB_A(mask_color); 3823 mask_red = FXARGB_R(mask_color); 3824 mask_green = FXARGB_G(mask_color); 3825 mask_blue = FXARGB_B(mask_color); 3826 } 3827 if (dest_format == FXDIB_8bppMask) { 3828 return true; 3829 } 3830 if ((dest_format & 0xff) == 8) { 3831 if (pIccTransform) { 3832 mask_color = (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) 3833 : FXARGB_TODIB(mask_color); 3834 uint8_t* gray_p = (uint8_t*)&mask_color; 3835 pIccModule->TranslateScanline(pIccTransform, gray_p, gray_p, 1); 3836 mask_red = dest_format & 0x0400 ? FX_CCOLOR(gray_p[0]) : gray_p[0]; 3837 } else { 3838 if (alpha_flag >> 8) { 3839 uint8_t r, g, b; 3840 AdobeCMYK_to_sRGB1(mask_red, mask_green, mask_blue, mask_black, r, g, 3841 b); 3842 mask_red = FXRGB2GRAY(r, g, b); 3843 } else { 3844 mask_red = FXRGB2GRAY(mask_red, mask_green, mask_blue); 3845 } 3846 if (dest_format & 0x0400) { 3847 mask_red = FX_CCOLOR(mask_red); 3848 } 3849 } 3850 } else { 3851 uint8_t* mask_color_p = (uint8_t*)&mask_color; 3852 mask_color = 3853 (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color); 3854 if (pIccTransform) { 3855 pIccModule->TranslateScanline(pIccTransform, mask_color_p, mask_color_p, 3856 1); 3857 mask_red = mask_color_p[2]; 3858 mask_green = mask_color_p[1]; 3859 mask_blue = mask_color_p[0]; 3860 } else if (alpha_flag >> 8) { 3861 AdobeCMYK_to_sRGB1(mask_color_p[0], mask_color_p[1], mask_color_p[2], 3862 mask_color_p[3], mask_color_p[2], mask_color_p[1], 3863 mask_color_p[0]); 3864 mask_red = mask_color_p[2]; 3865 mask_green = mask_color_p[1]; 3866 mask_blue = mask_color_p[0]; 3867 } 3868 } 3869 return true; 3870 } 3871 3872 void ScanlineCompositor_InitSourcePalette(FXDIB_Format src_format, 3873 FXDIB_Format dest_format, 3874 uint32_t*& pDestPalette, 3875 uint32_t* pSrcPalette, 3876 CCodec_IccModule* pIccModule, 3877 void* pIccTransform) { 3878 bool isSrcCmyk = !!(src_format & 0x0400); 3879 bool isDstCmyk = !!(dest_format & 0x0400); 3880 pDestPalette = nullptr; 3881 if (pIccTransform) { 3882 if (pSrcPalette) { 3883 if ((dest_format & 0xff) == 8) { 3884 int pal_count = 1 << (src_format & 0xff); 3885 uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); 3886 pDestPalette = (uint32_t*)gray_pal; 3887 for (int i = 0; i < pal_count; i++) { 3888 uint32_t color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) 3889 : FXARGB_TODIB(pSrcPalette[i]); 3890 pIccModule->TranslateScanline(pIccTransform, gray_pal, 3891 (const uint8_t*)&color, 1); 3892 gray_pal++; 3893 } 3894 } else { 3895 int palsize = 1 << (src_format & 0xff); 3896 pDestPalette = FX_Alloc(uint32_t, palsize); 3897 for (int i = 0; i < palsize; i++) { 3898 uint32_t color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) 3899 : FXARGB_TODIB(pSrcPalette[i]); 3900 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&color, 3901 (const uint8_t*)&color, 1); 3902 pDestPalette[i] = 3903 isDstCmyk ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); 3904 } 3905 } 3906 } else { 3907 int pal_count = 1 << (src_format & 0xff); 3908 uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); 3909 if (pal_count == 2) { 3910 gray_pal[0] = 0; 3911 gray_pal[1] = 255; 3912 } else { 3913 for (int i = 0; i < pal_count; i++) { 3914 gray_pal[i] = i; 3915 } 3916 } 3917 if ((dest_format & 0xff) == 8) { 3918 pIccModule->TranslateScanline(pIccTransform, gray_pal, gray_pal, 3919 pal_count); 3920 pDestPalette = (uint32_t*)gray_pal; 3921 } else { 3922 pDestPalette = FX_Alloc(uint32_t, pal_count); 3923 for (int i = 0; i < pal_count; i++) { 3924 pIccModule->TranslateScanline( 3925 pIccTransform, (uint8_t*)&pDestPalette[i], &gray_pal[i], 1); 3926 pDestPalette[i] = isDstCmyk ? FXCMYK_TODIB(pDestPalette[i]) 3927 : FXARGB_TODIB(pDestPalette[i]); 3928 } 3929 FX_Free(gray_pal); 3930 } 3931 } 3932 } else { 3933 if (pSrcPalette) { 3934 if ((dest_format & 0xff) == 8) { 3935 int pal_count = 1 << (src_format & 0xff); 3936 uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); 3937 pDestPalette = (uint32_t*)gray_pal; 3938 if (isSrcCmyk) { 3939 for (int i = 0; i < pal_count; i++) { 3940 FX_CMYK cmyk = pSrcPalette[i]; 3941 uint8_t r, g, b; 3942 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), 3943 FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r, 3944 g, b); 3945 *gray_pal++ = FXRGB2GRAY(r, g, b); 3946 } 3947 } else { 3948 for (int i = 0; i < pal_count; i++) { 3949 FX_ARGB argb = pSrcPalette[i]; 3950 *gray_pal++ = 3951 FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb)); 3952 } 3953 } 3954 } else { 3955 int palsize = 1 << (src_format & 0xff); 3956 pDestPalette = FX_Alloc(uint32_t, palsize); 3957 if (isDstCmyk == isSrcCmyk) { 3958 FXSYS_memcpy(pDestPalette, pSrcPalette, palsize * sizeof(uint32_t)); 3959 } else { 3960 for (int i = 0; i < palsize; i++) { 3961 FX_CMYK cmyk = pSrcPalette[i]; 3962 uint8_t r, g, b; 3963 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), 3964 FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r, 3965 g, b); 3966 pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b); 3967 } 3968 } 3969 } 3970 } else { 3971 if ((dest_format & 0xff) == 8) { 3972 int pal_count = 1 << (src_format & 0xff); 3973 uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); 3974 if (pal_count == 2) { 3975 gray_pal[0] = 0; 3976 gray_pal[1] = 255; 3977 } else { 3978 for (int i = 0; i < pal_count; i++) { 3979 gray_pal[i] = i; 3980 } 3981 } 3982 pDestPalette = (uint32_t*)gray_pal; 3983 } else { 3984 int palsize = 1 << (src_format & 0xff); 3985 pDestPalette = FX_Alloc(uint32_t, palsize); 3986 if (palsize == 2) { 3987 pDestPalette[0] = isSrcCmyk ? 255 : 0xff000000; 3988 pDestPalette[1] = isSrcCmyk ? 0 : 0xffffffff; 3989 } else { 3990 for (int i = 0; i < palsize; i++) { 3991 pDestPalette[i] = isSrcCmyk ? FX_CCOLOR(i) : (i * 0x10101); 3992 } 3993 } 3994 if (isSrcCmyk != isDstCmyk) { 3995 for (int i = 0; i < palsize; i++) { 3996 FX_CMYK cmyk = pDestPalette[i]; 3997 uint8_t r, g, b; 3998 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), 3999 FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r, 4000 g, b); 4001 pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b); 4002 } 4003 } 4004 } 4005 } 4006 } 4007 } 4008 4009 } // namespace 4010 4011 CFX_ScanlineCompositor::CFX_ScanlineCompositor() { 4012 m_pSrcPalette = nullptr; 4013 m_pCacheScanline = nullptr; 4014 m_CacheSize = 0; 4015 m_bRgbByteOrder = false; 4016 m_BlendType = FXDIB_BLEND_NORMAL; 4017 m_pIccTransform = nullptr; 4018 } 4019 4020 CFX_ScanlineCompositor::~CFX_ScanlineCompositor() { 4021 FX_Free(m_pSrcPalette); 4022 FX_Free(m_pCacheScanline); 4023 } 4024 4025 bool CFX_ScanlineCompositor::Init(FXDIB_Format dest_format, 4026 FXDIB_Format src_format, 4027 int32_t width, 4028 uint32_t* pSrcPalette, 4029 uint32_t mask_color, 4030 int blend_type, 4031 bool bClip, 4032 bool bRgbByteOrder, 4033 int alpha_flag, 4034 void* pIccTransform) { 4035 m_SrcFormat = src_format; 4036 m_DestFormat = dest_format; 4037 m_BlendType = blend_type; 4038 m_bRgbByteOrder = bRgbByteOrder; 4039 CCodec_IccModule* pIccModule = nullptr; 4040 if (CFX_GEModule::Get()->GetCodecModule()) { 4041 pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 4042 } 4043 if (!pIccModule) { 4044 pIccTransform = nullptr; 4045 } 4046 m_pIccTransform = pIccTransform; 4047 if ((dest_format & 0xff) == 1) { 4048 return false; 4049 } 4050 if (m_SrcFormat == FXDIB_1bppMask || m_SrcFormat == FXDIB_8bppMask) { 4051 return ScanlineCompositor_InitSourceMask( 4052 dest_format, alpha_flag, mask_color, m_MaskAlpha, m_MaskRed, 4053 m_MaskGreen, m_MaskBlue, m_MaskBlack, pIccModule, pIccTransform); 4054 } 4055 if (!pIccTransform && (~src_format & 0x0400) && (dest_format & 0x0400)) { 4056 return false; 4057 } 4058 if ((m_SrcFormat & 0xff) <= 8) { 4059 if (dest_format == FXDIB_8bppMask) { 4060 return true; 4061 } 4062 ScanlineCompositor_InitSourcePalette(src_format, dest_format, m_pSrcPalette, 4063 pSrcPalette, pIccModule, 4064 pIccTransform); 4065 m_Transparency = 4066 (dest_format == FXDIB_Argb ? 1 : 0) + (dest_format & 0x0200 ? 2 : 0) + 4067 (dest_format & 0x0400 ? 4 : 0) + ((src_format & 0xff) == 1 ? 8 : 0); 4068 return true; 4069 } 4070 m_Transparency = (src_format & 0x0200 ? 0 : 1) + 4071 (dest_format & 0x0200 ? 0 : 2) + 4072 (blend_type == FXDIB_BLEND_NORMAL ? 4 : 0) + 4073 (bClip ? 8 : 0) + (src_format & 0x0400 ? 16 : 0) + 4074 (dest_format & 0x0400 ? 32 : 0) + (pIccTransform ? 64 : 0); 4075 return true; 4076 } 4077 4078 void CFX_ScanlineCompositor::CompositeRgbBitmapLine( 4079 uint8_t* dest_scan, 4080 const uint8_t* src_scan, 4081 int width, 4082 const uint8_t* clip_scan, 4083 const uint8_t* src_extra_alpha, 4084 uint8_t* dst_extra_alpha) { 4085 int src_Bpp = (m_SrcFormat & 0xff) >> 3; 4086 int dest_Bpp = (m_DestFormat & 0xff) >> 3; 4087 if (m_bRgbByteOrder) { 4088 switch (m_Transparency) { 4089 case 0: 4090 case 4: 4091 case 8: 4092 case 12: 4093 CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width, 4094 m_BlendType, clip_scan); 4095 break; 4096 case 1: 4097 CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder( 4098 dest_scan, src_scan, width, m_BlendType, src_Bpp); 4099 break; 4100 case 2: 4101 case 10: 4102 CompositeRow_Argb2Rgb_Blend_RgbByteOrder( 4103 dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan); 4104 break; 4105 case 3: 4106 CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder( 4107 dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp); 4108 break; 4109 case 5: 4110 CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, 4111 width, src_Bpp); 4112 break; 4113 case 6: 4114 case 14: 4115 CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, 4116 dest_Bpp, clip_scan); 4117 break; 4118 case 7: 4119 CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder( 4120 dest_scan, src_scan, width, dest_Bpp, src_Bpp); 4121 break; 4122 case 9: 4123 CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder( 4124 dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan); 4125 break; 4126 case 11: 4127 CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, 4128 m_BlendType, dest_Bpp, 4129 src_Bpp, clip_scan); 4130 break; 4131 case 13: 4132 CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder( 4133 dest_scan, src_scan, width, src_Bpp, clip_scan); 4134 break; 4135 case 15: 4136 CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder( 4137 dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan); 4138 break; 4139 } 4140 return; 4141 } 4142 if (m_DestFormat == FXDIB_8bppMask) { 4143 if (m_SrcFormat & 0x0200) { 4144 if (m_SrcFormat == FXDIB_Argb) { 4145 CompositeRow_Argb2Mask(dest_scan, src_scan, width, clip_scan); 4146 } else { 4147 CompositeRow_Rgba2Mask(dest_scan, src_extra_alpha, width, clip_scan); 4148 } 4149 } else { 4150 CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan); 4151 } 4152 } else if ((m_DestFormat & 0xff) == 8) { 4153 if (m_DestFormat & 0x0400) { 4154 for (int i = 0; i < width; i++) { 4155 *dest_scan = ~*dest_scan; 4156 dest_scan++; 4157 } 4158 } 4159 if (m_SrcFormat & 0x0200) { 4160 if (m_DestFormat & 0x0200) { 4161 CompositeRow_Argb2Graya(dest_scan, src_scan, width, m_BlendType, 4162 clip_scan, src_extra_alpha, dst_extra_alpha, 4163 m_pIccTransform); 4164 } else { 4165 CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType, 4166 clip_scan, src_extra_alpha, m_pIccTransform); 4167 } 4168 } else { 4169 if (m_DestFormat & 0x0200) { 4170 CompositeRow_Rgb2Graya(dest_scan, src_scan, src_Bpp, width, m_BlendType, 4171 clip_scan, dst_extra_alpha, m_pIccTransform); 4172 } else { 4173 CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType, 4174 clip_scan, m_pIccTransform); 4175 } 4176 } 4177 if (m_DestFormat & 0x0400) { 4178 for (int i = 0; i < width; i++) { 4179 *dest_scan = ~*dest_scan; 4180 dest_scan++; 4181 } 4182 } 4183 } else { 4184 int dest_Size = width * dest_Bpp + 4; 4185 if (dest_Size > m_CacheSize) { 4186 m_pCacheScanline = FX_Realloc(uint8_t, m_pCacheScanline, dest_Size); 4187 if (!m_pCacheScanline) { 4188 return; 4189 } 4190 m_CacheSize = dest_Size; 4191 } 4192 switch (m_Transparency) { 4193 case 0: 4194 case 4: 4195 case 8: 4196 case 4 + 8: { 4197 CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType, 4198 clip_scan, dst_extra_alpha, src_extra_alpha); 4199 } break; 4200 case 64: 4201 case 4 + 64: 4202 case 8 + 64: 4203 case 4 + 8 + 64: { 4204 CompositeRow_Argb2Argb_Transform( 4205 dest_scan, src_scan, width, m_BlendType, clip_scan, dst_extra_alpha, 4206 src_extra_alpha, m_pCacheScanline, m_pIccTransform); 4207 } break; 4208 case 1: 4209 CompositeRow_Rgb2Argb_Blend_NoClip( 4210 dest_scan, src_scan, width, m_BlendType, src_Bpp, dst_extra_alpha); 4211 break; 4212 case 1 + 64: 4213 CompositeRow_Rgb2Argb_Blend_NoClip_Transform( 4214 dest_scan, src_scan, width, m_BlendType, src_Bpp, dst_extra_alpha, 4215 m_pCacheScanline, m_pIccTransform); 4216 break; 4217 case 1 + 8: 4218 CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width, 4219 m_BlendType, src_Bpp, clip_scan, 4220 dst_extra_alpha); 4221 break; 4222 case 1 + 8 + 64: 4223 CompositeRow_Rgb2Argb_Blend_Clip_Transform( 4224 dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan, 4225 dst_extra_alpha, m_pCacheScanline, m_pIccTransform); 4226 break; 4227 case 1 + 4: 4228 CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width, 4229 src_Bpp, dst_extra_alpha); 4230 break; 4231 case 1 + 4 + 64: 4232 CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform( 4233 dest_scan, src_scan, width, src_Bpp, dst_extra_alpha, 4234 m_pCacheScanline, m_pIccTransform); 4235 break; 4236 case 1 + 4 + 8: 4237 CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp, 4238 clip_scan, dst_extra_alpha); 4239 break; 4240 case 1 + 4 + 8 + 64: 4241 CompositeRow_Rgb2Argb_NoBlend_Clip_Transform( 4242 dest_scan, src_scan, width, src_Bpp, clip_scan, dst_extra_alpha, 4243 m_pCacheScanline, m_pIccTransform); 4244 break; 4245 case 2: 4246 case 2 + 8: 4247 CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType, 4248 dest_Bpp, clip_scan, src_extra_alpha); 4249 break; 4250 case 2 + 64: 4251 case 2 + 8 + 64: 4252 CompositeRow_Argb2Rgb_Blend_Transform( 4253 dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan, 4254 src_extra_alpha, m_pCacheScanline, m_pIccTransform); 4255 break; 4256 case 2 + 4: 4257 case 2 + 4 + 8: 4258 CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp, 4259 clip_scan, src_extra_alpha); 4260 break; 4261 case 2 + 4 + 64: 4262 case 2 + 4 + 8 + 64: 4263 CompositeRow_Argb2Rgb_NoBlend_Transform( 4264 dest_scan, src_scan, width, dest_Bpp, clip_scan, src_extra_alpha, 4265 m_pCacheScanline, m_pIccTransform); 4266 break; 4267 case 1 + 2: 4268 CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width, 4269 m_BlendType, dest_Bpp, src_Bpp); 4270 break; 4271 case 1 + 2 + 64: 4272 CompositeRow_Rgb2Rgb_Blend_NoClip_Transform( 4273 dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, 4274 m_pCacheScanline, m_pIccTransform); 4275 break; 4276 case 1 + 2 + 8: 4277 CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, 4278 dest_Bpp, src_Bpp, clip_scan); 4279 break; 4280 case 1 + 2 + 8 + 64: 4281 CompositeRow_Rgb2Rgb_Blend_Clip_Transform( 4282 dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, 4283 clip_scan, m_pCacheScanline, m_pIccTransform); 4284 break; 4285 case 1 + 2 + 4: 4286 CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width, 4287 dest_Bpp, src_Bpp); 4288 break; 4289 case 1 + 2 + 4 + 64: 4290 CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform( 4291 dest_scan, src_scan, width, dest_Bpp, src_Bpp, m_pCacheScanline, 4292 m_pIccTransform); 4293 break; 4294 case 1 + 2 + 4 + 8: 4295 CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp, 4296 src_Bpp, clip_scan); 4297 break; 4298 case 1 + 2 + 4 + 8 + 64: 4299 CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform( 4300 dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan, 4301 m_pCacheScanline, m_pIccTransform); 4302 break; 4303 } 4304 } 4305 } 4306 4307 void CFX_ScanlineCompositor::CompositePalBitmapLine( 4308 uint8_t* dest_scan, 4309 const uint8_t* src_scan, 4310 int src_left, 4311 int width, 4312 const uint8_t* clip_scan, 4313 const uint8_t* src_extra_alpha, 4314 uint8_t* dst_extra_alpha) { 4315 if (m_bRgbByteOrder) { 4316 if (m_SrcFormat == FXDIB_1bppRgb) { 4317 if (m_DestFormat == FXDIB_8bppRgb) { 4318 return; 4319 } 4320 if (m_DestFormat == FXDIB_Argb) { 4321 CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder( 4322 dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan); 4323 } else { 4324 CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder( 4325 dest_scan, src_scan, src_left, m_pSrcPalette, width, 4326 (m_DestFormat & 0xff) >> 3, clip_scan); 4327 } 4328 } else { 4329 if (m_DestFormat == FXDIB_8bppRgb) { 4330 return; 4331 } 4332 if (m_DestFormat == FXDIB_Argb) { 4333 CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder( 4334 dest_scan, src_scan, width, m_pSrcPalette, clip_scan); 4335 } else { 4336 CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder( 4337 dest_scan, src_scan, m_pSrcPalette, width, 4338 (m_DestFormat & 0xff) >> 3, clip_scan); 4339 } 4340 } 4341 return; 4342 } 4343 if (m_DestFormat == FXDIB_8bppMask) { 4344 CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan); 4345 return; 4346 } 4347 if ((m_DestFormat & 0xff) == 8) { 4348 if (m_Transparency & 8) { 4349 if (m_DestFormat & 0x0200) { 4350 CompositeRow_1bppPal2Graya(dest_scan, src_scan, src_left, 4351 (const uint8_t*)m_pSrcPalette, width, 4352 m_BlendType, clip_scan, dst_extra_alpha); 4353 } else { 4354 CompositeRow_1bppPal2Gray(dest_scan, src_scan, src_left, 4355 (const uint8_t*)m_pSrcPalette, width, 4356 m_BlendType, clip_scan); 4357 } 4358 } else { 4359 if (m_DestFormat & 0x0200) 4360 CompositeRow_8bppPal2Graya( 4361 dest_scan, src_scan, (const uint8_t*)m_pSrcPalette, width, 4362 m_BlendType, clip_scan, dst_extra_alpha, src_extra_alpha); 4363 else 4364 CompositeRow_8bppPal2Gray(dest_scan, src_scan, 4365 (const uint8_t*)m_pSrcPalette, width, 4366 m_BlendType, clip_scan, src_extra_alpha); 4367 } 4368 } else { 4369 switch (m_Transparency) { 4370 case 1 + 2: 4371 CompositeRow_8bppRgb2Argb_NoBlend(dest_scan, src_scan, width, 4372 m_pSrcPalette, clip_scan, 4373 src_extra_alpha); 4374 break; 4375 case 1 + 2 + 8: 4376 CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width, 4377 m_pSrcPalette, clip_scan); 4378 break; 4379 case 0: 4380 CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, 4381 width, (m_DestFormat & 0xff) >> 3, 4382 clip_scan, src_extra_alpha); 4383 break; 4384 case 0 + 8: 4385 CompositeRow_1bppRgb2Rgb_NoBlend(dest_scan, src_scan, src_left, 4386 m_pSrcPalette, width, 4387 (m_DestFormat & 0xff) >> 3, clip_scan); 4388 break; 4389 case 0 + 2: 4390 CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, 4391 width, (m_DestFormat & 0xff) >> 3, 4392 clip_scan, src_extra_alpha); 4393 break; 4394 case 0 + 2 + 8: 4395 CompositeRow_1bppRgb2Rgba_NoBlend(dest_scan, src_scan, src_left, width, 4396 m_pSrcPalette, clip_scan, 4397 dst_extra_alpha); 4398 break; 4399 break; 4400 } 4401 } 4402 } 4403 4404 void CFX_ScanlineCompositor::CompositeByteMaskLine(uint8_t* dest_scan, 4405 const uint8_t* src_scan, 4406 int width, 4407 const uint8_t* clip_scan, 4408 uint8_t* dst_extra_alpha) { 4409 if (m_DestFormat == FXDIB_8bppMask) { 4410 CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width, 4411 clip_scan); 4412 } else if ((m_DestFormat & 0xff) == 8) { 4413 if (m_DestFormat & 0x0200) { 4414 CompositeRow_ByteMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 4415 width, clip_scan, dst_extra_alpha); 4416 } else { 4417 CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 4418 width, clip_scan); 4419 } 4420 } else if (m_bRgbByteOrder) { 4421 if (m_DestFormat == FXDIB_Argb) { 4422 CompositeRow_ByteMask2Argb_RgbByteOrder( 4423 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 4424 width, m_BlendType, clip_scan); 4425 } else { 4426 CompositeRow_ByteMask2Rgb_RgbByteOrder( 4427 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 4428 width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); 4429 } 4430 return; 4431 } else if (m_DestFormat == FXDIB_Argb) { 4432 CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 4433 m_MaskGreen, m_MaskBlue, width, m_BlendType, 4434 clip_scan); 4435 } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) { 4436 CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 4437 m_MaskGreen, m_MaskBlue, width, m_BlendType, 4438 (m_DestFormat & 0xff) >> 3, clip_scan); 4439 } else if (m_DestFormat == FXDIB_Rgba) { 4440 CompositeRow_ByteMask2Rgba(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 4441 m_MaskGreen, m_MaskBlue, width, m_BlendType, 4442 clip_scan, dst_extra_alpha); 4443 } 4444 } 4445 4446 void CFX_ScanlineCompositor::CompositeBitMaskLine(uint8_t* dest_scan, 4447 const uint8_t* src_scan, 4448 int src_left, 4449 int width, 4450 const uint8_t* clip_scan, 4451 uint8_t* dst_extra_alpha) { 4452 if (m_DestFormat == FXDIB_8bppMask) { 4453 CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left, width, 4454 clip_scan); 4455 } else if ((m_DestFormat & 0xff) == 8) { 4456 if (m_DestFormat & 0x0200) { 4457 CompositeRow_BitMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 4458 src_left, width, clip_scan, dst_extra_alpha); 4459 } else { 4460 CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 4461 src_left, width, clip_scan); 4462 } 4463 } else if (m_bRgbByteOrder) { 4464 if (m_DestFormat == FXDIB_Argb) { 4465 CompositeRow_BitMask2Argb_RgbByteOrder( 4466 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 4467 src_left, width, m_BlendType, clip_scan); 4468 } else { 4469 CompositeRow_BitMask2Rgb_RgbByteOrder( 4470 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 4471 src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); 4472 } 4473 return; 4474 } else if (m_DestFormat == FXDIB_Argb) { 4475 CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 4476 m_MaskGreen, m_MaskBlue, src_left, width, 4477 m_BlendType, clip_scan); 4478 } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) { 4479 CompositeRow_BitMask2Rgb( 4480 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 4481 src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); 4482 } 4483 } 4484 4485 bool CFX_DIBitmap::CompositeBitmap(int dest_left, 4486 int dest_top, 4487 int width, 4488 int height, 4489 const CFX_DIBSource* pSrcBitmap, 4490 int src_left, 4491 int src_top, 4492 int blend_type, 4493 const CFX_ClipRgn* pClipRgn, 4494 bool bRgbByteOrder, 4495 void* pIccTransform) { 4496 if (!m_pBuffer) { 4497 return false; 4498 } 4499 ASSERT(!pSrcBitmap->IsAlphaMask()); 4500 ASSERT(m_bpp >= 8); 4501 if (pSrcBitmap->IsAlphaMask() || m_bpp < 8) { 4502 return false; 4503 } 4504 GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), 4505 pSrcBitmap->GetHeight(), src_left, src_top, pClipRgn); 4506 if (width == 0 || height == 0) { 4507 return true; 4508 } 4509 const CFX_DIBitmap* pClipMask = nullptr; 4510 FX_RECT clip_box; 4511 if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { 4512 ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF); 4513 pClipMask = pClipRgn->GetMask().GetObject(); 4514 clip_box = pClipRgn->GetBox(); 4515 } 4516 CFX_ScanlineCompositor compositor; 4517 if (!compositor.Init(GetFormat(), pSrcBitmap->GetFormat(), width, 4518 pSrcBitmap->GetPalette(), 0, blend_type, 4519 pClipMask != nullptr, bRgbByteOrder, 0, pIccTransform)) { 4520 return false; 4521 } 4522 int dest_Bpp = m_bpp / 8; 4523 int src_Bpp = pSrcBitmap->GetBPP() / 8; 4524 bool bRgb = src_Bpp > 1 && !pSrcBitmap->IsCmykImage(); 4525 CFX_DIBitmap* pSrcAlphaMask = pSrcBitmap->m_pAlphaMask; 4526 for (int row = 0; row < height; row++) { 4527 uint8_t* dest_scan = 4528 m_pBuffer + (dest_top + row) * m_Pitch + dest_left * dest_Bpp; 4529 const uint8_t* src_scan = 4530 pSrcBitmap->GetScanline(src_top + row) + src_left * src_Bpp; 4531 const uint8_t* src_scan_extra_alpha = 4532 pSrcAlphaMask ? pSrcAlphaMask->GetScanline(src_top + row) + src_left 4533 : nullptr; 4534 uint8_t* dst_scan_extra_alpha = 4535 m_pAlphaMask 4536 ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left 4537 : nullptr; 4538 const uint8_t* clip_scan = nullptr; 4539 if (pClipMask) { 4540 clip_scan = pClipMask->m_pBuffer + 4541 (dest_top + row - clip_box.top) * pClipMask->m_Pitch + 4542 (dest_left - clip_box.left); 4543 } 4544 if (bRgb) { 4545 compositor.CompositeRgbBitmapLine(dest_scan, src_scan, width, clip_scan, 4546 src_scan_extra_alpha, 4547 dst_scan_extra_alpha); 4548 } else { 4549 compositor.CompositePalBitmapLine(dest_scan, src_scan, src_left, width, 4550 clip_scan, src_scan_extra_alpha, 4551 dst_scan_extra_alpha); 4552 } 4553 } 4554 return true; 4555 } 4556 4557 bool CFX_DIBitmap::CompositeMask(int dest_left, 4558 int dest_top, 4559 int width, 4560 int height, 4561 const CFX_DIBSource* pMask, 4562 uint32_t color, 4563 int src_left, 4564 int src_top, 4565 int blend_type, 4566 const CFX_ClipRgn* pClipRgn, 4567 bool bRgbByteOrder, 4568 int alpha_flag, 4569 void* pIccTransform) { 4570 if (!m_pBuffer) { 4571 return false; 4572 } 4573 ASSERT(pMask->IsAlphaMask()); 4574 ASSERT(m_bpp >= 8); 4575 if (!pMask->IsAlphaMask() || m_bpp < 8) { 4576 return false; 4577 } 4578 GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(), 4579 pMask->GetHeight(), src_left, src_top, pClipRgn); 4580 if (width == 0 || height == 0) { 4581 return true; 4582 } 4583 int src_alpha = 4584 (uint8_t)(alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color); 4585 if (src_alpha == 0) { 4586 return true; 4587 } 4588 const CFX_DIBitmap* pClipMask = nullptr; 4589 FX_RECT clip_box; 4590 if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { 4591 ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF); 4592 pClipMask = pClipRgn->GetMask().GetObject(); 4593 clip_box = pClipRgn->GetBox(); 4594 } 4595 int src_bpp = pMask->GetBPP(); 4596 int Bpp = GetBPP() / 8; 4597 CFX_ScanlineCompositor compositor; 4598 if (!compositor.Init(GetFormat(), pMask->GetFormat(), width, nullptr, color, 4599 blend_type, pClipMask != nullptr, bRgbByteOrder, 4600 alpha_flag, pIccTransform)) { 4601 return false; 4602 } 4603 for (int row = 0; row < height; row++) { 4604 uint8_t* dest_scan = 4605 m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp; 4606 const uint8_t* src_scan = pMask->GetScanline(src_top + row); 4607 uint8_t* dst_scan_extra_alpha = 4608 m_pAlphaMask 4609 ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left 4610 : nullptr; 4611 const uint8_t* clip_scan = nullptr; 4612 if (pClipMask) { 4613 clip_scan = pClipMask->m_pBuffer + 4614 (dest_top + row - clip_box.top) * pClipMask->m_Pitch + 4615 (dest_left - clip_box.left); 4616 } 4617 if (src_bpp == 1) { 4618 compositor.CompositeBitMaskLine(dest_scan, src_scan, src_left, width, 4619 clip_scan, dst_scan_extra_alpha); 4620 } else { 4621 compositor.CompositeByteMaskLine(dest_scan, src_scan + src_left, width, 4622 clip_scan, dst_scan_extra_alpha); 4623 } 4624 } 4625 return true; 4626 } 4627 4628 bool CFX_DIBitmap::CompositeRect(int left, 4629 int top, 4630 int width, 4631 int height, 4632 uint32_t color, 4633 int alpha_flag, 4634 void* pIccTransform) { 4635 if (!m_pBuffer) { 4636 return false; 4637 } 4638 int src_alpha = (alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color); 4639 if (src_alpha == 0) { 4640 return true; 4641 } 4642 FX_RECT rect(left, top, left + width, top + height); 4643 rect.Intersect(0, 0, m_Width, m_Height); 4644 if (rect.IsEmpty()) { 4645 return true; 4646 } 4647 width = rect.Width(); 4648 uint32_t dst_color; 4649 if (alpha_flag >> 8) { 4650 dst_color = FXCMYK_TODIB(color); 4651 } else { 4652 dst_color = FXARGB_TODIB(color); 4653 } 4654 uint8_t* color_p = (uint8_t*)&dst_color; 4655 if (m_bpp == 8) { 4656 uint8_t gray = 255; 4657 if (!IsAlphaMask()) { 4658 if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() && 4659 CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { 4660 CCodec_IccModule* pIccModule = 4661 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 4662 pIccModule->TranslateScanline(pIccTransform, &gray, color_p, 1); 4663 } else { 4664 if (alpha_flag >> 8) { 4665 uint8_t r, g, b; 4666 AdobeCMYK_to_sRGB1(color_p[0], color_p[1], color_p[2], color_p[3], r, 4667 g, b); 4668 gray = FXRGB2GRAY(r, g, b); 4669 } else { 4670 gray = (uint8_t)FXRGB2GRAY((int)color_p[2], color_p[1], color_p[0]); 4671 } 4672 } 4673 if (IsCmykImage()) { 4674 gray = ~gray; 4675 } 4676 } 4677 for (int row = rect.top; row < rect.bottom; row++) { 4678 uint8_t* dest_scan = m_pBuffer + row * m_Pitch + rect.left; 4679 if (src_alpha == 255) { 4680 FXSYS_memset(dest_scan, gray, width); 4681 } else { 4682 for (int col = 0; col < width; col++) { 4683 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 4684 dest_scan++; 4685 } 4686 } 4687 } 4688 return true; 4689 } 4690 if (m_bpp == 1) { 4691 ASSERT(!IsCmykImage() && (uint8_t)(alpha_flag >> 8) == 0); 4692 int left_shift = rect.left % 8; 4693 int right_shift = rect.right % 8; 4694 int new_width = rect.right / 8 - rect.left / 8; 4695 int index = 0; 4696 if (m_pPalette) { 4697 for (int i = 0; i < 2; i++) { 4698 if (m_pPalette.get()[i] == color) { 4699 index = i; 4700 } 4701 } 4702 } else { 4703 index = ((uint8_t)color == 0xff) ? 1 : 0; 4704 } 4705 for (int row = rect.top; row < rect.bottom; row++) { 4706 uint8_t* dest_scan_top = (uint8_t*)GetScanline(row) + rect.left / 8; 4707 uint8_t* dest_scan_top_r = (uint8_t*)GetScanline(row) + rect.right / 8; 4708 uint8_t left_flag = *dest_scan_top & (255 << (8 - left_shift)); 4709 uint8_t right_flag = *dest_scan_top_r & (255 >> right_shift); 4710 if (new_width) { 4711 FXSYS_memset(dest_scan_top + 1, index ? 255 : 0, new_width - 1); 4712 if (!index) { 4713 *dest_scan_top &= left_flag; 4714 *dest_scan_top_r &= right_flag; 4715 } else { 4716 *dest_scan_top |= ~left_flag; 4717 *dest_scan_top_r |= ~right_flag; 4718 } 4719 } else { 4720 if (!index) { 4721 *dest_scan_top &= left_flag | right_flag; 4722 } else { 4723 *dest_scan_top |= ~(left_flag | right_flag); 4724 } 4725 } 4726 } 4727 return true; 4728 } 4729 ASSERT(m_bpp >= 24); 4730 if (m_bpp < 24) { 4731 return false; 4732 } 4733 if (pIccTransform && CFX_GEModule::Get()->GetCodecModule()) { 4734 CCodec_IccModule* pIccModule = 4735 CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 4736 pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1); 4737 } else { 4738 if (alpha_flag >> 8 && !IsCmykImage()) { 4739 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), 4740 FXSYS_GetYValue(color), FXSYS_GetKValue(color), 4741 color_p[2], color_p[1], color_p[0]); 4742 } else if (!(alpha_flag >> 8) && IsCmykImage()) { 4743 return false; 4744 } 4745 } 4746 if (!IsCmykImage()) { 4747 color_p[3] = (uint8_t)src_alpha; 4748 } 4749 int Bpp = m_bpp / 8; 4750 bool bAlpha = HasAlpha(); 4751 bool bArgb = GetFormat() == FXDIB_Argb; 4752 if (src_alpha == 255) { 4753 for (int row = rect.top; row < rect.bottom; row++) { 4754 uint8_t* dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp; 4755 uint8_t* dest_scan_alpha = 4756 m_pAlphaMask ? (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left 4757 : nullptr; 4758 if (dest_scan_alpha) { 4759 FXSYS_memset(dest_scan_alpha, 0xff, width); 4760 } 4761 if (Bpp == 4) { 4762 uint32_t* scan = (uint32_t*)dest_scan; 4763 for (int col = 0; col < width; col++) { 4764 *scan++ = dst_color; 4765 } 4766 } else { 4767 for (int col = 0; col < width; col++) { 4768 *dest_scan++ = color_p[0]; 4769 *dest_scan++ = color_p[1]; 4770 *dest_scan++ = color_p[2]; 4771 } 4772 } 4773 } 4774 return true; 4775 } 4776 for (int row = rect.top; row < rect.bottom; row++) { 4777 uint8_t* dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp; 4778 if (bAlpha) { 4779 if (bArgb) { 4780 for (int col = 0; col < width; col++) { 4781 uint8_t back_alpha = dest_scan[3]; 4782 if (back_alpha == 0) { 4783 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, color_p[2], 4784 color_p[1], color_p[0])); 4785 dest_scan += 4; 4786 continue; 4787 } 4788 uint8_t dest_alpha = 4789 back_alpha + src_alpha - back_alpha * src_alpha / 255; 4790 int alpha_ratio = src_alpha * 255 / dest_alpha; 4791 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[0], alpha_ratio); 4792 dest_scan++; 4793 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[1], alpha_ratio); 4794 dest_scan++; 4795 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[2], alpha_ratio); 4796 dest_scan++; 4797 *dest_scan++ = dest_alpha; 4798 } 4799 } else { 4800 uint8_t* dest_scan_alpha = 4801 (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left; 4802 for (int col = 0; col < width; col++) { 4803 uint8_t back_alpha = *dest_scan_alpha; 4804 if (back_alpha == 0) { 4805 *dest_scan_alpha++ = src_alpha; 4806 FXSYS_memcpy(dest_scan, color_p, Bpp); 4807 dest_scan += Bpp; 4808 continue; 4809 } 4810 uint8_t dest_alpha = 4811 back_alpha + src_alpha - back_alpha * src_alpha / 255; 4812 *dest_scan_alpha++ = dest_alpha; 4813 int alpha_ratio = src_alpha * 255 / dest_alpha; 4814 for (int comps = 0; comps < Bpp; comps++) { 4815 *dest_scan = 4816 FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], alpha_ratio); 4817 dest_scan++; 4818 } 4819 } 4820 } 4821 } else { 4822 for (int col = 0; col < width; col++) { 4823 for (int comps = 0; comps < Bpp; comps++) { 4824 if (comps == 3) { 4825 *dest_scan++ = 255; 4826 continue; 4827 } 4828 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], src_alpha); 4829 dest_scan++; 4830 } 4831 } 4832 } 4833 } 4834 return true; 4835 } 4836 4837 CFX_BitmapComposer::CFX_BitmapComposer() { 4838 m_pScanlineV = nullptr; 4839 m_pScanlineAlphaV = nullptr; 4840 m_pClipScanV = nullptr; 4841 m_pAddClipScan = nullptr; 4842 m_bRgbByteOrder = false; 4843 m_BlendType = FXDIB_BLEND_NORMAL; 4844 } 4845 4846 CFX_BitmapComposer::~CFX_BitmapComposer() { 4847 FX_Free(m_pScanlineV); 4848 FX_Free(m_pScanlineAlphaV); 4849 FX_Free(m_pClipScanV); 4850 FX_Free(m_pAddClipScan); 4851 } 4852 4853 void CFX_BitmapComposer::Compose(CFX_DIBitmap* pDest, 4854 const CFX_ClipRgn* pClipRgn, 4855 int bitmap_alpha, 4856 uint32_t mask_color, 4857 FX_RECT& dest_rect, 4858 bool bVertical, 4859 bool bFlipX, 4860 bool bFlipY, 4861 bool bRgbByteOrder, 4862 int alpha_flag, 4863 void* pIccTransform, 4864 int blend_type) { 4865 m_pBitmap = pDest; 4866 m_pClipRgn = pClipRgn; 4867 m_DestLeft = dest_rect.left; 4868 m_DestTop = dest_rect.top; 4869 m_DestWidth = dest_rect.Width(); 4870 m_DestHeight = dest_rect.Height(); 4871 m_BitmapAlpha = bitmap_alpha; 4872 m_MaskColor = mask_color; 4873 m_pClipMask = nullptr; 4874 if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { 4875 m_pClipMask = pClipRgn->GetMask().GetObject(); 4876 } 4877 m_bVertical = bVertical; 4878 m_bFlipX = bFlipX; 4879 m_bFlipY = bFlipY; 4880 m_AlphaFlag = alpha_flag; 4881 m_pIccTransform = pIccTransform; 4882 m_bRgbByteOrder = bRgbByteOrder; 4883 m_BlendType = blend_type; 4884 } 4885 bool CFX_BitmapComposer::SetInfo(int width, 4886 int height, 4887 FXDIB_Format src_format, 4888 uint32_t* pSrcPalette) { 4889 m_SrcFormat = src_format; 4890 if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, pSrcPalette, 4891 m_MaskColor, FXDIB_BLEND_NORMAL, 4892 m_pClipMask != nullptr || (m_BitmapAlpha < 255), 4893 m_bRgbByteOrder, m_AlphaFlag, m_pIccTransform)) { 4894 return false; 4895 } 4896 if (m_bVertical) { 4897 m_pScanlineV = FX_Alloc(uint8_t, m_pBitmap->GetBPP() / 8 * width + 4); 4898 m_pClipScanV = FX_Alloc(uint8_t, m_pBitmap->GetHeight()); 4899 if (m_pBitmap->m_pAlphaMask) { 4900 m_pScanlineAlphaV = FX_Alloc(uint8_t, width + 4); 4901 } 4902 } 4903 if (m_BitmapAlpha < 255) { 4904 m_pAddClipScan = FX_Alloc( 4905 uint8_t, m_bVertical ? m_pBitmap->GetHeight() : m_pBitmap->GetWidth()); 4906 } 4907 return true; 4908 } 4909 4910 void CFX_BitmapComposer::DoCompose(uint8_t* dest_scan, 4911 const uint8_t* src_scan, 4912 int dest_width, 4913 const uint8_t* clip_scan, 4914 const uint8_t* src_extra_alpha, 4915 uint8_t* dst_extra_alpha) { 4916 if (m_BitmapAlpha < 255) { 4917 if (clip_scan) { 4918 for (int i = 0; i < dest_width; i++) { 4919 m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255; 4920 } 4921 } else { 4922 FXSYS_memset(m_pAddClipScan, m_BitmapAlpha, dest_width); 4923 } 4924 clip_scan = m_pAddClipScan; 4925 } 4926 if (m_SrcFormat == FXDIB_8bppMask) { 4927 m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width, 4928 clip_scan, dst_extra_alpha); 4929 } else if ((m_SrcFormat & 0xff) == 8) { 4930 m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width, 4931 clip_scan, src_extra_alpha, 4932 dst_extra_alpha); 4933 } else { 4934 m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width, 4935 clip_scan, src_extra_alpha, 4936 dst_extra_alpha); 4937 } 4938 } 4939 4940 void CFX_BitmapComposer::ComposeScanline(int line, 4941 const uint8_t* scanline, 4942 const uint8_t* scan_extra_alpha) { 4943 if (m_bVertical) { 4944 ComposeScanlineV(line, scanline, scan_extra_alpha); 4945 return; 4946 } 4947 const uint8_t* clip_scan = nullptr; 4948 if (m_pClipMask) 4949 clip_scan = m_pClipMask->GetBuffer() + 4950 (m_DestTop + line - m_pClipRgn->GetBox().top) * 4951 m_pClipMask->GetPitch() + 4952 (m_DestLeft - m_pClipRgn->GetBox().left); 4953 uint8_t* dest_scan = (uint8_t*)m_pBitmap->GetScanline(line + m_DestTop) + 4954 m_DestLeft * m_pBitmap->GetBPP() / 8; 4955 uint8_t* dest_alpha_scan = 4956 m_pBitmap->m_pAlphaMask 4957 ? (uint8_t*)m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop) + 4958 m_DestLeft 4959 : nullptr; 4960 DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha, 4961 dest_alpha_scan); 4962 } 4963 4964 void CFX_BitmapComposer::ComposeScanlineV(int line, 4965 const uint8_t* scanline, 4966 const uint8_t* scan_extra_alpha) { 4967 int i; 4968 int Bpp = m_pBitmap->GetBPP() / 8; 4969 int dest_pitch = m_pBitmap->GetPitch(); 4970 int dest_alpha_pitch = 4971 m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetPitch() : 0; 4972 int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line); 4973 uint8_t* dest_buf = 4974 m_pBitmap->GetBuffer() + dest_x * Bpp + m_DestTop * dest_pitch; 4975 uint8_t* dest_alpha_buf = m_pBitmap->m_pAlphaMask 4976 ? m_pBitmap->m_pAlphaMask->GetBuffer() + 4977 dest_x + m_DestTop * dest_alpha_pitch 4978 : nullptr; 4979 if (m_bFlipY) { 4980 dest_buf += dest_pitch * (m_DestHeight - 1); 4981 dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1); 4982 } 4983 int y_step = dest_pitch; 4984 int y_alpha_step = dest_alpha_pitch; 4985 if (m_bFlipY) { 4986 y_step = -y_step; 4987 y_alpha_step = -y_alpha_step; 4988 } 4989 uint8_t* src_scan = m_pScanlineV; 4990 uint8_t* dest_scan = dest_buf; 4991 for (i = 0; i < m_DestHeight; i++) { 4992 for (int j = 0; j < Bpp; j++) { 4993 *src_scan++ = dest_scan[j]; 4994 } 4995 dest_scan += y_step; 4996 } 4997 uint8_t* src_alpha_scan = m_pScanlineAlphaV; 4998 uint8_t* dest_alpha_scan = dest_alpha_buf; 4999 if (dest_alpha_scan) { 5000 for (i = 0; i < m_DestHeight; i++) { 5001 *src_alpha_scan++ = *dest_alpha_scan; 5002 dest_alpha_scan += y_alpha_step; 5003 } 5004 } 5005 uint8_t* clip_scan = nullptr; 5006 if (m_pClipMask) { 5007 clip_scan = m_pClipScanV; 5008 int clip_pitch = m_pClipMask->GetPitch(); 5009 const uint8_t* src_clip = 5010 m_pClipMask->GetBuffer() + 5011 (m_DestTop - m_pClipRgn->GetBox().top) * clip_pitch + 5012 (dest_x - m_pClipRgn->GetBox().left); 5013 if (m_bFlipY) { 5014 src_clip += clip_pitch * (m_DestHeight - 1); 5015 clip_pitch = -clip_pitch; 5016 } 5017 for (i = 0; i < m_DestHeight; i++) { 5018 clip_scan[i] = *src_clip; 5019 src_clip += clip_pitch; 5020 } 5021 } 5022 DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan, scan_extra_alpha, 5023 m_pScanlineAlphaV); 5024 src_scan = m_pScanlineV; 5025 dest_scan = dest_buf; 5026 for (i = 0; i < m_DestHeight; i++) { 5027 for (int j = 0; j < Bpp; j++) { 5028 dest_scan[j] = *src_scan++; 5029 } 5030 dest_scan += y_step; 5031 } 5032 src_alpha_scan = m_pScanlineAlphaV; 5033 dest_alpha_scan = dest_alpha_buf; 5034 if (dest_alpha_scan) { 5035 for (i = 0; i < m_DestHeight; i++) { 5036 *dest_alpha_scan = *src_alpha_scan++; 5037 dest_alpha_scan += y_alpha_step; 5038 } 5039 } 5040 } 5041