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