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