1 // Copyright 2017 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/fxge/dib/cfx_scanlinecompositor.h" 8 9 #include <algorithm> 10 11 #include "core/fxcodec/fx_codec.h" 12 13 #define FX_CCOLOR(val) (255 - (val)) 14 #define FXDIB_ALPHA_UNION(dest, src) ((dest) + (src) - (dest) * (src) / 255) 15 #define FXARGB_COPY(dest, src) \ 16 *(dest) = *(src), *((dest) + 1) = *((src) + 1), \ 17 *((dest) + 2) = *((src) + 2), *((dest) + 3) = *((src) + 3) 18 #define FXARGB_RGBORDERCOPY(dest, src) \ 19 *((dest) + 3) = *((src) + 3), *(dest) = *((src) + 2), \ 20 *((dest) + 1) = *((src) + 1), *((dest) + 2) = *((src)) 21 22 namespace { 23 24 const uint8_t color_sqrt[256] = { 25 0x00, 0x03, 0x07, 0x0B, 0x0F, 0x12, 0x16, 0x19, 0x1D, 0x20, 0x23, 0x26, 26 0x29, 0x2C, 0x2F, 0x32, 0x35, 0x37, 0x3A, 0x3C, 0x3F, 0x41, 0x43, 0x46, 27 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x57, 0x59, 0x5B, 0x5C, 28 0x5E, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 29 0x6E, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 30 0x7B, 0x7C, 0x7D, 0x7E, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 31 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x91, 32 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 33 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5, 34 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE, 35 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7, 36 0xB7, 0xB8, 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBE, 0xBF, 37 0xC0, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7, 38 0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCE, 39 0xCF, 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6, 40 0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, 41 0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE2, 0xE3, 0xE4, 42 0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, 43 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE, 0xEF, 0xF0, 0xF0, 0xF1, 44 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7, 45 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 46 0xFD, 0xFE, 0xFE, 0xFF}; 47 48 int Blend(int blend_mode, int back_color, int src_color) { 49 switch (blend_mode) { 50 case FXDIB_BLEND_NORMAL: 51 return src_color; 52 case FXDIB_BLEND_MULTIPLY: 53 return src_color * back_color / 255; 54 case FXDIB_BLEND_SCREEN: 55 return src_color + back_color - src_color * back_color / 255; 56 case FXDIB_BLEND_OVERLAY: 57 return Blend(FXDIB_BLEND_HARDLIGHT, src_color, back_color); 58 case FXDIB_BLEND_DARKEN: 59 return src_color < back_color ? src_color : back_color; 60 case FXDIB_BLEND_LIGHTEN: 61 return src_color > back_color ? src_color : back_color; 62 case FXDIB_BLEND_COLORDODGE: { 63 if (src_color == 255) 64 return src_color; 65 66 return std::min(back_color * 255 / (255 - src_color), 255); 67 } 68 case FXDIB_BLEND_COLORBURN: { 69 if (src_color == 0) 70 return src_color; 71 72 return 255 - std::min((255 - back_color) * 255 / src_color, 255); 73 } 74 case FXDIB_BLEND_HARDLIGHT: 75 if (src_color < 128) 76 return (src_color * back_color * 2) / 255; 77 78 return Blend(FXDIB_BLEND_SCREEN, back_color, 2 * src_color - 255); 79 case FXDIB_BLEND_SOFTLIGHT: { 80 if (src_color < 128) { 81 return back_color - 82 (255 - 2 * src_color) * back_color * (255 - back_color) / 255 / 83 255; 84 } 85 return back_color + 86 (2 * src_color - 255) * (color_sqrt[back_color] - back_color) / 87 255; 88 } 89 case FXDIB_BLEND_DIFFERENCE: 90 return back_color < src_color ? src_color - back_color 91 : back_color - src_color; 92 case FXDIB_BLEND_EXCLUSION: 93 return back_color + src_color - 2 * back_color * src_color / 255; 94 } 95 return src_color; 96 } 97 98 struct RGB { 99 int red; 100 int green; 101 int blue; 102 }; 103 104 int Lum(RGB color) { 105 return (color.red * 30 + color.green * 59 + color.blue * 11) / 100; 106 } 107 108 RGB ClipColor(RGB color) { 109 int l = Lum(color); 110 int n = std::min(color.red, std::min(color.green, color.blue)); 111 int x = std::max(color.red, std::max(color.green, color.blue)); 112 if (n < 0) { 113 color.red = l + ((color.red - l) * l / (l - n)); 114 color.green = l + ((color.green - l) * l / (l - n)); 115 color.blue = l + ((color.blue - l) * l / (l - n)); 116 } 117 if (x > 255) { 118 color.red = l + ((color.red - l) * (255 - l) / (x - l)); 119 color.green = l + ((color.green - l) * (255 - l) / (x - l)); 120 color.blue = l + ((color.blue - l) * (255 - l) / (x - l)); 121 } 122 return color; 123 } 124 125 RGB SetLum(RGB color, int l) { 126 int d = l - Lum(color); 127 color.red += d; 128 color.green += d; 129 color.blue += d; 130 return ClipColor(color); 131 } 132 133 int Sat(RGB color) { 134 return std::max(color.red, std::max(color.green, color.blue)) - 135 std::min(color.red, std::min(color.green, color.blue)); 136 } 137 138 RGB SetSat(RGB color, int s) { 139 int min = std::min(color.red, std::min(color.green, color.blue)); 140 int max = std::max(color.red, std::max(color.green, color.blue)); 141 if (min == max) 142 return {0, 0, 0}; 143 144 color.red = (color.red - min) * s / (max - min); 145 color.green = (color.green - min) * s / (max - min); 146 color.blue = (color.blue - min) * s / (max - min); 147 return color; 148 } 149 150 void RGB_Blend(int blend_mode, 151 const uint8_t* src_scan, 152 const uint8_t* dest_scan, 153 int results[3]) { 154 RGB result = {0, 0, 0}; 155 RGB src; 156 src.red = src_scan[2]; 157 src.green = src_scan[1]; 158 src.blue = src_scan[0]; 159 RGB back; 160 back.red = dest_scan[2]; 161 back.green = dest_scan[1]; 162 back.blue = dest_scan[0]; 163 switch (blend_mode) { 164 case FXDIB_BLEND_HUE: 165 result = SetLum(SetSat(src, Sat(back)), Lum(back)); 166 break; 167 case FXDIB_BLEND_SATURATION: 168 result = SetLum(SetSat(back, Sat(src)), Lum(back)); 169 break; 170 case FXDIB_BLEND_COLOR: 171 result = SetLum(src, Lum(back)); 172 break; 173 case FXDIB_BLEND_LUMINOSITY: 174 result = SetLum(back, Lum(src)); 175 break; 176 } 177 results[0] = result.blue; 178 results[1] = result.green; 179 results[2] = result.red; 180 } 181 182 int GetAlpha(uint8_t src_alpha, const uint8_t* clip_scan, int col) { 183 return clip_scan ? clip_scan[col] * src_alpha / 255 : src_alpha; 184 } 185 186 void CompositeRow_AlphaToMask(uint8_t* dest_scan, 187 const uint8_t* src_scan, 188 int pixel_count, 189 const uint8_t* clip_scan, 190 uint8_t stride) { 191 src_scan += stride - 1; 192 for (int col = 0; col < pixel_count; ++col) { 193 int src_alpha = GetAlpha(*src_scan, clip_scan, col); 194 uint8_t back_alpha = *dest_scan; 195 if (!back_alpha) 196 *dest_scan = src_alpha; 197 else if (src_alpha) 198 *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; 199 ++dest_scan; 200 src_scan += stride; 201 } 202 } 203 204 void CompositeRow_Rgb2Mask(uint8_t* dest_scan, 205 const uint8_t* src_scan, 206 int width, 207 const uint8_t* clip_scan) { 208 if (!clip_scan) { 209 memset(dest_scan, 0xff, width); 210 return; 211 } 212 for (int i = 0; i < width; ++i) { 213 *dest_scan = FXDIB_ALPHA_UNION(*dest_scan, *clip_scan); 214 ++dest_scan; 215 ++clip_scan; 216 } 217 } 218 219 uint8_t GetGray(const uint8_t* src_scan) { 220 return FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); 221 } 222 223 uint8_t GetGrayWithBlend(const uint8_t* src_scan, 224 const uint8_t* dest_scan, 225 int blend_type) { 226 uint8_t gray = GetGray(src_scan); 227 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) 228 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 229 else if (blend_type) 230 gray = Blend(blend_type, *dest_scan, gray); 231 return gray; 232 } 233 234 void CompositeRow_Argb2Graya(uint8_t* dest_scan, 235 const uint8_t* src_scan, 236 int pixel_count, 237 int blend_type, 238 const uint8_t* clip_scan, 239 const uint8_t* src_alpha_scan, 240 uint8_t* dst_alpha_scan) { 241 uint8_t offset = src_alpha_scan ? 3 : 4; 242 for (int col = 0; col < pixel_count; ++col) { 243 const uint8_t* alpha_scan = 244 src_alpha_scan ? src_alpha_scan++ : &src_scan[3]; 245 uint8_t back_alpha = *dst_alpha_scan; 246 if (back_alpha == 0) { 247 int src_alpha = GetAlpha(*alpha_scan, clip_scan, col); 248 if (src_alpha) { 249 *dest_scan = GetGray(src_scan); 250 *dst_alpha_scan = src_alpha; 251 } 252 ++dest_scan; 253 ++dst_alpha_scan; 254 src_scan += offset; 255 continue; 256 } 257 uint8_t src_alpha = GetAlpha(*alpha_scan, clip_scan, col); 258 if (src_alpha == 0) { 259 ++dest_scan; 260 ++dst_alpha_scan; 261 src_scan += offset; 262 continue; 263 } 264 *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); 265 int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); 266 uint8_t gray = GetGray(src_scan); 267 // TODO(npm): Does this if really need src_alpha_scan or was that a bug? 268 if (blend_type && src_alpha_scan) { 269 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) 270 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 271 else 272 gray = Blend(blend_type, *dest_scan, gray); 273 } 274 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 275 ++dest_scan; 276 ++dst_alpha_scan; 277 src_scan += offset; 278 } 279 } 280 281 void CompositeRow_Argb2Gray(uint8_t* dest_scan, 282 const uint8_t* src_scan, 283 int pixel_count, 284 int blend_type, 285 const uint8_t* clip_scan, 286 const uint8_t* src_alpha_scan) { 287 uint8_t gray; 288 uint8_t offset = src_alpha_scan ? 3 : 4; 289 for (int col = 0; col < pixel_count; ++col) { 290 const uint8_t* alpha_scan = 291 src_alpha_scan ? src_alpha_scan++ : &src_scan[3]; 292 int src_alpha = GetAlpha(*alpha_scan, clip_scan, col); 293 if (src_alpha) { 294 gray = GetGrayWithBlend(src_scan, dest_scan, blend_type); 295 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 296 } 297 ++dest_scan; 298 src_scan += offset; 299 } 300 } 301 302 void CompositeRow_Rgb2Gray(uint8_t* dest_scan, 303 const uint8_t* src_scan, 304 int src_Bpp, 305 int pixel_count, 306 int blend_type, 307 const uint8_t* clip_scan) { 308 uint8_t gray; 309 for (int col = 0; col < pixel_count; ++col) { 310 gray = GetGrayWithBlend(src_scan, dest_scan, blend_type); 311 if (clip_scan && clip_scan[col] < 255) 312 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 313 else 314 *dest_scan = gray; 315 ++dest_scan; 316 src_scan += src_Bpp; 317 } 318 } 319 320 void CompositeRow_Rgb2Graya(uint8_t* dest_scan, 321 const uint8_t* src_scan, 322 int src_Bpp, 323 int pixel_count, 324 int blend_type, 325 const uint8_t* clip_scan, 326 uint8_t* dest_alpha_scan) { 327 for (int col = 0; col < pixel_count; ++col) { 328 if (blend_type && *dest_alpha_scan == 0) { 329 *dest_scan = GetGray(src_scan); 330 ++dest_scan; 331 ++dest_alpha_scan; 332 src_scan += src_Bpp; 333 continue; 334 } 335 int src_alpha = clip_scan ? clip_scan[col] : 255; 336 if (src_alpha == 255) { 337 *dest_scan = GetGrayWithBlend(src_scan, dest_scan, blend_type); 338 ++dest_scan; 339 *dest_alpha_scan = 255; 340 ++dest_alpha_scan; 341 src_scan += src_Bpp; 342 continue; 343 } 344 if (src_alpha == 0) { 345 ++dest_scan; 346 ++dest_alpha_scan; 347 src_scan += src_Bpp; 348 continue; 349 } 350 int back_alpha = *dest_alpha_scan; 351 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 352 *dest_alpha_scan = dest_alpha; 353 ++dest_alpha_scan; 354 int alpha_ratio = src_alpha * 255 / dest_alpha; 355 uint8_t gray = GetGrayWithBlend(src_scan, dest_scan, blend_type); 356 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 357 ++dest_scan; 358 src_scan += src_Bpp; 359 } 360 } 361 362 void CompositeRow_Argb2Argb(uint8_t* dest_scan, 363 const uint8_t* src_scan, 364 int pixel_count, 365 int blend_type, 366 const uint8_t* clip_scan, 367 uint8_t* dest_alpha_scan, 368 const uint8_t* src_alpha_scan) { 369 int blended_colors[3]; 370 uint8_t dest_offset = dest_alpha_scan ? 3 : 4; 371 uint8_t src_offset = src_alpha_scan ? 3 : 4; 372 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 373 bool has_src = !!src_alpha_scan; 374 bool has_dest = !!dest_alpha_scan; 375 for (int col = 0; col < pixel_count; ++col) { 376 uint8_t back_alpha = has_dest ? *dest_alpha_scan : dest_scan[3]; 377 const uint8_t* alpha_source = has_src ? src_alpha_scan++ : &src_scan[3]; 378 uint8_t src_alpha = GetAlpha(*alpha_source, clip_scan, col); 379 if (back_alpha == 0) { 380 if (!has_dest && !has_src) { 381 if (clip_scan) { 382 FXARGB_SETDIB(dest_scan, (FXARGB_GETDIB(src_scan) & 0xffffff) | 383 (src_alpha << 24)); 384 } else { 385 FXARGB_COPY(dest_scan, src_scan); 386 } 387 } else if (has_dest) { 388 *dest_alpha_scan = src_alpha; 389 for (int i = 0; i < 3; ++i) { 390 *dest_scan = *src_scan++; 391 ++dest_scan; 392 } 393 ++dest_alpha_scan; 394 if (!has_src) 395 ++src_scan; 396 } else { 397 FXARGB_SETDIB(dest_scan, FXARGB_MAKE((src_alpha << 24), src_scan[2], 398 src_scan[1], *src_scan)); 399 } 400 if (!has_dest) { 401 dest_scan += dest_offset; 402 src_scan += src_offset; 403 } 404 continue; 405 } 406 if (src_alpha == 0) { 407 dest_scan += dest_offset; 408 src_scan += src_offset; 409 if (has_dest) 410 ++dest_alpha_scan; 411 continue; 412 } 413 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 414 if (has_dest) { 415 *dest_alpha_scan = dest_alpha; 416 ++dest_alpha_scan; 417 } else { 418 dest_scan[3] = dest_alpha; 419 } 420 int alpha_ratio = src_alpha * 255 / dest_alpha; 421 if (bNonseparableBlend) 422 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 423 for (int color = 0; color < 3; ++color) { 424 if (blend_type) { 425 int blended = bNonseparableBlend 426 ? blended_colors[color] 427 : Blend(blend_type, *dest_scan, *src_scan); 428 blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); 429 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 430 } else { 431 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); 432 } 433 ++dest_scan; 434 ++src_scan; 435 } 436 if (!has_dest) 437 ++dest_scan; 438 if (!has_src) 439 ++src_scan; 440 } 441 } 442 443 void CompositeRow_Rgb2Argb_Blend_NoClip(uint8_t* dest_scan, 444 const uint8_t* src_scan, 445 int width, 446 int blend_type, 447 int src_Bpp, 448 uint8_t* dest_alpha_scan) { 449 int blended_colors[3]; 450 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 451 int src_gap = src_Bpp - 3; 452 for (int col = 0; col < width; ++col) { 453 uint8_t* dest_alpha = dest_alpha_scan ? dest_alpha_scan : &dest_scan[3]; 454 uint8_t back_alpha = *dest_alpha; 455 if (back_alpha == 0) { 456 if (dest_alpha_scan) { 457 for (int i = 0; i < 3; ++i) { 458 *dest_scan = *src_scan++; 459 ++dest_scan; 460 } 461 *dest_alpha_scan = 0xff; 462 ++dest_alpha_scan; 463 } else { 464 if (src_Bpp == 4) { 465 FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); 466 } else { 467 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], 468 src_scan[0])); 469 } 470 dest_scan += 4; 471 } 472 src_scan += src_Bpp; 473 continue; 474 } 475 *dest_alpha = 0xff; 476 if (bNonseparableBlend) 477 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 478 for (int color = 0; color < 3; ++color) { 479 int src_color = *src_scan; 480 int blended = bNonseparableBlend 481 ? blended_colors[color] 482 : Blend(blend_type, *dest_scan, src_color); 483 *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 484 ++dest_scan; 485 ++src_scan; 486 } 487 if (dest_alpha_scan) 488 ++dest_alpha_scan; 489 else 490 ++dest_scan; 491 src_scan += src_gap; 492 } 493 } 494 495 void CompositeRow_Rgb2Argb_Blend_Clip(uint8_t* dest_scan, 496 const uint8_t* src_scan, 497 int width, 498 int blend_type, 499 int src_Bpp, 500 const uint8_t* clip_scan, 501 uint8_t* dest_alpha_scan) { 502 int blended_colors[3]; 503 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 504 int src_gap = src_Bpp - 3; 505 bool has_dest = !!dest_alpha_scan; 506 for (int col = 0; col < width; ++col) { 507 int src_alpha = *clip_scan++; 508 uint8_t back_alpha = has_dest ? *dest_alpha_scan : dest_scan[3]; 509 if (back_alpha == 0) { 510 for (int i = 0; i < 3; ++i) { 511 *dest_scan = *src_scan++; 512 ++dest_scan; 513 } 514 src_scan += src_gap; 515 if (has_dest) 516 dest_alpha_scan++; 517 else 518 dest_scan++; 519 continue; 520 } 521 if (src_alpha == 0) { 522 dest_scan += has_dest ? 3 : 4; 523 if (has_dest) 524 dest_alpha_scan++; 525 src_scan += src_Bpp; 526 continue; 527 } 528 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 529 if (has_dest) 530 *dest_alpha_scan++ = dest_alpha; 531 else 532 dest_scan[3] = dest_alpha; 533 int alpha_ratio = src_alpha * 255 / dest_alpha; 534 if (bNonseparableBlend) 535 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 536 for (int color = 0; color < 3; color++) { 537 int src_color = *src_scan; 538 int blended = bNonseparableBlend 539 ? blended_colors[color] 540 : Blend(blend_type, *dest_scan, src_color); 541 blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 542 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 543 dest_scan++; 544 src_scan++; 545 } 546 src_scan += src_gap; 547 if (!has_dest) 548 dest_scan++; 549 } 550 } 551 552 void CompositeRow_Rgb2Argb_NoBlend_Clip(uint8_t* dest_scan, 553 const uint8_t* src_scan, 554 int width, 555 int src_Bpp, 556 const uint8_t* clip_scan, 557 uint8_t* dest_alpha_scan) { 558 int src_gap = src_Bpp - 3; 559 if (dest_alpha_scan) { 560 for (int col = 0; col < width; col++) { 561 int src_alpha = clip_scan[col]; 562 if (src_alpha == 255) { 563 *dest_scan++ = *src_scan++; 564 *dest_scan++ = *src_scan++; 565 *dest_scan++ = *src_scan++; 566 *dest_alpha_scan++ = 255; 567 src_scan += src_gap; 568 continue; 569 } 570 if (src_alpha == 0) { 571 dest_scan += 3; 572 dest_alpha_scan++; 573 src_scan += src_Bpp; 574 continue; 575 } 576 int back_alpha = *dest_alpha_scan; 577 uint8_t dest_alpha = 578 back_alpha + src_alpha - back_alpha * src_alpha / 255; 579 *dest_alpha_scan++ = dest_alpha; 580 int alpha_ratio = src_alpha * 255 / dest_alpha; 581 for (int color = 0; color < 3; color++) { 582 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); 583 dest_scan++; 584 src_scan++; 585 } 586 src_scan += src_gap; 587 } 588 } else { 589 for (int col = 0; col < width; col++) { 590 int src_alpha = clip_scan[col]; 591 if (src_alpha == 255) { 592 *dest_scan++ = *src_scan++; 593 *dest_scan++ = *src_scan++; 594 *dest_scan++ = *src_scan++; 595 *dest_scan++ = 255; 596 src_scan += src_gap; 597 continue; 598 } 599 if (src_alpha == 0) { 600 dest_scan += 4; 601 src_scan += src_Bpp; 602 continue; 603 } 604 int back_alpha = dest_scan[3]; 605 uint8_t dest_alpha = 606 back_alpha + src_alpha - back_alpha * src_alpha / 255; 607 dest_scan[3] = dest_alpha; 608 int alpha_ratio = src_alpha * 255 / dest_alpha; 609 for (int color = 0; color < 3; color++) { 610 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); 611 dest_scan++; 612 src_scan++; 613 } 614 dest_scan++; 615 src_scan += src_gap; 616 } 617 } 618 } 619 620 void CompositeRow_Rgb2Argb_NoBlend_NoClip(uint8_t* dest_scan, 621 const uint8_t* src_scan, 622 int width, 623 int src_Bpp, 624 uint8_t* dest_alpha_scan) { 625 if (dest_alpha_scan) { 626 int src_gap = src_Bpp - 3; 627 for (int col = 0; col < width; col++) { 628 *dest_scan++ = *src_scan++; 629 *dest_scan++ = *src_scan++; 630 *dest_scan++ = *src_scan++; 631 *dest_alpha_scan++ = 0xff; 632 src_scan += src_gap; 633 } 634 } else { 635 for (int col = 0; col < width; col++) { 636 if (src_Bpp == 4) { 637 FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); 638 } else { 639 FXARGB_SETDIB(dest_scan, 640 FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0])); 641 } 642 dest_scan += 4; 643 src_scan += src_Bpp; 644 } 645 } 646 } 647 648 void CompositeRow_Argb2Rgb_Blend(uint8_t* dest_scan, 649 const uint8_t* src_scan, 650 int width, 651 int blend_type, 652 int dest_Bpp, 653 const uint8_t* clip_scan, 654 const uint8_t* src_alpha_scan) { 655 int blended_colors[3]; 656 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 657 int dest_gap = dest_Bpp - 3; 658 if (src_alpha_scan) { 659 for (int col = 0; col < width; col++) { 660 uint8_t src_alpha; 661 if (clip_scan) { 662 src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; 663 } else { 664 src_alpha = *src_alpha_scan++; 665 } 666 if (src_alpha == 0) { 667 dest_scan += dest_Bpp; 668 src_scan += 3; 669 continue; 670 } 671 if (bNonseparableBlend) { 672 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 673 } 674 for (int color = 0; color < 3; color++) { 675 int back_color = *dest_scan; 676 int blended = bNonseparableBlend 677 ? blended_colors[color] 678 : Blend(blend_type, back_color, *src_scan); 679 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 680 dest_scan++; 681 src_scan++; 682 } 683 dest_scan += dest_gap; 684 } 685 } else { 686 for (int col = 0; col < width; col++) { 687 uint8_t src_alpha; 688 if (clip_scan) { 689 src_alpha = src_scan[3] * (*clip_scan++) / 255; 690 } else { 691 src_alpha = src_scan[3]; 692 } 693 if (src_alpha == 0) { 694 dest_scan += dest_Bpp; 695 src_scan += 4; 696 continue; 697 } 698 if (bNonseparableBlend) { 699 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 700 } 701 for (int color = 0; color < 3; color++) { 702 int back_color = *dest_scan; 703 int blended = bNonseparableBlend 704 ? blended_colors[color] 705 : Blend(blend_type, back_color, *src_scan); 706 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 707 dest_scan++; 708 src_scan++; 709 } 710 dest_scan += dest_gap; 711 src_scan++; 712 } 713 } 714 } 715 716 void CompositeRow_Argb2Rgb_NoBlend(uint8_t* dest_scan, 717 const uint8_t* src_scan, 718 int width, 719 int dest_Bpp, 720 const uint8_t* clip_scan, 721 const uint8_t* src_alpha_scan) { 722 int dest_gap = dest_Bpp - 3; 723 if (src_alpha_scan) { 724 for (int col = 0; col < width; col++) { 725 uint8_t src_alpha; 726 if (clip_scan) { 727 src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; 728 } else { 729 src_alpha = *src_alpha_scan++; 730 } 731 if (src_alpha == 255) { 732 *dest_scan++ = *src_scan++; 733 *dest_scan++ = *src_scan++; 734 *dest_scan++ = *src_scan++; 735 dest_scan += dest_gap; 736 continue; 737 } 738 if (src_alpha == 0) { 739 dest_scan += dest_Bpp; 740 src_scan += 3; 741 continue; 742 } 743 for (int color = 0; color < 3; color++) { 744 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 745 dest_scan++; 746 src_scan++; 747 } 748 dest_scan += dest_gap; 749 } 750 } else { 751 for (int col = 0; col < width; col++) { 752 uint8_t src_alpha; 753 if (clip_scan) { 754 src_alpha = src_scan[3] * (*clip_scan++) / 255; 755 } else { 756 src_alpha = src_scan[3]; 757 } 758 if (src_alpha == 255) { 759 *dest_scan++ = *src_scan++; 760 *dest_scan++ = *src_scan++; 761 *dest_scan++ = *src_scan++; 762 dest_scan += dest_gap; 763 src_scan++; 764 continue; 765 } 766 if (src_alpha == 0) { 767 dest_scan += dest_Bpp; 768 src_scan += 4; 769 continue; 770 } 771 for (int color = 0; color < 3; color++) { 772 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 773 dest_scan++; 774 src_scan++; 775 } 776 dest_scan += dest_gap; 777 src_scan++; 778 } 779 } 780 } 781 782 void CompositeRow_Rgb2Rgb_Blend_NoClip(uint8_t* dest_scan, 783 const uint8_t* src_scan, 784 int width, 785 int blend_type, 786 int dest_Bpp, 787 int src_Bpp) { 788 int blended_colors[3]; 789 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 790 int dest_gap = dest_Bpp - 3; 791 int src_gap = src_Bpp - 3; 792 for (int col = 0; col < width; col++) { 793 if (bNonseparableBlend) { 794 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 795 } 796 for (int color = 0; color < 3; color++) { 797 int back_color = *dest_scan; 798 int src_color = *src_scan; 799 int blended = bNonseparableBlend 800 ? blended_colors[color] 801 : Blend(blend_type, back_color, src_color); 802 *dest_scan = blended; 803 dest_scan++; 804 src_scan++; 805 } 806 dest_scan += dest_gap; 807 src_scan += src_gap; 808 } 809 } 810 811 void CompositeRow_Rgb2Rgb_Blend_Clip(uint8_t* dest_scan, 812 const uint8_t* src_scan, 813 int width, 814 int blend_type, 815 int dest_Bpp, 816 int src_Bpp, 817 const uint8_t* clip_scan) { 818 int blended_colors[3]; 819 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 820 int dest_gap = dest_Bpp - 3; 821 int src_gap = src_Bpp - 3; 822 for (int col = 0; col < width; col++) { 823 uint8_t src_alpha = *clip_scan++; 824 if (src_alpha == 0) { 825 dest_scan += dest_Bpp; 826 src_scan += src_Bpp; 827 continue; 828 } 829 if (bNonseparableBlend) { 830 RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); 831 } 832 for (int color = 0; color < 3; color++) { 833 int src_color = *src_scan; 834 int back_color = *dest_scan; 835 int blended = bNonseparableBlend 836 ? blended_colors[color] 837 : Blend(blend_type, back_color, src_color); 838 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 839 dest_scan++; 840 src_scan++; 841 } 842 dest_scan += dest_gap; 843 src_scan += src_gap; 844 } 845 } 846 847 void CompositeRow_Rgb2Rgb_NoBlend_NoClip(uint8_t* dest_scan, 848 const uint8_t* src_scan, 849 int width, 850 int dest_Bpp, 851 int src_Bpp) { 852 if (dest_Bpp == src_Bpp) { 853 memcpy(dest_scan, src_scan, width * dest_Bpp); 854 return; 855 } 856 for (int col = 0; col < width; col++) { 857 dest_scan[0] = src_scan[0]; 858 dest_scan[1] = src_scan[1]; 859 dest_scan[2] = src_scan[2]; 860 dest_scan += dest_Bpp; 861 src_scan += src_Bpp; 862 } 863 } 864 865 void CompositeRow_Rgb2Rgb_NoBlend_Clip(uint8_t* dest_scan, 866 const uint8_t* src_scan, 867 int width, 868 int dest_Bpp, 869 int src_Bpp, 870 const uint8_t* clip_scan) { 871 for (int col = 0; col < width; col++) { 872 int src_alpha = clip_scan[col]; 873 if (src_alpha == 255) { 874 dest_scan[0] = src_scan[0]; 875 dest_scan[1] = src_scan[1]; 876 dest_scan[2] = src_scan[2]; 877 } else if (src_alpha) { 878 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 879 dest_scan++; 880 src_scan++; 881 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 882 dest_scan++; 883 src_scan++; 884 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); 885 dest_scan += dest_Bpp - 2; 886 src_scan += src_Bpp - 2; 887 continue; 888 } 889 dest_scan += dest_Bpp; 890 src_scan += src_Bpp; 891 } 892 } 893 894 void CompositeRow_8bppPal2Gray(uint8_t* dest_scan, 895 const uint8_t* src_scan, 896 const uint8_t* pPalette, 897 int pixel_count, 898 int blend_type, 899 const uint8_t* clip_scan, 900 const uint8_t* src_alpha_scan) { 901 if (src_alpha_scan) { 902 if (blend_type) { 903 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 904 for (int col = 0; col < pixel_count; col++) { 905 uint8_t gray = pPalette[*src_scan]; 906 int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); 907 if (bNonseparableBlend) 908 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 909 else 910 gray = Blend(blend_type, *dest_scan, gray); 911 if (src_alpha) 912 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 913 else 914 *dest_scan = gray; 915 dest_scan++; 916 src_scan++; 917 } 918 return; 919 } 920 for (int col = 0; col < pixel_count; col++) { 921 uint8_t gray = pPalette[*src_scan]; 922 int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); 923 if (src_alpha) 924 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 925 else 926 *dest_scan = gray; 927 dest_scan++; 928 src_scan++; 929 } 930 } else { 931 if (blend_type) { 932 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 933 for (int col = 0; col < pixel_count; col++) { 934 uint8_t gray = pPalette[*src_scan]; 935 if (bNonseparableBlend) 936 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 937 else 938 gray = Blend(blend_type, *dest_scan, gray); 939 if (clip_scan && clip_scan[col] < 255) 940 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 941 else 942 *dest_scan = gray; 943 dest_scan++; 944 src_scan++; 945 } 946 return; 947 } 948 for (int col = 0; col < pixel_count; col++) { 949 uint8_t gray = pPalette[*src_scan]; 950 if (clip_scan && clip_scan[col] < 255) 951 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 952 else 953 *dest_scan = gray; 954 dest_scan++; 955 src_scan++; 956 } 957 } 958 } 959 960 void CompositeRow_8bppPal2Graya(uint8_t* dest_scan, 961 const uint8_t* src_scan, 962 const uint8_t* pPalette, 963 int pixel_count, 964 int blend_type, 965 const uint8_t* clip_scan, 966 uint8_t* dest_alpha_scan, 967 const uint8_t* src_alpha_scan) { 968 if (src_alpha_scan) { 969 if (blend_type) { 970 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 971 for (int col = 0; col < pixel_count; col++) { 972 uint8_t gray = pPalette[*src_scan]; 973 src_scan++; 974 uint8_t back_alpha = *dest_alpha_scan; 975 if (back_alpha == 0) { 976 int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); 977 if (src_alpha) { 978 *dest_scan = gray; 979 *dest_alpha_scan = src_alpha; 980 } 981 dest_scan++; 982 dest_alpha_scan++; 983 continue; 984 } 985 uint8_t src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); 986 if (src_alpha == 0) { 987 dest_scan++; 988 dest_alpha_scan++; 989 continue; 990 } 991 *dest_alpha_scan = 992 back_alpha + src_alpha - back_alpha * src_alpha / 255; 993 int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan); 994 if (bNonseparableBlend) 995 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 996 else 997 gray = Blend(blend_type, *dest_scan, gray); 998 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 999 dest_alpha_scan++; 1000 dest_scan++; 1001 } 1002 return; 1003 } 1004 for (int col = 0; col < pixel_count; col++) { 1005 uint8_t gray = pPalette[*src_scan]; 1006 src_scan++; 1007 uint8_t back_alpha = *dest_alpha_scan; 1008 if (back_alpha == 0) { 1009 int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); 1010 if (src_alpha) { 1011 *dest_scan = gray; 1012 *dest_alpha_scan = src_alpha; 1013 } 1014 dest_scan++; 1015 dest_alpha_scan++; 1016 continue; 1017 } 1018 uint8_t src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); 1019 if (src_alpha == 0) { 1020 dest_scan++; 1021 dest_alpha_scan++; 1022 continue; 1023 } 1024 *dest_alpha_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1025 int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan); 1026 dest_alpha_scan++; 1027 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 1028 dest_scan++; 1029 } 1030 } else { 1031 if (blend_type) { 1032 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1033 for (int col = 0; col < pixel_count; col++) { 1034 uint8_t gray = pPalette[*src_scan]; 1035 src_scan++; 1036 if (!clip_scan || clip_scan[col] == 255) { 1037 *dest_scan++ = gray; 1038 *dest_alpha_scan++ = 255; 1039 continue; 1040 } 1041 int src_alpha = clip_scan[col]; 1042 if (src_alpha == 0) { 1043 dest_scan++; 1044 dest_alpha_scan++; 1045 continue; 1046 } 1047 int back_alpha = *dest_alpha_scan; 1048 uint8_t dest_alpha = 1049 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1050 *dest_alpha_scan++ = dest_alpha; 1051 int alpha_ratio = src_alpha * 255 / dest_alpha; 1052 if (bNonseparableBlend) 1053 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 1054 else 1055 gray = Blend(blend_type, *dest_scan, gray); 1056 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 1057 dest_scan++; 1058 } 1059 return; 1060 } 1061 for (int col = 0; col < pixel_count; col++) { 1062 uint8_t gray = pPalette[*src_scan]; 1063 src_scan++; 1064 if (!clip_scan || clip_scan[col] == 255) { 1065 *dest_scan++ = gray; 1066 *dest_alpha_scan++ = 255; 1067 continue; 1068 } 1069 int src_alpha = clip_scan[col]; 1070 if (src_alpha == 0) { 1071 dest_scan++; 1072 dest_alpha_scan++; 1073 continue; 1074 } 1075 int back_alpha = *dest_alpha_scan; 1076 uint8_t dest_alpha = 1077 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1078 *dest_alpha_scan++ = dest_alpha; 1079 int alpha_ratio = src_alpha * 255 / dest_alpha; 1080 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 1081 dest_scan++; 1082 } 1083 } 1084 } 1085 1086 void CompositeRow_1bppPal2Gray(uint8_t* dest_scan, 1087 const uint8_t* src_scan, 1088 int src_left, 1089 const uint8_t* pPalette, 1090 int pixel_count, 1091 int blend_type, 1092 const uint8_t* clip_scan) { 1093 int reset_gray = pPalette[0]; 1094 int set_gray = pPalette[1]; 1095 if (blend_type) { 1096 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1097 for (int col = 0; col < pixel_count; col++) { 1098 uint8_t gray = 1099 (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) 1100 ? set_gray 1101 : reset_gray; 1102 if (bNonseparableBlend) 1103 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 1104 else 1105 gray = Blend(blend_type, *dest_scan, gray); 1106 if (clip_scan && clip_scan[col] < 255) { 1107 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 1108 } else { 1109 *dest_scan = gray; 1110 } 1111 dest_scan++; 1112 } 1113 return; 1114 } 1115 for (int col = 0; col < pixel_count; col++) { 1116 uint8_t gray = 1117 (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) 1118 ? set_gray 1119 : reset_gray; 1120 if (clip_scan && clip_scan[col] < 255) { 1121 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); 1122 } else { 1123 *dest_scan = gray; 1124 } 1125 dest_scan++; 1126 } 1127 } 1128 1129 void CompositeRow_1bppPal2Graya(uint8_t* dest_scan, 1130 const uint8_t* src_scan, 1131 int src_left, 1132 const uint8_t* pPalette, 1133 int pixel_count, 1134 int blend_type, 1135 const uint8_t* clip_scan, 1136 uint8_t* dest_alpha_scan) { 1137 int reset_gray = pPalette[0]; 1138 int set_gray = pPalette[1]; 1139 if (blend_type) { 1140 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 1141 for (int col = 0; col < pixel_count; col++) { 1142 uint8_t gray = 1143 (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) 1144 ? set_gray 1145 : reset_gray; 1146 if (!clip_scan || clip_scan[col] == 255) { 1147 *dest_scan++ = gray; 1148 *dest_alpha_scan++ = 255; 1149 continue; 1150 } 1151 int src_alpha = clip_scan[col]; 1152 if (src_alpha == 0) { 1153 dest_scan++; 1154 dest_alpha_scan++; 1155 continue; 1156 } 1157 int back_alpha = *dest_alpha_scan; 1158 uint8_t dest_alpha = 1159 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1160 *dest_alpha_scan++ = dest_alpha; 1161 int alpha_ratio = src_alpha * 255 / dest_alpha; 1162 if (bNonseparableBlend) 1163 gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; 1164 else 1165 gray = Blend(blend_type, *dest_scan, gray); 1166 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 1167 dest_scan++; 1168 } 1169 return; 1170 } 1171 for (int col = 0; col < pixel_count; col++) { 1172 uint8_t gray = 1173 (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) 1174 ? set_gray 1175 : reset_gray; 1176 if (!clip_scan || clip_scan[col] == 255) { 1177 *dest_scan++ = gray; 1178 *dest_alpha_scan++ = 255; 1179 continue; 1180 } 1181 int src_alpha = clip_scan[col]; 1182 if (src_alpha == 0) { 1183 dest_scan++; 1184 dest_alpha_scan++; 1185 continue; 1186 } 1187 int back_alpha = *dest_alpha_scan; 1188 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1189 *dest_alpha_scan++ = dest_alpha; 1190 int alpha_ratio = src_alpha * 255 / dest_alpha; 1191 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); 1192 dest_scan++; 1193 } 1194 } 1195 1196 void CompositeRow_8bppRgb2Rgb_NoBlend(uint8_t* dest_scan, 1197 const uint8_t* src_scan, 1198 uint32_t* pPalette, 1199 int pixel_count, 1200 int DestBpp, 1201 const uint8_t* clip_scan, 1202 const uint8_t* src_alpha_scan) { 1203 if (src_alpha_scan) { 1204 int dest_gap = DestBpp - 3; 1205 FX_ARGB argb = 0; 1206 for (int col = 0; col < pixel_count; col++) { 1207 argb = pPalette[*src_scan]; 1208 int src_r = FXARGB_R(argb); 1209 int src_g = FXARGB_G(argb); 1210 int src_b = FXARGB_B(argb); 1211 src_scan++; 1212 uint8_t src_alpha = 0; 1213 if (clip_scan) { 1214 src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; 1215 } else { 1216 src_alpha = *src_alpha_scan++; 1217 } 1218 if (src_alpha == 255) { 1219 *dest_scan++ = src_b; 1220 *dest_scan++ = src_g; 1221 *dest_scan++ = src_r; 1222 dest_scan += dest_gap; 1223 continue; 1224 } 1225 if (src_alpha == 0) { 1226 dest_scan += DestBpp; 1227 continue; 1228 } 1229 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); 1230 dest_scan++; 1231 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); 1232 dest_scan++; 1233 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); 1234 dest_scan++; 1235 dest_scan += dest_gap; 1236 } 1237 } else { 1238 FX_ARGB argb = 0; 1239 for (int col = 0; col < pixel_count; col++) { 1240 argb = pPalette[*src_scan]; 1241 int src_r = FXARGB_R(argb); 1242 int src_g = FXARGB_G(argb); 1243 int src_b = FXARGB_B(argb); 1244 if (clip_scan && clip_scan[col] < 255) { 1245 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]); 1246 dest_scan++; 1247 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]); 1248 dest_scan++; 1249 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]); 1250 dest_scan++; 1251 } else { 1252 *dest_scan++ = src_b; 1253 *dest_scan++ = src_g; 1254 *dest_scan++ = src_r; 1255 } 1256 if (DestBpp == 4) { 1257 dest_scan++; 1258 } 1259 src_scan++; 1260 } 1261 } 1262 } 1263 1264 void CompositeRow_1bppRgb2Rgb_NoBlend(uint8_t* dest_scan, 1265 const uint8_t* src_scan, 1266 int src_left, 1267 uint32_t* pPalette, 1268 int pixel_count, 1269 int DestBpp, 1270 const uint8_t* clip_scan) { 1271 int reset_r, reset_g, reset_b; 1272 int set_r, set_g, set_b; 1273 reset_r = FXARGB_R(pPalette[0]); 1274 reset_g = FXARGB_G(pPalette[0]); 1275 reset_b = FXARGB_B(pPalette[0]); 1276 set_r = FXARGB_R(pPalette[1]); 1277 set_g = FXARGB_G(pPalette[1]); 1278 set_b = FXARGB_B(pPalette[1]); 1279 for (int col = 0; col < pixel_count; col++) { 1280 int src_r, src_g, src_b; 1281 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 1282 src_r = set_r; 1283 src_g = set_g; 1284 src_b = set_b; 1285 } else { 1286 src_r = reset_r; 1287 src_g = reset_g; 1288 src_b = reset_b; 1289 } 1290 if (clip_scan && clip_scan[col] < 255) { 1291 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]); 1292 dest_scan++; 1293 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]); 1294 dest_scan++; 1295 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]); 1296 dest_scan++; 1297 } else { 1298 *dest_scan++ = src_b; 1299 *dest_scan++ = src_g; 1300 *dest_scan++ = src_r; 1301 } 1302 if (DestBpp == 4) { 1303 dest_scan++; 1304 } 1305 } 1306 } 1307 1308 void CompositeRow_8bppRgb2Argb_NoBlend(uint8_t* dest_scan, 1309 const uint8_t* src_scan, 1310 int width, 1311 uint32_t* pPalette, 1312 const uint8_t* clip_scan, 1313 const uint8_t* src_alpha_scan) { 1314 if (src_alpha_scan) { 1315 for (int col = 0; col < width; col++) { 1316 FX_ARGB argb = pPalette[*src_scan]; 1317 src_scan++; 1318 int src_r = FXARGB_R(argb); 1319 int src_g = FXARGB_G(argb); 1320 int src_b = FXARGB_B(argb); 1321 uint8_t back_alpha = dest_scan[3]; 1322 if (back_alpha == 0) { 1323 if (clip_scan) { 1324 int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255; 1325 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 1326 } else { 1327 FXARGB_SETDIB(dest_scan, 1328 FXARGB_MAKE(*src_alpha_scan, src_r, src_g, src_b)); 1329 } 1330 dest_scan += 4; 1331 src_alpha_scan++; 1332 continue; 1333 } 1334 uint8_t src_alpha; 1335 if (clip_scan) { 1336 src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255; 1337 } else { 1338 src_alpha = *src_alpha_scan++; 1339 } 1340 if (src_alpha == 0) { 1341 dest_scan += 4; 1342 continue; 1343 } 1344 uint8_t dest_alpha = 1345 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1346 dest_scan[3] = dest_alpha; 1347 int alpha_ratio = src_alpha * 255 / dest_alpha; 1348 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 1349 dest_scan++; 1350 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 1351 dest_scan++; 1352 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 1353 dest_scan++; 1354 dest_scan++; 1355 } 1356 } else { 1357 for (int col = 0; col < width; col++) { 1358 FX_ARGB argb = pPalette[*src_scan]; 1359 int src_r = FXARGB_R(argb); 1360 int src_g = FXARGB_G(argb); 1361 int src_b = FXARGB_B(argb); 1362 if (!clip_scan || clip_scan[col] == 255) { 1363 *dest_scan++ = src_b; 1364 *dest_scan++ = src_g; 1365 *dest_scan++ = src_r; 1366 *dest_scan++ = 255; 1367 src_scan++; 1368 continue; 1369 } 1370 int src_alpha = clip_scan[col]; 1371 if (src_alpha == 0) { 1372 dest_scan += 4; 1373 src_scan++; 1374 continue; 1375 } 1376 int back_alpha = dest_scan[3]; 1377 uint8_t dest_alpha = 1378 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1379 dest_scan[3] = dest_alpha; 1380 int alpha_ratio = src_alpha * 255 / dest_alpha; 1381 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 1382 dest_scan++; 1383 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 1384 dest_scan++; 1385 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 1386 dest_scan++; 1387 dest_scan++; 1388 src_scan++; 1389 } 1390 } 1391 } 1392 1393 void CompositeRow_1bppRgb2Argb_NoBlend(uint8_t* dest_scan, 1394 const uint8_t* src_scan, 1395 int src_left, 1396 int width, 1397 uint32_t* pPalette, 1398 const uint8_t* clip_scan) { 1399 int reset_r, reset_g, reset_b; 1400 int set_r, set_g, set_b; 1401 reset_r = FXARGB_R(pPalette[0]); 1402 reset_g = FXARGB_G(pPalette[0]); 1403 reset_b = FXARGB_B(pPalette[0]); 1404 set_r = FXARGB_R(pPalette[1]); 1405 set_g = FXARGB_G(pPalette[1]); 1406 set_b = FXARGB_B(pPalette[1]); 1407 for (int col = 0; col < width; col++) { 1408 int src_r, src_g, src_b; 1409 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 1410 src_r = set_r; 1411 src_g = set_g; 1412 src_b = set_b; 1413 } else { 1414 src_r = reset_r; 1415 src_g = reset_g; 1416 src_b = reset_b; 1417 } 1418 if (!clip_scan || clip_scan[col] == 255) { 1419 *dest_scan++ = src_b; 1420 *dest_scan++ = src_g; 1421 *dest_scan++ = src_r; 1422 *dest_scan++ = 255; 1423 continue; 1424 } 1425 int src_alpha = clip_scan[col]; 1426 if (src_alpha == 0) { 1427 dest_scan += 4; 1428 continue; 1429 } 1430 int back_alpha = dest_scan[3]; 1431 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1432 dest_scan[3] = dest_alpha; 1433 int alpha_ratio = src_alpha * 255 / dest_alpha; 1434 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 1435 dest_scan++; 1436 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 1437 dest_scan++; 1438 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 1439 dest_scan++; 1440 dest_scan++; 1441 } 1442 } 1443 1444 void CompositeRow_1bppRgb2Rgba_NoBlend(uint8_t* dest_scan, 1445 const uint8_t* src_scan, 1446 int src_left, 1447 int width, 1448 uint32_t* pPalette, 1449 const uint8_t* clip_scan, 1450 uint8_t* dest_alpha_scan) { 1451 int reset_r, reset_g, reset_b; 1452 int set_r, set_g, set_b; 1453 reset_r = FXARGB_R(pPalette[0]); 1454 reset_g = FXARGB_G(pPalette[0]); 1455 reset_b = FXARGB_B(pPalette[0]); 1456 set_r = FXARGB_R(pPalette[1]); 1457 set_g = FXARGB_G(pPalette[1]); 1458 set_b = FXARGB_B(pPalette[1]); 1459 for (int col = 0; col < width; col++) { 1460 int src_r, src_g, src_b; 1461 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 1462 src_r = set_r; 1463 src_g = set_g; 1464 src_b = set_b; 1465 } else { 1466 src_r = reset_r; 1467 src_g = reset_g; 1468 src_b = reset_b; 1469 } 1470 if (!clip_scan || clip_scan[col] == 255) { 1471 *dest_scan++ = src_b; 1472 *dest_scan++ = src_g; 1473 *dest_scan++ = src_r; 1474 *dest_alpha_scan++ = 255; 1475 continue; 1476 } 1477 int src_alpha = clip_scan[col]; 1478 if (src_alpha == 0) { 1479 dest_scan += 3; 1480 dest_alpha_scan++; 1481 continue; 1482 } 1483 int back_alpha = *dest_alpha_scan; 1484 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1485 *dest_alpha_scan++ = dest_alpha; 1486 int alpha_ratio = src_alpha * 255 / dest_alpha; 1487 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 1488 dest_scan++; 1489 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 1490 dest_scan++; 1491 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 1492 dest_scan++; 1493 } 1494 } 1495 1496 void CompositeRow_ByteMask2Argb(uint8_t* dest_scan, 1497 const uint8_t* src_scan, 1498 int mask_alpha, 1499 int src_r, 1500 int src_g, 1501 int src_b, 1502 int pixel_count, 1503 int blend_type, 1504 const uint8_t* clip_scan) { 1505 for (int col = 0; col < pixel_count; col++) { 1506 int src_alpha; 1507 if (clip_scan) { 1508 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 1509 } else { 1510 src_alpha = mask_alpha * src_scan[col] / 255; 1511 } 1512 uint8_t back_alpha = dest_scan[3]; 1513 if (back_alpha == 0) { 1514 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 1515 dest_scan += 4; 1516 continue; 1517 } 1518 if (src_alpha == 0) { 1519 dest_scan += 4; 1520 continue; 1521 } 1522 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1523 dest_scan[3] = dest_alpha; 1524 int alpha_ratio = src_alpha * 255 / dest_alpha; 1525 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 1526 int blended_colors[3]; 1527 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 1528 static_cast<uint8_t>(src_g), 1529 static_cast<uint8_t>(src_r)}; 1530 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 1531 *dest_scan = 1532 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); 1533 dest_scan++; 1534 *dest_scan = 1535 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); 1536 dest_scan++; 1537 *dest_scan = 1538 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); 1539 } else if (blend_type) { 1540 int blended = Blend(blend_type, *dest_scan, src_b); 1541 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 1542 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1543 dest_scan++; 1544 blended = Blend(blend_type, *dest_scan, src_g); 1545 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 1546 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1547 dest_scan++; 1548 blended = Blend(blend_type, *dest_scan, src_r); 1549 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 1550 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1551 } else { 1552 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 1553 dest_scan++; 1554 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 1555 dest_scan++; 1556 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 1557 } 1558 dest_scan += 2; 1559 } 1560 } 1561 1562 void CompositeRow_ByteMask2Rgba(uint8_t* dest_scan, 1563 const uint8_t* src_scan, 1564 int mask_alpha, 1565 int src_r, 1566 int src_g, 1567 int src_b, 1568 int pixel_count, 1569 int blend_type, 1570 const uint8_t* clip_scan, 1571 uint8_t* dest_alpha_scan) { 1572 for (int col = 0; col < pixel_count; col++) { 1573 int src_alpha; 1574 if (clip_scan) { 1575 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 1576 } else { 1577 src_alpha = mask_alpha * src_scan[col] / 255; 1578 } 1579 uint8_t back_alpha = *dest_alpha_scan; 1580 if (back_alpha == 0) { 1581 *dest_scan++ = src_b; 1582 *dest_scan++ = src_g; 1583 *dest_scan++ = src_r; 1584 *dest_alpha_scan++ = src_alpha; 1585 continue; 1586 } 1587 if (src_alpha == 0) { 1588 dest_scan += 3; 1589 dest_alpha_scan++; 1590 continue; 1591 } 1592 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1593 *dest_alpha_scan++ = dest_alpha; 1594 int alpha_ratio = src_alpha * 255 / dest_alpha; 1595 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 1596 int blended_colors[3]; 1597 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 1598 static_cast<uint8_t>(src_g), 1599 static_cast<uint8_t>(src_r)}; 1600 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 1601 *dest_scan = 1602 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); 1603 dest_scan++; 1604 *dest_scan = 1605 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); 1606 dest_scan++; 1607 *dest_scan = 1608 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); 1609 dest_scan++; 1610 } else if (blend_type) { 1611 int blended = Blend(blend_type, *dest_scan, src_b); 1612 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 1613 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1614 dest_scan++; 1615 blended = Blend(blend_type, *dest_scan, src_g); 1616 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 1617 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1618 dest_scan++; 1619 blended = Blend(blend_type, *dest_scan, src_r); 1620 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 1621 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1622 dest_scan++; 1623 } else { 1624 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 1625 dest_scan++; 1626 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 1627 dest_scan++; 1628 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 1629 dest_scan++; 1630 } 1631 } 1632 } 1633 1634 void CompositeRow_ByteMask2Rgb(uint8_t* dest_scan, 1635 const uint8_t* src_scan, 1636 int mask_alpha, 1637 int src_r, 1638 int src_g, 1639 int src_b, 1640 int pixel_count, 1641 int blend_type, 1642 int Bpp, 1643 const uint8_t* clip_scan) { 1644 for (int col = 0; col < pixel_count; col++) { 1645 int src_alpha; 1646 if (clip_scan) { 1647 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 1648 } else { 1649 src_alpha = mask_alpha * src_scan[col] / 255; 1650 } 1651 if (src_alpha == 0) { 1652 dest_scan += Bpp; 1653 continue; 1654 } 1655 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 1656 int blended_colors[3]; 1657 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 1658 static_cast<uint8_t>(src_g), 1659 static_cast<uint8_t>(src_r)}; 1660 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 1661 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha); 1662 dest_scan++; 1663 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha); 1664 dest_scan++; 1665 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha); 1666 } else if (blend_type) { 1667 int blended = Blend(blend_type, *dest_scan, src_b); 1668 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 1669 dest_scan++; 1670 blended = Blend(blend_type, *dest_scan, src_g); 1671 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 1672 dest_scan++; 1673 blended = Blend(blend_type, *dest_scan, src_r); 1674 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 1675 } else { 1676 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); 1677 dest_scan++; 1678 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); 1679 dest_scan++; 1680 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); 1681 } 1682 dest_scan += Bpp - 2; 1683 } 1684 } 1685 1686 void CompositeRow_ByteMask2Mask(uint8_t* dest_scan, 1687 const uint8_t* src_scan, 1688 int mask_alpha, 1689 int pixel_count, 1690 const uint8_t* clip_scan) { 1691 for (int col = 0; col < pixel_count; col++) { 1692 int src_alpha; 1693 if (clip_scan) { 1694 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 1695 } else { 1696 src_alpha = mask_alpha * src_scan[col] / 255; 1697 } 1698 uint8_t back_alpha = *dest_scan; 1699 if (!back_alpha) { 1700 *dest_scan = src_alpha; 1701 } else if (src_alpha) { 1702 *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1703 } 1704 dest_scan++; 1705 } 1706 } 1707 1708 void CompositeRow_ByteMask2Gray(uint8_t* dest_scan, 1709 const uint8_t* src_scan, 1710 int mask_alpha, 1711 int src_gray, 1712 int pixel_count, 1713 const uint8_t* clip_scan) { 1714 for (int col = 0; col < pixel_count; col++) { 1715 int src_alpha; 1716 if (clip_scan) { 1717 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 1718 } else { 1719 src_alpha = mask_alpha * src_scan[col] / 255; 1720 } 1721 if (src_alpha) { 1722 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha); 1723 } 1724 dest_scan++; 1725 } 1726 } 1727 1728 void CompositeRow_ByteMask2Graya(uint8_t* dest_scan, 1729 const uint8_t* src_scan, 1730 int mask_alpha, 1731 int src_gray, 1732 int pixel_count, 1733 const uint8_t* clip_scan, 1734 uint8_t* dest_alpha_scan) { 1735 for (int col = 0; col < pixel_count; col++) { 1736 int src_alpha; 1737 if (clip_scan) { 1738 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 1739 } else { 1740 src_alpha = mask_alpha * src_scan[col] / 255; 1741 } 1742 uint8_t back_alpha = *dest_alpha_scan; 1743 if (back_alpha == 0) { 1744 *dest_scan++ = src_gray; 1745 *dest_alpha_scan++ = src_alpha; 1746 continue; 1747 } 1748 if (src_alpha == 0) { 1749 dest_scan++; 1750 dest_alpha_scan++; 1751 continue; 1752 } 1753 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1754 *dest_alpha_scan++ = dest_alpha; 1755 int alpha_ratio = src_alpha * 255 / dest_alpha; 1756 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio); 1757 dest_scan++; 1758 } 1759 } 1760 1761 void CompositeRow_BitMask2Argb(uint8_t* dest_scan, 1762 const uint8_t* src_scan, 1763 int mask_alpha, 1764 int src_r, 1765 int src_g, 1766 int src_b, 1767 int src_left, 1768 int pixel_count, 1769 int blend_type, 1770 const uint8_t* clip_scan) { 1771 if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { 1772 FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b); 1773 for (int col = 0; col < pixel_count; col++) { 1774 if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { 1775 FXARGB_SETDIB(dest_scan, argb); 1776 } 1777 dest_scan += 4; 1778 } 1779 return; 1780 } 1781 for (int col = 0; col < pixel_count; col++) { 1782 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 1783 dest_scan += 4; 1784 continue; 1785 } 1786 int src_alpha; 1787 if (clip_scan) { 1788 src_alpha = mask_alpha * clip_scan[col] / 255; 1789 } else { 1790 src_alpha = mask_alpha; 1791 } 1792 uint8_t back_alpha = dest_scan[3]; 1793 if (back_alpha == 0) { 1794 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 1795 dest_scan += 4; 1796 continue; 1797 } 1798 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1799 dest_scan[3] = dest_alpha; 1800 int alpha_ratio = src_alpha * 255 / dest_alpha; 1801 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 1802 int blended_colors[3]; 1803 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 1804 static_cast<uint8_t>(src_g), 1805 static_cast<uint8_t>(src_r)}; 1806 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 1807 *dest_scan = 1808 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); 1809 dest_scan++; 1810 *dest_scan = 1811 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); 1812 dest_scan++; 1813 *dest_scan = 1814 FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); 1815 } else if (blend_type) { 1816 int blended = Blend(blend_type, *dest_scan, src_b); 1817 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 1818 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1819 dest_scan++; 1820 blended = Blend(blend_type, *dest_scan, src_g); 1821 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 1822 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1823 dest_scan++; 1824 blended = Blend(blend_type, *dest_scan, src_r); 1825 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 1826 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); 1827 } else { 1828 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); 1829 dest_scan++; 1830 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); 1831 dest_scan++; 1832 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); 1833 } 1834 dest_scan += 2; 1835 } 1836 } 1837 1838 void CompositeRow_BitMask2Rgb(uint8_t* dest_scan, 1839 const uint8_t* src_scan, 1840 int mask_alpha, 1841 int src_r, 1842 int src_g, 1843 int src_b, 1844 int src_left, 1845 int pixel_count, 1846 int blend_type, 1847 int Bpp, 1848 const uint8_t* clip_scan) { 1849 if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { 1850 for (int col = 0; col < pixel_count; col++) { 1851 if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { 1852 dest_scan[2] = src_r; 1853 dest_scan[1] = src_g; 1854 dest_scan[0] = src_b; 1855 } 1856 dest_scan += Bpp; 1857 } 1858 return; 1859 } 1860 for (int col = 0; col < pixel_count; col++) { 1861 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 1862 dest_scan += Bpp; 1863 continue; 1864 } 1865 int src_alpha; 1866 if (clip_scan) { 1867 src_alpha = mask_alpha * clip_scan[col] / 255; 1868 } else { 1869 src_alpha = mask_alpha; 1870 } 1871 if (src_alpha == 0) { 1872 dest_scan += Bpp; 1873 continue; 1874 } 1875 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 1876 int blended_colors[3]; 1877 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 1878 static_cast<uint8_t>(src_g), 1879 static_cast<uint8_t>(src_r)}; 1880 RGB_Blend(blend_type, scan, dest_scan, blended_colors); 1881 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha); 1882 dest_scan++; 1883 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha); 1884 dest_scan++; 1885 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha); 1886 } else if (blend_type) { 1887 int blended = Blend(blend_type, *dest_scan, src_b); 1888 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 1889 dest_scan++; 1890 blended = Blend(blend_type, *dest_scan, src_g); 1891 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 1892 dest_scan++; 1893 blended = Blend(blend_type, *dest_scan, src_r); 1894 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); 1895 } else { 1896 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); 1897 dest_scan++; 1898 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); 1899 dest_scan++; 1900 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); 1901 } 1902 dest_scan += Bpp - 2; 1903 } 1904 } 1905 1906 void CompositeRow_BitMask2Mask(uint8_t* dest_scan, 1907 const uint8_t* src_scan, 1908 int mask_alpha, 1909 int src_left, 1910 int pixel_count, 1911 const uint8_t* clip_scan) { 1912 for (int col = 0; col < pixel_count; col++) { 1913 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 1914 dest_scan++; 1915 continue; 1916 } 1917 int src_alpha; 1918 if (clip_scan) { 1919 src_alpha = mask_alpha * clip_scan[col] / 255; 1920 } else { 1921 src_alpha = mask_alpha; 1922 } 1923 uint8_t back_alpha = *dest_scan; 1924 if (!back_alpha) { 1925 *dest_scan = src_alpha; 1926 } else if (src_alpha) { 1927 *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1928 } 1929 dest_scan++; 1930 } 1931 } 1932 1933 void CompositeRow_BitMask2Gray(uint8_t* dest_scan, 1934 const uint8_t* src_scan, 1935 int mask_alpha, 1936 int src_gray, 1937 int src_left, 1938 int pixel_count, 1939 const uint8_t* clip_scan) { 1940 for (int col = 0; col < pixel_count; col++) { 1941 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 1942 dest_scan++; 1943 continue; 1944 } 1945 int src_alpha; 1946 if (clip_scan) { 1947 src_alpha = mask_alpha * clip_scan[col] / 255; 1948 } else { 1949 src_alpha = mask_alpha; 1950 } 1951 if (src_alpha) { 1952 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha); 1953 } 1954 dest_scan++; 1955 } 1956 } 1957 1958 void CompositeRow_BitMask2Graya(uint8_t* dest_scan, 1959 const uint8_t* src_scan, 1960 int mask_alpha, 1961 int src_gray, 1962 int src_left, 1963 int pixel_count, 1964 const uint8_t* clip_scan, 1965 uint8_t* dest_alpha_scan) { 1966 for (int col = 0; col < pixel_count; col++) { 1967 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 1968 dest_scan++; 1969 dest_alpha_scan++; 1970 continue; 1971 } 1972 int src_alpha; 1973 if (clip_scan) { 1974 src_alpha = mask_alpha * clip_scan[col] / 255; 1975 } else { 1976 src_alpha = mask_alpha; 1977 } 1978 uint8_t back_alpha = *dest_alpha_scan; 1979 if (back_alpha == 0) { 1980 *dest_scan++ = src_gray; 1981 *dest_alpha_scan++ = src_alpha; 1982 continue; 1983 } 1984 if (src_alpha == 0) { 1985 dest_scan++; 1986 dest_alpha_scan++; 1987 continue; 1988 } 1989 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 1990 *dest_alpha_scan++ = dest_alpha; 1991 int alpha_ratio = src_alpha * 255 / dest_alpha; 1992 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio); 1993 dest_scan++; 1994 } 1995 } 1996 1997 void CompositeRow_Argb2Argb_RgbByteOrder(uint8_t* dest_scan, 1998 const uint8_t* src_scan, 1999 int pixel_count, 2000 int blend_type, 2001 const uint8_t* clip_scan) { 2002 int blended_colors[3]; 2003 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2004 for (int col = 0; col < pixel_count; col++) { 2005 uint8_t back_alpha = dest_scan[3]; 2006 if (back_alpha == 0) { 2007 if (clip_scan) { 2008 int src_alpha = clip_scan[col] * src_scan[3] / 255; 2009 dest_scan[3] = src_alpha; 2010 dest_scan[0] = src_scan[2]; 2011 dest_scan[1] = src_scan[1]; 2012 dest_scan[2] = src_scan[0]; 2013 } else { 2014 FXARGB_RGBORDERCOPY(dest_scan, src_scan); 2015 } 2016 dest_scan += 4; 2017 src_scan += 4; 2018 continue; 2019 } 2020 uint8_t src_alpha; 2021 if (clip_scan) { 2022 src_alpha = clip_scan[col] * src_scan[3] / 255; 2023 } else { 2024 src_alpha = src_scan[3]; 2025 } 2026 if (src_alpha == 0) { 2027 dest_scan += 4; 2028 src_scan += 4; 2029 continue; 2030 } 2031 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2032 dest_scan[3] = dest_alpha; 2033 int alpha_ratio = src_alpha * 255 / dest_alpha; 2034 if (bNonseparableBlend) { 2035 uint8_t dest_scan_o[3]; 2036 dest_scan_o[0] = dest_scan[2]; 2037 dest_scan_o[1] = dest_scan[1]; 2038 dest_scan_o[2] = dest_scan[0]; 2039 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 2040 } 2041 for (int color = 0; color < 3; color++) { 2042 int index = 2 - color; 2043 if (blend_type) { 2044 int blended = bNonseparableBlend 2045 ? blended_colors[color] 2046 : Blend(blend_type, dest_scan[index], *src_scan); 2047 blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); 2048 dest_scan[index] = 2049 FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio); 2050 } else { 2051 dest_scan[index] = 2052 FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio); 2053 } 2054 src_scan++; 2055 } 2056 dest_scan += 4; 2057 src_scan++; 2058 } 2059 } 2060 2061 void CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan, 2062 const uint8_t* src_scan, 2063 int width, 2064 int blend_type, 2065 int src_Bpp) { 2066 int blended_colors[3]; 2067 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2068 int src_gap = src_Bpp - 3; 2069 for (int col = 0; col < width; col++) { 2070 uint8_t back_alpha = dest_scan[3]; 2071 if (back_alpha == 0) { 2072 if (src_Bpp == 4) { 2073 FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); 2074 } else { 2075 FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], 2076 src_scan[1], src_scan[0])); 2077 } 2078 dest_scan += 4; 2079 src_scan += src_Bpp; 2080 continue; 2081 } 2082 dest_scan[3] = 0xff; 2083 if (bNonseparableBlend) { 2084 uint8_t dest_scan_o[3]; 2085 dest_scan_o[0] = dest_scan[2]; 2086 dest_scan_o[1] = dest_scan[1]; 2087 dest_scan_o[2] = dest_scan[0]; 2088 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 2089 } 2090 for (int color = 0; color < 3; color++) { 2091 int index = 2 - color; 2092 int src_color = *src_scan; 2093 int blended = bNonseparableBlend 2094 ? blended_colors[color] 2095 : Blend(blend_type, dest_scan[index], src_color); 2096 dest_scan[index] = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 2097 src_scan++; 2098 } 2099 dest_scan += 4; 2100 src_scan += src_gap; 2101 } 2102 } 2103 2104 void CompositeRow_Argb2Rgb_Blend_RgbByteOrder(uint8_t* dest_scan, 2105 const uint8_t* src_scan, 2106 int width, 2107 int blend_type, 2108 int dest_Bpp, 2109 const uint8_t* clip_scan) { 2110 int blended_colors[3]; 2111 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2112 for (int col = 0; col < width; col++) { 2113 uint8_t src_alpha; 2114 if (clip_scan) { 2115 src_alpha = src_scan[3] * (*clip_scan++) / 255; 2116 } else { 2117 src_alpha = src_scan[3]; 2118 } 2119 if (src_alpha == 0) { 2120 dest_scan += dest_Bpp; 2121 src_scan += 4; 2122 continue; 2123 } 2124 if (bNonseparableBlend) { 2125 uint8_t dest_scan_o[3]; 2126 dest_scan_o[0] = dest_scan[2]; 2127 dest_scan_o[1] = dest_scan[1]; 2128 dest_scan_o[2] = dest_scan[0]; 2129 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 2130 } 2131 for (int color = 0; color < 3; color++) { 2132 int index = 2 - color; 2133 int back_color = dest_scan[index]; 2134 int blended = bNonseparableBlend 2135 ? blended_colors[color] 2136 : Blend(blend_type, back_color, *src_scan); 2137 dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 2138 src_scan++; 2139 } 2140 dest_scan += dest_Bpp; 2141 src_scan++; 2142 } 2143 } 2144 2145 void CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan, 2146 const uint8_t* src_scan, 2147 int width, 2148 int src_Bpp) { 2149 for (int col = 0; col < width; col++) { 2150 if (src_Bpp == 4) { 2151 FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); 2152 } else { 2153 FXARGB_SETRGBORDERDIB( 2154 dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0])); 2155 } 2156 dest_scan += 4; 2157 src_scan += src_Bpp; 2158 } 2159 } 2160 2161 void CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan, 2162 const uint8_t* src_scan, 2163 int width, 2164 int blend_type, 2165 int dest_Bpp, 2166 int src_Bpp) { 2167 int blended_colors[3]; 2168 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2169 int src_gap = src_Bpp - 3; 2170 for (int col = 0; col < width; col++) { 2171 if (bNonseparableBlend) { 2172 uint8_t dest_scan_o[3]; 2173 dest_scan_o[0] = dest_scan[2]; 2174 dest_scan_o[1] = dest_scan[1]; 2175 dest_scan_o[2] = dest_scan[0]; 2176 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 2177 } 2178 for (int color = 0; color < 3; color++) { 2179 int index = 2 - color; 2180 int back_color = dest_scan[index]; 2181 int src_color = *src_scan; 2182 int blended = bNonseparableBlend 2183 ? blended_colors[color] 2184 : Blend(blend_type, back_color, src_color); 2185 dest_scan[index] = blended; 2186 src_scan++; 2187 } 2188 dest_scan += dest_Bpp; 2189 src_scan += src_gap; 2190 } 2191 } 2192 2193 void CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 2194 const uint8_t* src_scan, 2195 int width, 2196 int dest_Bpp, 2197 const uint8_t* clip_scan) { 2198 for (int col = 0; col < width; col++) { 2199 uint8_t src_alpha; 2200 if (clip_scan) { 2201 src_alpha = src_scan[3] * (*clip_scan++) / 255; 2202 } else { 2203 src_alpha = src_scan[3]; 2204 } 2205 if (src_alpha == 255) { 2206 dest_scan[2] = *src_scan++; 2207 dest_scan[1] = *src_scan++; 2208 dest_scan[0] = *src_scan++; 2209 dest_scan += dest_Bpp; 2210 src_scan++; 2211 continue; 2212 } 2213 if (src_alpha == 0) { 2214 dest_scan += dest_Bpp; 2215 src_scan += 4; 2216 continue; 2217 } 2218 for (int color = 0; color < 3; color++) { 2219 int index = 2 - color; 2220 dest_scan[index] = 2221 FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, src_alpha); 2222 src_scan++; 2223 } 2224 dest_scan += dest_Bpp; 2225 src_scan++; 2226 } 2227 } 2228 2229 void CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan, 2230 const uint8_t* src_scan, 2231 int width, 2232 int dest_Bpp, 2233 int src_Bpp) { 2234 for (int col = 0; col < width; col++) { 2235 dest_scan[2] = src_scan[0]; 2236 dest_scan[1] = src_scan[1]; 2237 dest_scan[0] = src_scan[2]; 2238 dest_scan += dest_Bpp; 2239 src_scan += src_Bpp; 2240 } 2241 } 2242 2243 void CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan, 2244 const uint8_t* src_scan, 2245 int width, 2246 int blend_type, 2247 int src_Bpp, 2248 const uint8_t* clip_scan) { 2249 int blended_colors[3]; 2250 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2251 int src_gap = src_Bpp - 3; 2252 for (int col = 0; col < width; col++) { 2253 int src_alpha = *clip_scan++; 2254 uint8_t back_alpha = dest_scan[3]; 2255 if (back_alpha == 0) { 2256 dest_scan[2] = *src_scan++; 2257 dest_scan[1] = *src_scan++; 2258 dest_scan[0] = *src_scan++; 2259 src_scan += src_gap; 2260 dest_scan += 4; 2261 continue; 2262 } 2263 if (src_alpha == 0) { 2264 dest_scan += 4; 2265 src_scan += src_Bpp; 2266 continue; 2267 } 2268 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2269 dest_scan[3] = dest_alpha; 2270 int alpha_ratio = src_alpha * 255 / dest_alpha; 2271 if (bNonseparableBlend) { 2272 uint8_t dest_scan_o[3]; 2273 dest_scan_o[0] = dest_scan[2]; 2274 dest_scan_o[1] = dest_scan[1]; 2275 dest_scan_o[2] = dest_scan[0]; 2276 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 2277 } 2278 for (int color = 0; color < 3; color++) { 2279 int index = 2 - color; 2280 int src_color = *src_scan; 2281 int blended = bNonseparableBlend 2282 ? blended_colors[color] 2283 : Blend(blend_type, dest_scan[index], src_color); 2284 blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); 2285 dest_scan[index] = 2286 FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio); 2287 src_scan++; 2288 } 2289 dest_scan += 4; 2290 src_scan += src_gap; 2291 } 2292 } 2293 2294 void CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan, 2295 const uint8_t* src_scan, 2296 int width, 2297 int blend_type, 2298 int dest_Bpp, 2299 int src_Bpp, 2300 const uint8_t* clip_scan) { 2301 int blended_colors[3]; 2302 bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; 2303 int src_gap = src_Bpp - 3; 2304 for (int col = 0; col < width; col++) { 2305 uint8_t src_alpha = *clip_scan++; 2306 if (src_alpha == 0) { 2307 dest_scan += dest_Bpp; 2308 src_scan += src_Bpp; 2309 continue; 2310 } 2311 if (bNonseparableBlend) { 2312 uint8_t dest_scan_o[3]; 2313 dest_scan_o[0] = dest_scan[2]; 2314 dest_scan_o[1] = dest_scan[1]; 2315 dest_scan_o[2] = dest_scan[0]; 2316 RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); 2317 } 2318 for (int color = 0; color < 3; color++) { 2319 int index = 2 - color; 2320 int src_color = *src_scan; 2321 int back_color = dest_scan[index]; 2322 int blended = bNonseparableBlend 2323 ? blended_colors[color] 2324 : Blend(blend_type, back_color, src_color); 2325 dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 2326 src_scan++; 2327 } 2328 dest_scan += dest_Bpp; 2329 src_scan += src_gap; 2330 } 2331 } 2332 2333 void CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan, 2334 const uint8_t* src_scan, 2335 int width, 2336 int src_Bpp, 2337 const uint8_t* clip_scan) { 2338 int src_gap = src_Bpp - 3; 2339 for (int col = 0; col < width; col++) { 2340 int src_alpha = clip_scan[col]; 2341 if (src_alpha == 255) { 2342 dest_scan[2] = *src_scan++; 2343 dest_scan[1] = *src_scan++; 2344 dest_scan[0] = *src_scan++; 2345 dest_scan[3] = 255; 2346 dest_scan += 4; 2347 src_scan += src_gap; 2348 continue; 2349 } 2350 if (src_alpha == 0) { 2351 dest_scan += 4; 2352 src_scan += src_Bpp; 2353 continue; 2354 } 2355 int back_alpha = dest_scan[3]; 2356 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2357 dest_scan[3] = dest_alpha; 2358 int alpha_ratio = src_alpha * 255 / dest_alpha; 2359 for (int color = 0; color < 3; color++) { 2360 int index = 2 - color; 2361 dest_scan[index] = 2362 FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio); 2363 src_scan++; 2364 } 2365 dest_scan += 4; 2366 src_scan += src_gap; 2367 } 2368 } 2369 2370 void CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan, 2371 const uint8_t* src_scan, 2372 int width, 2373 int dest_Bpp, 2374 int src_Bpp, 2375 const uint8_t* clip_scan) { 2376 for (int col = 0; col < width; col++) { 2377 int src_alpha = clip_scan[col]; 2378 if (src_alpha == 255) { 2379 dest_scan[2] = src_scan[0]; 2380 dest_scan[1] = src_scan[1]; 2381 dest_scan[0] = src_scan[2]; 2382 } else if (src_alpha) { 2383 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], *src_scan, src_alpha); 2384 src_scan++; 2385 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], *src_scan, src_alpha); 2386 src_scan++; 2387 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], *src_scan, src_alpha); 2388 dest_scan += dest_Bpp; 2389 src_scan += src_Bpp - 2; 2390 continue; 2391 } 2392 dest_scan += dest_Bpp; 2393 src_scan += src_Bpp; 2394 } 2395 } 2396 2397 void CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 2398 const uint8_t* src_scan, 2399 FX_ARGB* pPalette, 2400 int pixel_count, 2401 int DestBpp, 2402 const uint8_t* clip_scan) { 2403 for (int col = 0; col < pixel_count; col++) { 2404 FX_ARGB argb = pPalette ? pPalette[*src_scan] : (*src_scan) * 0x010101; 2405 int src_r = FXARGB_R(argb); 2406 int src_g = FXARGB_G(argb); 2407 int src_b = FXARGB_B(argb); 2408 if (clip_scan && clip_scan[col] < 255) { 2409 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]); 2410 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]); 2411 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]); 2412 } else { 2413 dest_scan[2] = src_b; 2414 dest_scan[1] = src_g; 2415 dest_scan[0] = src_r; 2416 } 2417 dest_scan += DestBpp; 2418 src_scan++; 2419 } 2420 } 2421 2422 void CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 2423 const uint8_t* src_scan, 2424 int src_left, 2425 FX_ARGB* pPalette, 2426 int pixel_count, 2427 int DestBpp, 2428 const uint8_t* clip_scan) { 2429 int reset_r, reset_g, reset_b; 2430 int set_r, set_g, set_b; 2431 if (pPalette) { 2432 reset_r = FXARGB_R(pPalette[0]); 2433 reset_g = FXARGB_G(pPalette[0]); 2434 reset_b = FXARGB_B(pPalette[0]); 2435 set_r = FXARGB_R(pPalette[1]); 2436 set_g = FXARGB_G(pPalette[1]); 2437 set_b = FXARGB_B(pPalette[1]); 2438 } else { 2439 reset_r = reset_g = reset_b = 0; 2440 set_r = set_g = set_b = 255; 2441 } 2442 for (int col = 0; col < pixel_count; col++) { 2443 int src_r, src_g, src_b; 2444 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 2445 src_r = set_r; 2446 src_g = set_g; 2447 src_b = set_b; 2448 } else { 2449 src_r = reset_r; 2450 src_g = reset_g; 2451 src_b = reset_b; 2452 } 2453 if (clip_scan && clip_scan[col] < 255) { 2454 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]); 2455 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]); 2456 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]); 2457 } else { 2458 dest_scan[2] = src_b; 2459 dest_scan[1] = src_g; 2460 dest_scan[0] = src_r; 2461 } 2462 dest_scan += DestBpp; 2463 } 2464 } 2465 2466 void CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 2467 const uint8_t* src_scan, 2468 int width, 2469 FX_ARGB* pPalette, 2470 const uint8_t* clip_scan) { 2471 for (int col = 0; col < width; col++) { 2472 int src_r, src_g, src_b; 2473 if (pPalette) { 2474 FX_ARGB argb = pPalette[*src_scan]; 2475 src_r = FXARGB_R(argb); 2476 src_g = FXARGB_G(argb); 2477 src_b = FXARGB_B(argb); 2478 } else { 2479 src_r = src_g = src_b = *src_scan; 2480 } 2481 if (!clip_scan || clip_scan[col] == 255) { 2482 dest_scan[2] = src_b; 2483 dest_scan[1] = src_g; 2484 dest_scan[0] = src_r; 2485 dest_scan[3] = 255; 2486 src_scan++; 2487 dest_scan += 4; 2488 continue; 2489 } 2490 int src_alpha = clip_scan[col]; 2491 if (src_alpha == 0) { 2492 dest_scan += 4; 2493 src_scan++; 2494 continue; 2495 } 2496 int back_alpha = dest_scan[3]; 2497 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2498 dest_scan[3] = dest_alpha; 2499 int alpha_ratio = src_alpha * 255 / dest_alpha; 2500 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); 2501 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); 2502 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); 2503 dest_scan += 4; 2504 src_scan++; 2505 } 2506 } 2507 2508 void CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan, 2509 const uint8_t* src_scan, 2510 int src_left, 2511 int width, 2512 FX_ARGB* pPalette, 2513 const uint8_t* clip_scan) { 2514 int reset_r, reset_g, reset_b; 2515 int set_r, set_g, set_b; 2516 if (pPalette) { 2517 reset_r = FXARGB_R(pPalette[0]); 2518 reset_g = FXARGB_G(pPalette[0]); 2519 reset_b = FXARGB_B(pPalette[0]); 2520 set_r = FXARGB_R(pPalette[1]); 2521 set_g = FXARGB_G(pPalette[1]); 2522 set_b = FXARGB_B(pPalette[1]); 2523 } else { 2524 reset_r = reset_g = reset_b = 0; 2525 set_r = set_g = set_b = 255; 2526 } 2527 for (int col = 0; col < width; col++) { 2528 int src_r, src_g, src_b; 2529 if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { 2530 src_r = set_r; 2531 src_g = set_g; 2532 src_b = set_b; 2533 } else { 2534 src_r = reset_r; 2535 src_g = reset_g; 2536 src_b = reset_b; 2537 } 2538 if (!clip_scan || clip_scan[col] == 255) { 2539 dest_scan[2] = src_b; 2540 dest_scan[1] = src_g; 2541 dest_scan[0] = src_r; 2542 dest_scan[3] = 255; 2543 dest_scan += 4; 2544 continue; 2545 } 2546 int src_alpha = clip_scan[col]; 2547 if (src_alpha == 0) { 2548 dest_scan += 4; 2549 continue; 2550 } 2551 int back_alpha = dest_scan[3]; 2552 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2553 dest_scan[3] = dest_alpha; 2554 int alpha_ratio = src_alpha * 255 / dest_alpha; 2555 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); 2556 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); 2557 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); 2558 dest_scan += 4; 2559 } 2560 } 2561 2562 void CompositeRow_ByteMask2Argb_RgbByteOrder(uint8_t* dest_scan, 2563 const uint8_t* src_scan, 2564 int mask_alpha, 2565 int src_r, 2566 int src_g, 2567 int src_b, 2568 int pixel_count, 2569 int blend_type, 2570 const uint8_t* clip_scan) { 2571 for (int col = 0; col < pixel_count; col++) { 2572 int src_alpha; 2573 if (clip_scan) { 2574 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 2575 } else { 2576 src_alpha = mask_alpha * src_scan[col] / 255; 2577 } 2578 uint8_t back_alpha = dest_scan[3]; 2579 if (back_alpha == 0) { 2580 FXARGB_SETRGBORDERDIB(dest_scan, 2581 FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 2582 dest_scan += 4; 2583 continue; 2584 } 2585 if (src_alpha == 0) { 2586 dest_scan += 4; 2587 continue; 2588 } 2589 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2590 dest_scan[3] = dest_alpha; 2591 int alpha_ratio = src_alpha * 255 / dest_alpha; 2592 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 2593 int blended_colors[3]; 2594 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 2595 static_cast<uint8_t>(src_g), 2596 static_cast<uint8_t>(src_r)}; 2597 uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; 2598 RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); 2599 dest_scan[2] = 2600 FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio); 2601 dest_scan[1] = 2602 FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio); 2603 dest_scan[0] = 2604 FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio); 2605 } else if (blend_type) { 2606 int blended = Blend(blend_type, dest_scan[2], src_b); 2607 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 2608 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio); 2609 blended = Blend(blend_type, dest_scan[1], src_g); 2610 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 2611 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio); 2612 blended = Blend(blend_type, dest_scan[0], src_r); 2613 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 2614 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio); 2615 } else { 2616 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); 2617 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); 2618 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); 2619 } 2620 dest_scan += 4; 2621 } 2622 } 2623 2624 void CompositeRow_ByteMask2Rgb_RgbByteOrder(uint8_t* dest_scan, 2625 const uint8_t* src_scan, 2626 int mask_alpha, 2627 int src_r, 2628 int src_g, 2629 int src_b, 2630 int pixel_count, 2631 int blend_type, 2632 int Bpp, 2633 const uint8_t* clip_scan) { 2634 for (int col = 0; col < pixel_count; col++) { 2635 int src_alpha; 2636 if (clip_scan) { 2637 src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; 2638 } else { 2639 src_alpha = mask_alpha * src_scan[col] / 255; 2640 } 2641 if (src_alpha == 0) { 2642 dest_scan += Bpp; 2643 continue; 2644 } 2645 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 2646 int blended_colors[3]; 2647 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 2648 static_cast<uint8_t>(src_g), 2649 static_cast<uint8_t>(src_r)}; 2650 uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; 2651 RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); 2652 dest_scan[2] = 2653 FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha); 2654 dest_scan[1] = 2655 FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha); 2656 dest_scan[0] = 2657 FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha); 2658 } else if (blend_type) { 2659 int blended = Blend(blend_type, dest_scan[2], src_b); 2660 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha); 2661 blended = Blend(blend_type, dest_scan[1], src_g); 2662 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha); 2663 blended = Blend(blend_type, dest_scan[0], src_r); 2664 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha); 2665 } else { 2666 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha); 2667 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha); 2668 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha); 2669 } 2670 dest_scan += Bpp; 2671 } 2672 } 2673 2674 void CompositeRow_BitMask2Argb_RgbByteOrder(uint8_t* dest_scan, 2675 const uint8_t* src_scan, 2676 int mask_alpha, 2677 int src_r, 2678 int src_g, 2679 int src_b, 2680 int src_left, 2681 int pixel_count, 2682 int blend_type, 2683 const uint8_t* clip_scan) { 2684 if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { 2685 FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b); 2686 for (int col = 0; col < pixel_count; col++) { 2687 if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { 2688 FXARGB_SETRGBORDERDIB(dest_scan, argb); 2689 } 2690 dest_scan += 4; 2691 } 2692 return; 2693 } 2694 for (int col = 0; col < pixel_count; col++) { 2695 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 2696 dest_scan += 4; 2697 continue; 2698 } 2699 int src_alpha; 2700 if (clip_scan) { 2701 src_alpha = mask_alpha * clip_scan[col] / 255; 2702 } else { 2703 src_alpha = mask_alpha; 2704 } 2705 uint8_t back_alpha = dest_scan[3]; 2706 if (back_alpha == 0) { 2707 FXARGB_SETRGBORDERDIB(dest_scan, 2708 FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); 2709 dest_scan += 4; 2710 continue; 2711 } 2712 uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; 2713 dest_scan[3] = dest_alpha; 2714 int alpha_ratio = src_alpha * 255 / dest_alpha; 2715 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 2716 int blended_colors[3]; 2717 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 2718 static_cast<uint8_t>(src_g), 2719 static_cast<uint8_t>(src_r)}; 2720 uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; 2721 RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); 2722 dest_scan[2] = 2723 FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio); 2724 dest_scan[1] = 2725 FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio); 2726 dest_scan[0] = 2727 FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio); 2728 } else if (blend_type) { 2729 int blended = Blend(blend_type, dest_scan[2], src_b); 2730 blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); 2731 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio); 2732 blended = Blend(blend_type, dest_scan[1], src_g); 2733 blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); 2734 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio); 2735 blended = Blend(blend_type, dest_scan[0], src_r); 2736 blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); 2737 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio); 2738 } else { 2739 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); 2740 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); 2741 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); 2742 } 2743 dest_scan += 4; 2744 } 2745 } 2746 2747 void CompositeRow_BitMask2Rgb_RgbByteOrder(uint8_t* dest_scan, 2748 const uint8_t* src_scan, 2749 int mask_alpha, 2750 int src_r, 2751 int src_g, 2752 int src_b, 2753 int src_left, 2754 int pixel_count, 2755 int blend_type, 2756 int Bpp, 2757 const uint8_t* clip_scan) { 2758 if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { 2759 for (int col = 0; col < pixel_count; col++) { 2760 if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { 2761 dest_scan[2] = src_b; 2762 dest_scan[1] = src_g; 2763 dest_scan[0] = src_r; 2764 } 2765 dest_scan += Bpp; 2766 } 2767 return; 2768 } 2769 for (int col = 0; col < pixel_count; col++) { 2770 if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { 2771 dest_scan += Bpp; 2772 continue; 2773 } 2774 int src_alpha; 2775 if (clip_scan) { 2776 src_alpha = mask_alpha * clip_scan[col] / 255; 2777 } else { 2778 src_alpha = mask_alpha; 2779 } 2780 if (src_alpha == 0) { 2781 dest_scan += Bpp; 2782 continue; 2783 } 2784 if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { 2785 int blended_colors[3]; 2786 uint8_t scan[3] = {static_cast<uint8_t>(src_b), 2787 static_cast<uint8_t>(src_g), 2788 static_cast<uint8_t>(src_r)}; 2789 uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; 2790 RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); 2791 dest_scan[2] = 2792 FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha); 2793 dest_scan[1] = 2794 FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha); 2795 dest_scan[0] = 2796 FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha); 2797 } else if (blend_type) { 2798 int back_color = dest_scan[2]; 2799 int blended = Blend(blend_type, back_color, src_b); 2800 dest_scan[2] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 2801 back_color = dest_scan[1]; 2802 blended = Blend(blend_type, back_color, src_g); 2803 dest_scan[1] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 2804 back_color = dest_scan[0]; 2805 blended = Blend(blend_type, back_color, src_r); 2806 dest_scan[0] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); 2807 } else { 2808 dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha); 2809 dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha); 2810 dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha); 2811 } 2812 dest_scan += Bpp; 2813 } 2814 } 2815 2816 } // namespace 2817 2818 CFX_ScanlineCompositor::CFX_ScanlineCompositor() 2819 : m_BlendType(FXDIB_BLEND_NORMAL), m_bRgbByteOrder(false) {} 2820 2821 CFX_ScanlineCompositor::~CFX_ScanlineCompositor() {} 2822 2823 bool CFX_ScanlineCompositor::Init(FXDIB_Format dest_format, 2824 FXDIB_Format src_format, 2825 int32_t width, 2826 uint32_t* pSrcPalette, 2827 uint32_t mask_color, 2828 int blend_type, 2829 bool bClip, 2830 bool bRgbByteOrder, 2831 int alpha_flag) { 2832 m_SrcFormat = src_format; 2833 m_DestFormat = dest_format; 2834 m_BlendType = blend_type; 2835 m_bRgbByteOrder = bRgbByteOrder; 2836 if ((dest_format & 0xff) == 1) 2837 return false; 2838 if (m_SrcFormat == FXDIB_1bppMask || m_SrcFormat == FXDIB_8bppMask) { 2839 InitSourceMask(alpha_flag, mask_color); 2840 return true; 2841 } 2842 if ((~src_format & 0x0400) && (dest_format & 0x0400)) 2843 return false; 2844 if ((m_SrcFormat & 0xff) <= 8) { 2845 if (dest_format == FXDIB_8bppMask) 2846 return true; 2847 2848 InitSourcePalette(src_format, dest_format, pSrcPalette); 2849 m_iTransparency = 2850 (dest_format == FXDIB_Argb ? 1 : 0) + (dest_format & 0x0200 ? 2 : 0) + 2851 (dest_format & 0x0400 ? 4 : 0) + ((src_format & 0xff) == 1 ? 8 : 0); 2852 return true; 2853 } 2854 m_iTransparency = 2855 (src_format & 0x0200 ? 0 : 1) + (dest_format & 0x0200 ? 0 : 2) + 2856 (blend_type == FXDIB_BLEND_NORMAL ? 4 : 0) + (bClip ? 8 : 0) + 2857 (src_format & 0x0400 ? 16 : 0) + (dest_format & 0x0400 ? 32 : 0); 2858 return true; 2859 } 2860 2861 void CFX_ScanlineCompositor::InitSourceMask(int alpha_flag, 2862 uint32_t mask_color) { 2863 int mask_black = 0; 2864 if (alpha_flag >> 8) { 2865 m_MaskAlpha = alpha_flag & 0xff; 2866 m_MaskRed = FXSYS_GetCValue(mask_color); 2867 m_MaskGreen = FXSYS_GetMValue(mask_color); 2868 m_MaskBlue = FXSYS_GetYValue(mask_color); 2869 mask_black = FXSYS_GetKValue(mask_color); 2870 } else { 2871 m_MaskAlpha = FXARGB_A(mask_color); 2872 m_MaskRed = FXARGB_R(mask_color); 2873 m_MaskGreen = FXARGB_G(mask_color); 2874 m_MaskBlue = FXARGB_B(mask_color); 2875 } 2876 if (m_DestFormat == FXDIB_8bppMask) 2877 return; 2878 2879 if ((m_DestFormat & 0xff) == 8) { 2880 if (alpha_flag >> 8) { 2881 uint8_t r; 2882 uint8_t g; 2883 uint8_t b; 2884 std::tie(r, g, b) = 2885 AdobeCMYK_to_sRGB1(m_MaskRed, m_MaskGreen, m_MaskBlue, mask_black); 2886 m_MaskRed = FXRGB2GRAY(r, g, b); 2887 } else { 2888 m_MaskRed = FXRGB2GRAY(m_MaskRed, m_MaskGreen, m_MaskBlue); 2889 } 2890 if (m_DestFormat & 0x0400) 2891 m_MaskRed = FX_CCOLOR(m_MaskRed); 2892 return; 2893 } 2894 uint8_t* mask_color_p = (uint8_t*)&mask_color; 2895 mask_color = 2896 (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color); 2897 if (alpha_flag >> 8) { 2898 std::tie(mask_color_p[2], mask_color_p[1], mask_color_p[0]) = 2899 AdobeCMYK_to_sRGB1(mask_color_p[0], mask_color_p[1], mask_color_p[2], 2900 mask_color_p[3]); 2901 m_MaskRed = mask_color_p[2]; 2902 m_MaskGreen = mask_color_p[1]; 2903 m_MaskBlue = mask_color_p[0]; 2904 } 2905 } 2906 2907 void CFX_ScanlineCompositor::InitSourcePalette(FXDIB_Format src_format, 2908 FXDIB_Format dest_format, 2909 const uint32_t* pSrcPalette) { 2910 bool isSrcCmyk = !!(src_format & 0x0400); 2911 bool isDstCmyk = !!(dest_format & 0x0400); 2912 m_pSrcPalette = nullptr; 2913 if (pSrcPalette) { 2914 if ((dest_format & 0xff) == 8) { 2915 int pal_count = 1 << (src_format & 0xff); 2916 uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); 2917 m_pSrcPalette.reset(reinterpret_cast<uint32_t*>(gray_pal)); 2918 if (isSrcCmyk) { 2919 for (int i = 0; i < pal_count; ++i) { 2920 FX_CMYK cmyk = pSrcPalette[i]; 2921 uint8_t r; 2922 uint8_t g; 2923 uint8_t b; 2924 std::tie(r, g, b) = 2925 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), 2926 FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk)); 2927 *gray_pal++ = FXRGB2GRAY(r, g, b); 2928 } 2929 } else { 2930 for (int i = 0; i < pal_count; ++i) { 2931 FX_ARGB argb = pSrcPalette[i]; 2932 *gray_pal++ = 2933 FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb)); 2934 } 2935 } 2936 return; 2937 } 2938 int palsize = 1 << (src_format & 0xff); 2939 m_pSrcPalette.reset(FX_Alloc(uint32_t, palsize)); 2940 uint32_t* pPalette = m_pSrcPalette.get(); 2941 if (isDstCmyk == isSrcCmyk) { 2942 memcpy(pPalette, pSrcPalette, palsize * sizeof(uint32_t)); 2943 } else { 2944 for (int i = 0; i < palsize; ++i) { 2945 FX_CMYK cmyk = pSrcPalette[i]; 2946 uint8_t r; 2947 uint8_t g; 2948 uint8_t b; 2949 std::tie(r, g, b) = 2950 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), 2951 FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk)); 2952 pPalette[i] = FXARGB_MAKE(0xff, r, g, b); 2953 } 2954 } 2955 return; 2956 } 2957 if ((dest_format & 0xff) == 8) { 2958 int pal_count = 1 << (src_format & 0xff); 2959 uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); 2960 if (pal_count == 2) { 2961 gray_pal[0] = 0; 2962 gray_pal[1] = 255; 2963 } else { 2964 for (int i = 0; i < pal_count; ++i) 2965 gray_pal[i] = i; 2966 } 2967 m_pSrcPalette.reset(reinterpret_cast<uint32_t*>(gray_pal)); 2968 return; 2969 } 2970 int palsize = 1 << (src_format & 0xff); 2971 m_pSrcPalette.reset(FX_Alloc(uint32_t, palsize)); 2972 uint32_t* pPalette = m_pSrcPalette.get(); 2973 if (palsize == 2) { 2974 pPalette[0] = isSrcCmyk ? 255 : 0xff000000; 2975 pPalette[1] = isSrcCmyk ? 0 : 0xffffffff; 2976 } else { 2977 for (int i = 0; i < palsize; ++i) 2978 pPalette[i] = isSrcCmyk ? FX_CCOLOR(i) : (i * 0x10101); 2979 } 2980 if (isSrcCmyk != isDstCmyk) { 2981 for (int i = 0; i < palsize; ++i) { 2982 FX_CMYK cmyk = pPalette[i]; 2983 uint8_t r; 2984 uint8_t g; 2985 uint8_t b; 2986 std::tie(r, g, b) = 2987 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), 2988 FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk)); 2989 pPalette[i] = FXARGB_MAKE(0xff, r, g, b); 2990 } 2991 } 2992 } 2993 2994 void CFX_ScanlineCompositor::CompositeRgbBitmapLine( 2995 uint8_t* dest_scan, 2996 const uint8_t* src_scan, 2997 int width, 2998 const uint8_t* clip_scan, 2999 const uint8_t* src_extra_alpha, 3000 uint8_t* dst_extra_alpha) { 3001 int src_Bpp = (m_SrcFormat & 0xff) >> 3; 3002 int dest_Bpp = (m_DestFormat & 0xff) >> 3; 3003 if (m_bRgbByteOrder) { 3004 switch (m_iTransparency) { 3005 case 0: 3006 case 4: 3007 case 8: 3008 case 12: 3009 CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width, 3010 m_BlendType, clip_scan); 3011 break; 3012 case 1: 3013 CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder( 3014 dest_scan, src_scan, width, m_BlendType, src_Bpp); 3015 break; 3016 case 2: 3017 case 10: 3018 CompositeRow_Argb2Rgb_Blend_RgbByteOrder( 3019 dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan); 3020 break; 3021 case 3: 3022 CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder( 3023 dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp); 3024 break; 3025 case 5: 3026 CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, 3027 width, src_Bpp); 3028 break; 3029 case 6: 3030 case 14: 3031 CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, 3032 dest_Bpp, clip_scan); 3033 break; 3034 case 7: 3035 CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder( 3036 dest_scan, src_scan, width, dest_Bpp, src_Bpp); 3037 break; 3038 case 9: 3039 CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder( 3040 dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan); 3041 break; 3042 case 11: 3043 CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, 3044 m_BlendType, dest_Bpp, 3045 src_Bpp, clip_scan); 3046 break; 3047 case 13: 3048 CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder( 3049 dest_scan, src_scan, width, src_Bpp, clip_scan); 3050 break; 3051 case 15: 3052 CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder( 3053 dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan); 3054 break; 3055 } 3056 return; 3057 } 3058 if (m_DestFormat == FXDIB_8bppMask) { 3059 if (m_SrcFormat & 0x0200) { 3060 if (m_SrcFormat == FXDIB_Argb) { 3061 CompositeRow_AlphaToMask(dest_scan, src_scan, width, clip_scan, 4); 3062 } else { 3063 CompositeRow_AlphaToMask(dest_scan, src_extra_alpha, width, clip_scan, 3064 1); 3065 } 3066 } else { 3067 CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan); 3068 } 3069 } else if ((m_DestFormat & 0xff) == 8) { 3070 if (m_DestFormat & 0x0400) { 3071 for (int i = 0; i < width; ++i) { 3072 *dest_scan = ~*dest_scan; 3073 dest_scan++; 3074 } 3075 } 3076 if (m_SrcFormat & 0x0200) { 3077 if (m_DestFormat & 0x0200) { 3078 CompositeRow_Argb2Graya(dest_scan, src_scan, width, m_BlendType, 3079 clip_scan, src_extra_alpha, dst_extra_alpha); 3080 } else { 3081 CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType, 3082 clip_scan, src_extra_alpha); 3083 } 3084 } else { 3085 if (m_DestFormat & 0x0200) { 3086 CompositeRow_Rgb2Graya(dest_scan, src_scan, src_Bpp, width, m_BlendType, 3087 clip_scan, dst_extra_alpha); 3088 } else { 3089 CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType, 3090 clip_scan); 3091 } 3092 } 3093 if (m_DestFormat & 0x0400) { 3094 for (int i = 0; i < width; ++i) { 3095 *dest_scan = ~*dest_scan; 3096 dest_scan++; 3097 } 3098 } 3099 } else { 3100 switch (m_iTransparency) { 3101 case 0: 3102 case 4: 3103 case 8: 3104 case 4 + 8: { 3105 CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType, 3106 clip_scan, dst_extra_alpha, src_extra_alpha); 3107 } break; 3108 case 1: 3109 CompositeRow_Rgb2Argb_Blend_NoClip( 3110 dest_scan, src_scan, width, m_BlendType, src_Bpp, dst_extra_alpha); 3111 break; 3112 case 1 + 8: 3113 CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width, 3114 m_BlendType, src_Bpp, clip_scan, 3115 dst_extra_alpha); 3116 break; 3117 case 1 + 4: 3118 CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width, 3119 src_Bpp, dst_extra_alpha); 3120 break; 3121 case 1 + 4 + 8: 3122 CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp, 3123 clip_scan, dst_extra_alpha); 3124 break; 3125 case 2: 3126 case 2 + 8: 3127 CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType, 3128 dest_Bpp, clip_scan, src_extra_alpha); 3129 break; 3130 case 2 + 4: 3131 case 2 + 4 + 8: 3132 CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp, 3133 clip_scan, src_extra_alpha); 3134 break; 3135 case 1 + 2: 3136 CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width, 3137 m_BlendType, dest_Bpp, src_Bpp); 3138 break; 3139 case 1 + 2 + 8: 3140 CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, 3141 dest_Bpp, src_Bpp, clip_scan); 3142 break; 3143 case 1 + 2 + 4: 3144 CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width, 3145 dest_Bpp, src_Bpp); 3146 break; 3147 case 1 + 2 + 4 + 8: 3148 CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp, 3149 src_Bpp, clip_scan); 3150 break; 3151 } 3152 } 3153 } 3154 3155 void CFX_ScanlineCompositor::CompositePalBitmapLine( 3156 uint8_t* dest_scan, 3157 const uint8_t* src_scan, 3158 int src_left, 3159 int width, 3160 const uint8_t* clip_scan, 3161 const uint8_t* src_extra_alpha, 3162 uint8_t* dst_extra_alpha) { 3163 if (m_bRgbByteOrder) { 3164 if (m_SrcFormat == FXDIB_1bppRgb) { 3165 if (m_DestFormat == FXDIB_8bppRgb) { 3166 return; 3167 } 3168 if (m_DestFormat == FXDIB_Argb) { 3169 CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder( 3170 dest_scan, src_scan, src_left, width, m_pSrcPalette.get(), 3171 clip_scan); 3172 } else { 3173 CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder( 3174 dest_scan, src_scan, src_left, m_pSrcPalette.get(), width, 3175 (m_DestFormat & 0xff) >> 3, clip_scan); 3176 } 3177 } else { 3178 if (m_DestFormat == FXDIB_8bppRgb) { 3179 return; 3180 } 3181 if (m_DestFormat == FXDIB_Argb) { 3182 CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder( 3183 dest_scan, src_scan, width, m_pSrcPalette.get(), clip_scan); 3184 } else { 3185 CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder( 3186 dest_scan, src_scan, m_pSrcPalette.get(), width, 3187 (m_DestFormat & 0xff) >> 3, clip_scan); 3188 } 3189 } 3190 return; 3191 } 3192 if (m_DestFormat == FXDIB_8bppMask) { 3193 CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan); 3194 return; 3195 } 3196 if ((m_DestFormat & 0xff) == 8) { 3197 if (m_iTransparency & 8) { 3198 if (m_DestFormat & 0x0200) { 3199 CompositeRow_1bppPal2Graya( 3200 dest_scan, src_scan, src_left, 3201 reinterpret_cast<const uint8_t*>(m_pSrcPalette.get()), width, 3202 m_BlendType, clip_scan, dst_extra_alpha); 3203 } else { 3204 CompositeRow_1bppPal2Gray( 3205 dest_scan, src_scan, src_left, 3206 reinterpret_cast<const uint8_t*>(m_pSrcPalette.get()), width, 3207 m_BlendType, clip_scan); 3208 } 3209 } else { 3210 if (m_DestFormat & 0x0200) 3211 CompositeRow_8bppPal2Graya( 3212 dest_scan, src_scan, 3213 reinterpret_cast<const uint8_t*>(m_pSrcPalette.get()), width, 3214 m_BlendType, clip_scan, dst_extra_alpha, src_extra_alpha); 3215 else 3216 CompositeRow_8bppPal2Gray( 3217 dest_scan, src_scan, 3218 reinterpret_cast<const uint8_t*>(m_pSrcPalette.get()), width, 3219 m_BlendType, clip_scan, src_extra_alpha); 3220 } 3221 } else { 3222 switch (m_iTransparency) { 3223 case 1 + 2: 3224 CompositeRow_8bppRgb2Argb_NoBlend(dest_scan, src_scan, width, 3225 m_pSrcPalette.get(), clip_scan, 3226 src_extra_alpha); 3227 break; 3228 case 1 + 2 + 8: 3229 CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width, 3230 m_pSrcPalette.get(), clip_scan); 3231 break; 3232 case 0: 3233 CompositeRow_8bppRgb2Rgb_NoBlend( 3234 dest_scan, src_scan, m_pSrcPalette.get(), width, 3235 (m_DestFormat & 0xff) >> 3, clip_scan, src_extra_alpha); 3236 break; 3237 case 0 + 8: 3238 CompositeRow_1bppRgb2Rgb_NoBlend(dest_scan, src_scan, src_left, 3239 m_pSrcPalette.get(), width, 3240 (m_DestFormat & 0xff) >> 3, clip_scan); 3241 break; 3242 case 0 + 2: 3243 CompositeRow_8bppRgb2Rgb_NoBlend( 3244 dest_scan, src_scan, m_pSrcPalette.get(), width, 3245 (m_DestFormat & 0xff) >> 3, clip_scan, src_extra_alpha); 3246 break; 3247 case 0 + 2 + 8: 3248 CompositeRow_1bppRgb2Rgba_NoBlend(dest_scan, src_scan, src_left, width, 3249 m_pSrcPalette.get(), clip_scan, 3250 dst_extra_alpha); 3251 break; 3252 break; 3253 } 3254 } 3255 } 3256 3257 void CFX_ScanlineCompositor::CompositeByteMaskLine(uint8_t* dest_scan, 3258 const uint8_t* src_scan, 3259 int width, 3260 const uint8_t* clip_scan, 3261 uint8_t* dst_extra_alpha) { 3262 if (m_DestFormat == FXDIB_8bppMask) { 3263 CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width, 3264 clip_scan); 3265 } else if ((m_DestFormat & 0xff) == 8) { 3266 if (m_DestFormat & 0x0200) { 3267 CompositeRow_ByteMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 3268 width, clip_scan, dst_extra_alpha); 3269 } else { 3270 CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 3271 width, clip_scan); 3272 } 3273 } else if (m_bRgbByteOrder) { 3274 if (m_DestFormat == FXDIB_Argb) { 3275 CompositeRow_ByteMask2Argb_RgbByteOrder( 3276 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 3277 width, m_BlendType, clip_scan); 3278 } else { 3279 CompositeRow_ByteMask2Rgb_RgbByteOrder( 3280 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 3281 width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); 3282 } 3283 return; 3284 } else if (m_DestFormat == FXDIB_Argb) { 3285 CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 3286 m_MaskGreen, m_MaskBlue, width, m_BlendType, 3287 clip_scan); 3288 } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) { 3289 CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 3290 m_MaskGreen, m_MaskBlue, width, m_BlendType, 3291 (m_DestFormat & 0xff) >> 3, clip_scan); 3292 } else if (m_DestFormat == FXDIB_Rgba) { 3293 CompositeRow_ByteMask2Rgba(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 3294 m_MaskGreen, m_MaskBlue, width, m_BlendType, 3295 clip_scan, dst_extra_alpha); 3296 } 3297 } 3298 3299 void CFX_ScanlineCompositor::CompositeBitMaskLine(uint8_t* dest_scan, 3300 const uint8_t* src_scan, 3301 int src_left, 3302 int width, 3303 const uint8_t* clip_scan, 3304 uint8_t* dst_extra_alpha) { 3305 if (m_DestFormat == FXDIB_8bppMask) { 3306 CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left, width, 3307 clip_scan); 3308 } else if ((m_DestFormat & 0xff) == 8) { 3309 if (m_DestFormat & 0x0200) { 3310 CompositeRow_BitMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 3311 src_left, width, clip_scan, dst_extra_alpha); 3312 } else { 3313 CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 3314 src_left, width, clip_scan); 3315 } 3316 } else if (m_bRgbByteOrder) { 3317 if (m_DestFormat == FXDIB_Argb) { 3318 CompositeRow_BitMask2Argb_RgbByteOrder( 3319 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 3320 src_left, width, m_BlendType, clip_scan); 3321 } else { 3322 CompositeRow_BitMask2Rgb_RgbByteOrder( 3323 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 3324 src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); 3325 } 3326 return; 3327 } else if (m_DestFormat == FXDIB_Argb) { 3328 CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, 3329 m_MaskGreen, m_MaskBlue, src_left, width, 3330 m_BlendType, clip_scan); 3331 } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) { 3332 CompositeRow_BitMask2Rgb( 3333 dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, 3334 src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); 3335 } 3336 } 3337