1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 /* $Id: gxblend.c 9666 2009-04-20 19:16:24Z mvrhel $ */
14 /* PDF 1.4 blending functions */
15
16 #include "memory_.h"
17 #include "gx.h"
18 #include "gstparam.h"
19 #include "gxblend.h"
20 #include "gxcolor2.h"
21
22 typedef int art_s32;
23
24 #if RAW_DUMP
25 extern unsigned int global_index;
26 extern unsigned int clist_band_count;
27 #endif
28
29 /* This function is used for mapping the SMask source to a
30 monochrome luminosity value which basically is the alpha value
31 Note, that separation colors are not allowed here. Everything
32 must be in CMYK, RGB or monochrome. */
33
34 /* Note, data is planar */
35
36 void
Smask_Luminosity_Mapping(int num_rows,int num_cols,int n_chan,int row_stride,int plane_stride,byte * dst,const byte * src,bool isadditive,bool SMask_is_CIE,gs_transparency_mask_subtype_t SMask_SubType)37 Smask_Luminosity_Mapping(int num_rows, int num_cols, int n_chan, int row_stride,
38 int plane_stride, byte *dst, const byte *src, bool isadditive,
39 bool SMask_is_CIE, gs_transparency_mask_subtype_t SMask_SubType)
40 {
41
42 int x,y;
43 int mask_alpha_offset,mask_C_offset,mask_M_offset,mask_Y_offset,mask_K_offset;
44 int mask_R_offset,mask_G_offset,mask_B_offset;
45 byte *dstptr;
46
47 #if RAW_DUMP
48
49 dump_raw_buffer(num_rows, row_stride, n_chan,
50 plane_stride, row_stride,
51 "Raw_Mask", src);
52
53 global_index++;
54
55 #endif
56
57 dstptr = dst;
58
59 /* If we are CIE AND subtype is Luminosity then we should just grab the Y channel */
60
61 if ( SMask_is_CIE && SMask_SubType == TRANSPARENCY_MASK_Luminosity ){
62
63
64 memcpy(dst, &(src[plane_stride]), plane_stride);
65 return;
66
67 }
68
69 /* If we are alpha type, then just grab that */
70 /* We need to optimize this so that we are only drawing alpha in the rect fills */
71
72 if ( SMask_SubType == TRANSPARENCY_MASK_Alpha ){
73
74 mask_alpha_offset = (n_chan - 1) * plane_stride;
75 memcpy(dst, &(src[mask_alpha_offset]), plane_stride);
76 return;
77
78 }
79
80 /* To avoid the if statement inside this loop,
81 decide on additive or subractive now */
82
83 if (isadditive || n_chan == 2)
84 {
85
86 /* Now we need to split Gray from RGB */
87
88 if( n_chan == 2 )
89 {
90 /* Gray Scale case */
91
92 mask_alpha_offset = (n_chan - 1) * plane_stride;
93 mask_R_offset = 0;
94
95 for ( y = 0; y < num_rows; y++ )
96 {
97
98 for ( x = 0; x < num_cols; x++ ){
99
100 /* With the current design this will indicate if
101 we ever did a fill at this pixel. if not then move on.
102 This could have some serious optimization */
103
104 if (src[x + mask_alpha_offset] != 0x00) {
105
106 dstptr[x] = src[x + mask_R_offset];
107
108 }
109
110 }
111
112 dstptr += row_stride;
113 mask_alpha_offset += row_stride;
114 mask_R_offset += row_stride;
115
116 }
117
118 } else {
119
120
121
122 /* RGB case */
123
124 mask_R_offset = 0;
125 mask_G_offset = plane_stride;
126 mask_B_offset = 2 * plane_stride;
127 mask_alpha_offset = (n_chan - 1) * plane_stride;
128
129 for ( y = 0; y < num_rows; y++ )
130 {
131
132 for ( x = 0; x < num_cols; x++ ){
133
134 /* With the current design this will indicate if
135 we ever did a fill at this pixel. if not then move on */
136
137 if (src[x + mask_alpha_offset] != 0x00) {
138
139 /* Get luminosity of Device RGB value */
140
141 float temp;
142
143 temp = ( 0.30 * src[x + mask_R_offset] +
144 0.59 * src[x + mask_G_offset] +
145 0.11 * src[x + mask_B_offset] );
146
147 temp = temp * (1.0 / 255.0 ); /* May need to be optimized */
148 dstptr[x] = float_color_to_byte_color(temp);
149
150 }
151
152 }
153
154 dstptr += row_stride;
155 mask_alpha_offset += row_stride;
156 mask_R_offset += row_stride;
157 mask_G_offset += row_stride;
158 mask_B_offset += row_stride;
159
160 }
161
162 }
163
164 } else {
165
166 /* CMYK case */
167
168 mask_alpha_offset = (n_chan - 1) * plane_stride;
169 mask_C_offset = 0;
170 mask_M_offset = plane_stride;
171 mask_Y_offset = 2 * plane_stride;
172 mask_K_offset = 3 * plane_stride;
173
174 for ( y = 0; y < num_rows; y++ ){
175
176 for ( x = 0; x < num_cols; x++ ){
177
178 /* With the current design this will indicate if
179 we ever did a fill at this pixel. if not then move on */
180
181 if (src[x + mask_alpha_offset] != 0x00){
182
183 /* PDF spec says to use Y = 0.30 (1 - C)(1 - K) +
184 0.59 (1 - M)(1 - K) + 0.11 (1 - Y)(1 - K) */
185 /* For device CMYK */
186
187 float temp;
188
189 temp = ( 0.30 * ( 0xff - src[x + mask_C_offset]) +
190 0.59 * ( 0xff - src[x + mask_M_offset]) +
191 0.11 * ( 0xff - src[x + mask_Y_offset]) ) *
192 ( 0xff - src[x + mask_K_offset]);
193
194 temp = temp * (1.0 / 65025.0 ); /* May need to be optimized */
195
196 dstptr[x] = float_color_to_byte_color(temp);
197
198 }
199
200 }
201
202 dstptr += row_stride;
203 mask_alpha_offset += row_stride;
204 mask_C_offset += row_stride;
205 mask_M_offset += row_stride;
206 mask_Y_offset += row_stride;
207 mask_K_offset += row_stride;
208
209 }
210
211
212 }
213
214
215 }
216
217 void
art_blend_luminosity_rgb_8(int n_chan,byte * dst,const byte * backdrop,const byte * src)218 art_blend_luminosity_rgb_8(int n_chan, byte *dst, const byte *backdrop,
219 const byte *src)
220 {
221 int rb = backdrop[0], gb = backdrop[1], bb = backdrop[2];
222 int rs = src[0], gs = src[1], bs = src[2];
223 int delta_y;
224 int r, g, b;
225
226 /*
227 * From section 7.4 of the PDF 1.5 specification, for RGB, the luminosity
228 * is: Y = 0.30 R + 0.59 G + 0.11 B)
229 */
230 delta_y = ((rs - rb) * 77 + (gs - gb) * 151 + (bs - bb) * 28 + 0x80) >> 8;
231 r = rb + delta_y;
232 g = gb + delta_y;
233 b = bb + delta_y;
234 if ((r | g | b) & 0x100) {
235 int y;
236 int scale;
237
238 y = (rs * 77 + gs * 151 + bs * 28 + 0x80) >> 8;
239 if (delta_y > 0) {
240 int max;
241
242 max = r > g ? r : g;
243 max = b > max ? b : max;
244 scale = ((255 - y) << 16) / (max - y);
245 } else {
246 int min;
247
248 min = r < g ? r : g;
249 min = b < min ? b : min;
250 scale = (y << 16) / (y - min);
251 }
252 r = y + (((r - y) * scale + 0x8000) >> 16);
253 g = y + (((g - y) * scale + 0x8000) >> 16);
254 b = y + (((b - y) * scale + 0x8000) >> 16);
255 }
256 dst[0] = r;
257 dst[1] = g;
258 dst[2] = b;
259 }
260
261 void
art_blend_luminosity_custom_8(int n_chan,byte * dst,const byte * backdrop,const byte * src)262 art_blend_luminosity_custom_8(int n_chan, byte *dst, const byte *backdrop,
263 const byte *src)
264 {
265 int delta_y = 0, test = 0;
266 int r[ART_MAX_CHAN];
267 int i;
268
269 /*
270 * Since we do not know the details of the blending color space, we are
271 * simply using the average as the luminosity. First we need the
272 * delta luminosity values.
273 */
274 for (i = 0; i < n_chan; i++)
275 delta_y += src[i] - backdrop[i];
276 delta_y = (delta_y + n_chan / 2) / n_chan;
277 for (i = 0; i < n_chan; i++) {
278 r[i] = backdrop[i] + delta_y;
279 test |= r[i];
280 }
281
282 if (test & 0x100) {
283 int y;
284 int scale;
285
286 /* Assume that the luminosity is simply the average of the backdrop. */
287 y = src[0];
288 for (i = 1; i < n_chan; i++)
289 y += src[i];
290 y = (y + n_chan / 2) / n_chan;
291
292 if (delta_y > 0) {
293 int max;
294
295 max = r[0];
296 for (i = 1; i < n_chan; i++)
297 max = max(max, r[i]);
298 scale = ((255 - y) << 16) / (max - y);
299 } else {
300 int min;
301
302 min = r[0];
303 for (i = 1; i < n_chan; i++)
304 min = min(min, r[i]);
305 scale = (y << 16) / (y - min);
306 }
307 for (i = 0; i < n_chan; i++)
308 r[i] = y + (((r[i] - y) * scale + 0x8000) >> 16);
309 }
310 for (i = 0; i < n_chan; i++)
311 dst[i] = r[i];
312 }
313
314 /*
315 * The PDF 1.4 spec. does not give the details of the math involved in the
316 * luminosity blending. All we are given is:
317 * "Creates a color with the luminance of the source color and the hue
318 * and saturation of the backdrop color. This produces an inverse
319 * effect to that of the Color mode."
320 * From section 7.4 of the PDF 1.5 specification, which is duscussing soft
321 * masks, we are given that, for CMYK, the luminosity is:
322 * Y = 0.30 (1 - C)(1 - K) + 0.59 (1 - M)(1 - K) + 0.11 (1 - Y)(1 - K)
323 * However the results of this equation do not match the results seen from
324 * Illustrator CS. Very different results are obtained if process gray
325 * (.5, .5, .5, 0) is blended over pure cyan, versus gray (0, 0, 0, .5) over
326 * the same pure cyan. The first gives a medium cyan while the later gives a
327 * medium gray. This routine seems to match Illustrator's actions. C, M and Y
328 * are treated similar to RGB in the previous routine and black is treated
329 * separately.
330 *
331 * Our component values have already been complemented, i.e. (1 - X).
332 */
333 void
art_blend_luminosity_cmyk_8(int n_chan,byte * dst,const byte * backdrop,const byte * src)334 art_blend_luminosity_cmyk_8(int n_chan, byte *dst, const byte *backdrop,
335 const byte *src)
336 {
337 int i;
338
339 /* Treat CMY the same as RGB. */
340 art_blend_luminosity_rgb_8(3, dst, backdrop, src);
341 for (i = 3; i < n_chan; i++)
342 dst[i] = src[i];
343 }
344
345 void
art_blend_saturation_rgb_8(int n_chan,byte * dst,const byte * backdrop,const byte * src)346 art_blend_saturation_rgb_8(int n_chan, byte *dst, const byte *backdrop,
347 const byte *src)
348 {
349 int rb = backdrop[0], gb = backdrop[1], bb = backdrop[2];
350 int rs = src[0], gs = src[1], bs = src[2];
351 int minb, maxb;
352 int mins, maxs;
353 int y;
354 int scale;
355 int r, g, b;
356
357 minb = rb < gb ? rb : gb;
358 minb = minb < bb ? minb : bb;
359 maxb = rb > gb ? rb : gb;
360 maxb = maxb > bb ? maxb : bb;
361 if (minb == maxb) {
362 /* backdrop has zero saturation, avoid divide by 0 */
363 dst[0] = gb;
364 dst[1] = gb;
365 dst[2] = gb;
366 return;
367 }
368
369 mins = rs < gs ? rs : gs;
370 mins = mins < bs ? mins : bs;
371 maxs = rs > gs ? rs : gs;
372 maxs = maxs > bs ? maxs : bs;
373
374 scale = ((maxs - mins) << 16) / (maxb - minb);
375 y = (rb * 77 + gb * 151 + bb * 28 + 0x80) >> 8;
376 r = y + ((((rb - y) * scale) + 0x8000) >> 16);
377 g = y + ((((gb - y) * scale) + 0x8000) >> 16);
378 b = y + ((((bb - y) * scale) + 0x8000) >> 16);
379
380 if ((r | g | b) & 0x100) {
381 int scalemin, scalemax;
382 int min, max;
383
384 min = r < g ? r : g;
385 min = min < b ? min : b;
386 max = r > g ? r : g;
387 max = max > b ? max : b;
388
389 if (min < 0)
390 scalemin = (y << 16) / (y - min);
391 else
392 scalemin = 0x10000;
393
394 if (max > 255)
395 scalemax = ((255 - y) << 16) / (max - y);
396 else
397 scalemax = 0x10000;
398
399 scale = scalemin < scalemax ? scalemin : scalemax;
400 r = y + (((r - y) * scale + 0x8000) >> 16);
401 g = y + (((g - y) * scale + 0x8000) >> 16);
402 b = y + (((b - y) * scale + 0x8000) >> 16);
403 }
404
405 dst[0] = r;
406 dst[1] = g;
407 dst[2] = b;
408 }
409
410 void
art_blend_saturation_custom_8(int n_chan,byte * dst,const byte * backdrop,const byte * src)411 art_blend_saturation_custom_8(int n_chan, byte *dst, const byte *backdrop,
412 const byte *src)
413 {
414 int minb, maxb;
415 int mins, maxs;
416 int y;
417 int scale;
418 int r[ART_MAX_CHAN];
419 int test = 0;
420 int temp, i;
421
422 /* Determine min and max of the backdrop */
423 minb = maxb = temp = backdrop[0];
424 for (i = 1; i < n_chan; i++) {
425 temp = backdrop[i];
426 minb = min(minb, temp);
427 maxb = max(maxb, temp);
428 }
429
430 if (minb == maxb) {
431 /* backdrop has zero saturation, avoid divide by 0 */
432 for (i = 0; i < n_chan; i++)
433 dst[i] = temp;
434 return;
435 }
436
437 /* Determine min and max of the source */
438 mins = maxs = src[0];
439 for (i = 1; i < n_chan; i++) {
440 temp = src[i];
441 mins = min(minb, temp);
442 maxs = max(minb, temp);
443 }
444
445 scale = ((maxs - mins) << 16) / (maxb - minb);
446
447 /* Assume that the saturation is simply the average of the backdrop. */
448 y = backdrop[0];
449 for (i = 1; i < n_chan; i++)
450 y += backdrop[i];
451 y = (y + n_chan / 2) / n_chan;
452
453 /* Calculate the saturated values */
454 for (i = 0; i < n_chan; i++) {
455 r[i] = y + ((((backdrop[i] - y) * scale) + 0x8000) >> 16);
456 test |= r[i];
457 }
458
459 if (test & 0x100) {
460 int scalemin, scalemax;
461 int min, max;
462
463 /* Determine min and max of our blended values */
464 min = max = temp = r[0];
465 for (i = 1; i < n_chan; i++) {
466 temp = src[i];
467 min = min(min, temp);
468 max = max(max, temp);
469 }
470
471 if (min < 0)
472 scalemin = (y << 16) / (y - min);
473 else
474 scalemin = 0x10000;
475
476 if (max > 255)
477 scalemax = ((255 - y) << 16) / (max - y);
478 else
479 scalemax = 0x10000;
480
481 scale = scalemin < scalemax ? scalemin : scalemax;
482 for (i = 0; i < n_chan; i++)
483 r[i] = y + (((r[i] - y) * scale + 0x8000) >> 16);
484 }
485
486 for (i = 0; i < n_chan; i++)
487 dst[i] = r[i];
488 }
489
490 /* Our component values have already been complemented, i.e. (1 - X). */
491 void
art_blend_saturation_cmyk_8(int n_chan,byte * dst,const byte * backdrop,const byte * src)492 art_blend_saturation_cmyk_8(int n_chan, byte *dst, const byte *backdrop,
493 const byte *src)
494 {
495 int i;
496
497 /* Treat CMY the same as RGB */
498 art_blend_saturation_rgb_8(3, dst, backdrop, src);
499 for (i = 3; i < n_chan; i++)
500 dst[i] = backdrop[i];
501 }
502
503 /* This array consists of floor ((x - x * x / 255.0) * 65536 / 255 +
504 0.5) for x in [0..255]. */
505 const unsigned int art_blend_sq_diff_8[256] = {
506 0, 256, 510, 762, 1012, 1260, 1506, 1750, 1992, 2231, 2469, 2705,
507 2939, 3171, 3401, 3628, 3854, 4078, 4300, 4519, 4737, 4953, 5166,
508 5378, 5588, 5795, 6001, 6204, 6406, 6606, 6803, 6999, 7192, 7384,
509 7573, 7761, 7946, 8129, 8311, 8490, 8668, 8843, 9016, 9188, 9357,
510 9524, 9690, 9853, 10014, 10173, 10331, 10486, 10639, 10790, 10939,
511 11086, 11232, 11375, 11516, 11655, 11792, 11927, 12060, 12191, 12320,
512 12447, 12572, 12695, 12816, 12935, 13052, 13167, 13280, 13390, 13499,
513 13606, 13711, 13814, 13914, 14013, 14110, 14205, 14297, 14388, 14477,
514 14564, 14648, 14731, 14811, 14890, 14967, 15041, 15114, 15184, 15253,
515 15319, 15384, 15446, 15507, 15565, 15622, 15676, 15729, 15779, 15827,
516 15874, 15918, 15960, 16001, 16039, 16075, 16110, 16142, 16172, 16200,
517 16227, 16251, 16273, 16293, 16311, 16327, 16341, 16354, 16364, 16372,
518 16378, 16382, 16384, 16384, 16382, 16378, 16372, 16364, 16354, 16341,
519 16327, 16311, 16293, 16273, 16251, 16227, 16200, 16172, 16142, 16110,
520 16075, 16039, 16001, 15960, 15918, 15874, 15827, 15779, 15729, 15676,
521 15622, 15565, 15507, 15446, 15384, 15319, 15253, 15184, 15114, 15041,
522 14967, 14890, 14811, 14731, 14648, 14564, 14477, 14388, 14297, 14205,
523 14110, 14013, 13914, 13814, 13711, 13606, 13499, 13390, 13280, 13167,
524 13052, 12935, 12816, 12695, 12572, 12447, 12320, 12191, 12060, 11927,
525 11792, 11655, 11516, 11375, 11232, 11086, 10939, 10790, 10639, 10486,
526 10331, 10173, 10014, 9853, 9690, 9524, 9357, 9188, 9016, 8843, 8668,
527 8490, 8311, 8129, 7946, 7761, 7573, 7384, 7192, 6999, 6803, 6606,
528 6406, 6204, 6001, 5795, 5588, 5378, 5166, 4953, 4737, 4519, 4300,
529 4078, 3854, 3628, 3401, 3171, 2939, 2705, 2469, 2231, 1992, 1750,
530 1506, 1260, 1012, 762, 510, 256, 0
531 };
532
533 /* This array consists of SoftLight (x, 255) - x, for values of x in
534 the range [0..255] (normalized to [0..255 range). The original
535 values were directly sampled from Adobe Illustrator 9. I've fit a
536 quadratic spline to the SoftLight (x, 1) function as follows
537 (normalized to [0..1] range):
538
539 Anchor point (0, 0)
540 Control point (0.0755, 0.302)
541 Anchor point (0.18, 0.4245)
542 Control point (0.4263, 0.7131)
543 Anchor point (1, 1)
544
545 I don't believe this is _exactly_ the function that Adobe uses,
546 but it really should be close enough for all practical purposes. */
547 const byte art_blend_soft_light_8[256] = {
548 0, 3, 6, 9, 11, 14, 16, 19, 21, 23, 26, 28, 30, 32, 33, 35, 37, 39,
549 40, 42, 43, 45, 46, 47, 48, 49, 51, 52, 53, 53, 54, 55, 56, 57, 57,
550 58, 58, 59, 60, 60, 60, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, 63,
551 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
552 64, 64, 64, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, 62,
553 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 59, 59,
554 59, 59, 59, 58, 58, 58, 58, 57, 57, 57, 57, 56, 56, 56, 56, 55, 55,
555 55, 55, 54, 54, 54, 54, 53, 53, 53, 52, 52, 52, 51, 51, 51, 51, 50,
556 50, 50, 49, 49, 49, 48, 48, 48, 47, 47, 47, 46, 46, 46, 45, 45, 45,
557 44, 44, 43, 43, 43, 42, 42, 42, 41, 41, 40, 40, 40, 39, 39, 39, 38,
558 38, 37, 37, 37, 36, 36, 35, 35, 35, 34, 34, 33, 33, 33, 32, 32, 31,
559 31, 31, 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, 26, 25, 25, 25, 24,
560 24, 23, 23, 22, 22, 21, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16,
561 16, 15, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7,
562 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0
563 };
564
565 void
art_blend_pixel_8(byte * dst,const byte * backdrop,const byte * src,int n_chan,gs_blend_mode_t blend_mode,const pdf14_nonseparable_blending_procs_t * pblend_procs)566 art_blend_pixel_8(byte *dst, const byte *backdrop,
567 const byte *src, int n_chan, gs_blend_mode_t blend_mode,
568 const pdf14_nonseparable_blending_procs_t * pblend_procs)
569 {
570 int i;
571 byte b, s;
572 bits32 t;
573
574 switch (blend_mode) {
575 case BLEND_MODE_Normal:
576 case BLEND_MODE_Compatible: /* todo */
577 memcpy(dst, src, n_chan);
578 break;
579 case BLEND_MODE_Multiply:
580 for (i = 0; i < n_chan; i++) {
581 t = ((bits32) backdrop[i]) * ((bits32) src[i]);
582 t += 0x80;
583 t += (t >> 8);
584 dst[i] = t >> 8;
585 }
586 break;
587 case BLEND_MODE_Screen:
588 for (i = 0; i < n_chan; i++) {
589 t =
590 ((bits32) (0xff - backdrop[i])) *
591 ((bits32) (0xff - src[i]));
592 t += 0x80;
593 t += (t >> 8);
594 dst[i] = 0xff - (t >> 8);
595 }
596 break;
597 case BLEND_MODE_Overlay:
598 for (i = 0; i < n_chan; i++) {
599 b = backdrop[i];
600 s = src[i];
601 if (b < 0x80)
602 t = 2 * ((bits32) b) * ((bits32) s);
603 else
604 t = 0xfe01 -
605 2 * ((bits32) (0xff - b)) * ((bits32) (0xff - s));
606 t += 0x80;
607 t += (t >> 8);
608 dst[i] = t >> 8;
609 }
610 break;
611 case BLEND_MODE_SoftLight:
612 for (i = 0; i < n_chan; i++) {
613 b = backdrop[i];
614 s = src[i];
615 if (s < 0x80) {
616 t = (0xff - (s << 1)) * art_blend_sq_diff_8[b];
617 t += 0x8000;
618 dst[i] = b - (t >> 16);
619 } else {
620 t =
621 ((s << 1) -
622 0xff) * ((bits32) (art_blend_soft_light_8[b]));
623 t += 0x80;
624 t += (t >> 8);
625 dst[i] = b + (t >> 8);
626 }
627 }
628 break;
629 case BLEND_MODE_HardLight:
630 for (i = 0; i < n_chan; i++) {
631 b = backdrop[i];
632 s = src[i];
633 if (s < 0x80)
634 t = 2 * ((bits32) b) * ((bits32) s);
635 else
636 t = 0xfe01 -
637 2 * ((bits32) (0xff - b)) * ((bits32) (0xff - s));
638 t += 0x80;
639 t += (t >> 8);
640 dst[i] = t >> 8;
641 }
642 break;
643 case BLEND_MODE_ColorDodge:
644 for (i = 0; i < n_chan; i++) {
645 b = backdrop[i];
646 s = 0xff - src[i];
647 if (b == 0)
648 dst[i] = 0;
649 else if (b >= s)
650 dst[i] = 0xff;
651 else
652 dst[i] = (0x1fe * b + s) / (s << 1);
653 }
654 break;
655 case BLEND_MODE_ColorBurn:
656 for (i = 0; i < n_chan; i++) {
657 b = 0xff - backdrop[i];
658 s = src[i];
659 if (b == 0)
660 dst[i] = 0xff;
661 else if (b >= s)
662 dst[i] = 0;
663 else
664 dst[i] = 0xff - (0x1fe * b + s) / (s << 1);
665 }
666 break;
667 case BLEND_MODE_Darken:
668 for (i = 0; i < n_chan; i++) {
669 b = backdrop[i];
670 s = src[i];
671 dst[i] = b < s ? b : s;
672 }
673 break;
674 case BLEND_MODE_Lighten:
675 for (i = 0; i < n_chan; i++) {
676 b = backdrop[i];
677 s = src[i];
678 dst[i] = b > s ? b : s;
679 }
680 break;
681 case BLEND_MODE_Difference:
682 for (i = 0; i < n_chan; i++) {
683 art_s32 tmp;
684
685 tmp = ((art_s32) backdrop[i]) - ((art_s32) src[i]);
686 dst[i] = tmp < 0 ? -tmp : tmp;
687 }
688 break;
689 case BLEND_MODE_Exclusion:
690 for (i = 0; i < n_chan; i++) {
691 b = backdrop[i];
692 s = src[i];
693 t = ((bits32) (0xff - b)) * ((bits32) s) +
694 ((bits32) b) * ((bits32) (0xff - s));
695 t += 0x80;
696 t += (t >> 8);
697 dst[i] = t >> 8;
698 }
699 break;
700 case BLEND_MODE_Luminosity:
701 pblend_procs->blend_luminosity(n_chan, dst, backdrop, src);
702 break;
703 case BLEND_MODE_Color:
704 pblend_procs->blend_luminosity(n_chan, dst, src, backdrop);
705 break;
706 case BLEND_MODE_Saturation:
707 pblend_procs->blend_saturation(n_chan, dst, backdrop, src);
708 break;
709 case BLEND_MODE_Hue:
710 {
711 byte tmp[4];
712
713 pblend_procs->blend_luminosity(n_chan, tmp, src, backdrop);
714 pblend_procs->blend_saturation(n_chan, dst, tmp, backdrop);
715 }
716 break;
717 default:
718 dlprintf1("art_blend_pixel_8: blend mode %d not implemented\n",
719 blend_mode);
720 memcpy(dst, src, n_chan);
721 break;
722 }
723 }
724
725 void
art_blend_pixel(ArtPixMaxDepth * dst,const ArtPixMaxDepth * backdrop,const ArtPixMaxDepth * src,int n_chan,gs_blend_mode_t blend_mode)726 art_blend_pixel(ArtPixMaxDepth* dst, const ArtPixMaxDepth *backdrop,
727 const ArtPixMaxDepth* src, int n_chan,
728 gs_blend_mode_t blend_mode)
729 {
730 int i;
731 ArtPixMaxDepth b, s;
732 bits32 t;
733
734 switch (blend_mode) {
735 case BLEND_MODE_Normal:
736 case BLEND_MODE_Compatible: /* todo */
737 memcpy(dst, src, n_chan * sizeof(ArtPixMaxDepth));
738 break;
739 case BLEND_MODE_Multiply:
740 for (i = 0; i < n_chan; i++) {
741 t = ((bits32) backdrop[i]) * ((bits32) src[i]);
742 t += 0x8000;
743 t += (t >> 16);
744 dst[i] = t >> 16;
745 }
746 break;
747 case BLEND_MODE_Screen:
748 for (i = 0; i < n_chan; i++) {
749 t =
750 ((bits32) (0xffff - backdrop[i])) *
751 ((bits32) (0xffff - src[i]));
752 t += 0x8000;
753 t += (t >> 16);
754 dst[i] = 0xffff - (t >> 16);
755 }
756 break;
757 case BLEND_MODE_Overlay:
758 for (i = 0; i < n_chan; i++) {
759 b = backdrop[i];
760 s = src[i];
761 if (b < 0x8000)
762 t = 2 * ((bits32) b) * ((bits32) s);
763 else
764 t = 0xfffe0001u -
765 2 * ((bits32) (0xffff - b)) * ((bits32) (0xffff - s));
766 t += 0x8000;
767 t += (t >> 16);
768 dst[i] = t >> 16;
769 }
770 break;
771 case BLEND_MODE_HardLight:
772 for (i = 0; i < n_chan; i++) {
773 b = backdrop[i];
774 s = src[i];
775 if (s < 0x8000)
776 t = 2 * ((bits32) b) * ((bits32) s);
777 else
778 t = 0xfffe0001u -
779 2 * ((bits32) (0xffff - b)) * ((bits32) (0xffff - s));
780 t += 0x8000;
781 t += (t >> 16);
782 dst[i] = t >> 16;
783 }
784 break;
785 case BLEND_MODE_ColorDodge:
786 for (i = 0; i < n_chan; i++) {
787 b = backdrop[i];
788 s = src[i];
789 if (b == 0)
790 dst[i] = 0;
791 else if (s >= b)
792 dst[i] = 0xffff;
793 else
794 dst[i] = (0x1fffe * s + b) / (b << 1);
795 }
796 break;
797 case BLEND_MODE_ColorBurn:
798 for (i = 0; i < n_chan; i++) {
799 b = 0xffff - backdrop[i];
800 s = src[i];
801 if (b == 0)
802 dst[i] = 0xffff;
803 else if (b >= s)
804 dst[i] = 0;
805 else
806 dst[i] = 0xffff - (0x1fffe * b + s) / (s << 1);
807 }
808 break;
809 case BLEND_MODE_Darken:
810 for (i = 0; i < n_chan; i++) {
811 b = backdrop[i];
812 s = src[i];
813 dst[i] = b < s ? b : s;
814 }
815 break;
816 case BLEND_MODE_Lighten:
817 for (i = 0; i < n_chan; i++) {
818 b = backdrop[i];
819 s = src[i];
820 dst[i] = b > s ? b : s;
821 }
822 break;
823 case BLEND_MODE_Difference:
824 for (i = 0; i < n_chan; i++) {
825 art_s32 tmp;
826
827 tmp = ((art_s32) backdrop[i]) - ((art_s32) src[i]);
828 dst[i] = tmp < 0 ? -tmp : tmp;
829 }
830 break;
831 case BLEND_MODE_Exclusion:
832 for (i = 0; i < n_chan; i++) {
833 b = backdrop[i];
834 s = src[i];
835 t = ((bits32) (0xffff - b)) * ((bits32) s) +
836 ((bits32) b) * ((bits32) (0xffff - s));
837 t += 0x8000;
838 t += (t >> 16);
839 dst[i] = t >> 16;
840 }
841 break;
842 default:
843 dlprintf1("art_blend_pixel: blend mode %d not implemented\n",
844 blend_mode);
845 memcpy(dst, src, n_chan);
846 break;
847 }
848 }
849
850 byte
art_pdf_union_8(byte alpha1,byte alpha2)851 art_pdf_union_8(byte alpha1, byte alpha2)
852 {
853 int tmp;
854
855 tmp = (0xff - alpha1) * (0xff - alpha2) + 0x80;
856 return 0xff - ((tmp + (tmp >> 8)) >> 8);
857 }
858
859 byte
art_pdf_union_mul_8(byte alpha1,byte alpha2,byte alpha_mask)860 art_pdf_union_mul_8(byte alpha1, byte alpha2, byte alpha_mask)
861 {
862 int tmp;
863
864 if (alpha_mask == 0xff) {
865 tmp = (0xff - alpha1) * (0xff - alpha2) + 0x80;
866 return 0xff - ((tmp + (tmp >> 8)) >> 8);
867 } else {
868 tmp = alpha2 * alpha_mask + 0x80;
869 tmp = (tmp + (tmp >> 8)) >> 8;
870 tmp = (0xff - alpha1) * (0xff - tmp) + 0x80;
871 return 0xff - ((tmp + (tmp >> 8)) >> 8);
872 }
873 }
874
875 void
art_pdf_composite_pixel_alpha_8(byte * dst,const byte * src,int n_chan,gs_blend_mode_t blend_mode,const pdf14_nonseparable_blending_procs_t * pblend_procs)876 art_pdf_composite_pixel_alpha_8(byte *dst, const byte *src, int n_chan,
877 gs_blend_mode_t blend_mode,
878 const pdf14_nonseparable_blending_procs_t * pblend_procs)
879 {
880 byte a_b, a_s;
881 unsigned int a_r;
882 int tmp;
883 int src_scale;
884 int c_b, c_s;
885 int i;
886
887 a_s = src[n_chan];
888 if (a_s == 0) {
889 /* source alpha is zero, avoid all computations and possible
890 divide by zero errors. */
891 return;
892 }
893
894 a_b = dst[n_chan];
895 if (a_b == 0) {
896 /* backdrop alpha is zero, just copy source pixels and avoid
897 computation. */
898
899 /* this idiom is faster than memcpy (dst, src, n_chan + 1); for
900 expected small values of n_chan. */
901 for (i = 0; i <= n_chan >> 2; i++) {
902 ((bits32 *) dst)[i] = ((const bits32 *)src)[i];
903 }
904
905 return;
906 }
907
908 /* Result alpha is Union of backdrop and source alpha */
909 tmp = (0xff - a_b) * (0xff - a_s) + 0x80;
910 a_r = 0xff - (((tmp >> 8) + tmp) >> 8);
911 /* todo: verify that a_r is nonzero in all cases */
912
913 /* Compute a_s / a_r in 16.16 format */
914 src_scale = ((a_s << 16) + (a_r >> 1)) / a_r;
915
916 if (blend_mode == BLEND_MODE_Normal) {
917 /* Do simple compositing of source over backdrop */
918 for (i = 0; i < n_chan; i++) {
919 c_s = src[i];
920 c_b = dst[i];
921 tmp = (c_b << 16) + src_scale * (c_s - c_b) + 0x8000;
922 dst[i] = tmp >> 16;
923 }
924 } else {
925 /* Do compositing with blending */
926 byte blend[ART_MAX_CHAN];
927
928 art_blend_pixel_8(blend, dst, src, n_chan, blend_mode, pblend_procs);
929 for (i = 0; i < n_chan; i++) {
930 int c_bl; /* Result of blend function */
931 int c_mix; /* Blend result mixed with source color */
932
933 c_s = src[i];
934 c_b = dst[i];
935 c_bl = blend[i];
936 tmp = a_b * (c_bl - ((int)c_s)) + 0x80;
937 c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
938 tmp = (c_b << 16) + src_scale * (c_mix - c_b) + 0x8000;
939 dst[i] = tmp >> 16;
940 }
941 }
942 dst[n_chan] = a_r;
943 }
944
945 #if 0
946 /**
947 * art_pdf_composite_pixel_knockout_8: Composite two pixels with knockout.
948 * @dst: Where to store resulting pixel, also immediate backdrop.
949 * @backdrop: Initial backdrop color.
950 * @src: Source pixel color.
951 * @n_chan: Number of channels.
952 * @blend_mode: Blend mode.
953 *
954 * Composites two pixels using the compositing operation specialized
955 * for knockout groups (Section 5.5). A few things to keep in mind:
956 *
957 * 1. This is a reference implementation, not a high-performance one.
958 *
959 * 2. All pixels are assumed to have a single alpha channel.
960 *
961 * 3. Zero is black, one is white.
962 *
963 * Also note that src and dst are expected to be allocated aligned to
964 * 32 bit boundaries, ie bytes from [0] to [(n_chan + 3) & -4] may
965 * be accessed.
966 *
967 * All pixel values have both alpha and shape channels, ie with those
968 * included the total number of channels is @n_chan + 2.
969 *
970 * An invariant: shape >= alpha.
971 **/
972 void
973 art_pdf_composite_pixel_knockout_8(byte *dst,
974 const byte *backdrop, const byte *src,
975 int n_chan, gs_blend_mode_t blend_mode)
976 {
977 int i;
978 byte ct[ART_MAX_CHAN + 1];
979 byte src_shape;
980 byte backdrop_alpha;
981 byte dst_alpha;
982 bits32 src_opacity;
983 bits32 backdrop_weight, t_weight;
984 int tmp;
985
986 if (src[n_chan] == 0)
987 return;
988 if (src[n_chan + 1] == 255 && blend_mode == BLEND_MODE_Normal ||
989 dst[n_chan] == 0) {
990 /* this idiom is faster than memcpy (dst, src, n_chan + 2); for
991 expected small values of n_chan. */
992 for (i = 0; i <= (n_chan + 1) >> 2; i++) {
993 ((bits32 *) dst)[i] = ((const bits32 *)src[i]);
994 }
995
996 return;
997 }
998
999
1000 src_shape = src[n_chan + 1]; /* $fs_i$ */
1001 src_opacity = (255 * src[n_chan] + 0x80) / src_shape; /* $qs_i$ */
1002 #if 0
1003 for (i = 0; i < (n_chan + 3) >> 2; i++) {
1004 ((bits32 *) src_tmp)[i] = ((const bits32 *)src[i]);
1005 }
1006 src_tmp[n_chan] = src_opacity;
1007
1008 for (i = 0; i <= n_chan >> 2; i++) {
1009 ((bits32 *) tmp)[i] = ((bits32 *) backdrop[i]);
1010 }
1011 #endif
1012
1013 backdrop_scale = if (blend_mode == BLEND_MODE_Normal) {
1014 /* Do simple compositing of source over backdrop */
1015 for (i = 0; i < n_chan; i++) {
1016 c_s = src[i];
1017 c_b = dst[i];
1018 tmp = (c_b << 16) + ct_scale * (c_s - c_b) + 0x8000;
1019 ct[i] = tmp >> 16;
1020 }
1021 } else {
1022 /* Do compositing with blending */
1023 byte blend[ART_MAX_CHAN];
1024
1025 art_blend_pixel_8(blend, backdrop, src, n_chan, blend_mode, pblend_procs);
1026 for (i = 0; i < n_chan; i++) {
1027 int c_bl; /* Result of blend function */
1028 int c_mix; /* Blend result mixed with source color */
1029
1030 c_s = src[i];
1031 c_b = dst[i];
1032 c_bl = blend[i];
1033 tmp = a_b * (((int)c_bl) - ((int)c_s)) + 0x80;
1034 c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
1035 tmp = (c_b << 16) + ct_scale * (c_mix - c_b) + 0x8000;
1036 ct[i] = tmp >> 16;
1037 }
1038 }
1039
1040 /* do weighted average of $Ct$ using relative alpha contribution as weight */
1041 backdrop_alpha = backdrop[n_chan];
1042 tmp = (0xff - blend_alpha) * (0xff - backdrop_alpha) + 0x80;
1043 dst_alpha = 0xff - (((tmp >> 8) + tmp) >> 8);
1044 dst[n_chan] = dst_alpha;
1045 t_weight = ((blend_alpha << 16) + 0x8000) / dst_alpha;
1046 for (i = 0; i < n_chan; i++) {
1047
1048 }
1049 }
1050 #endif
1051
1052 void
art_pdf_uncomposite_group_8(byte * dst,const byte * backdrop,const byte * src,byte src_alpha_g,int n_chan)1053 art_pdf_uncomposite_group_8(byte *dst,
1054 const byte *backdrop,
1055 const byte *src, byte src_alpha_g, int n_chan)
1056 {
1057 byte backdrop_alpha = backdrop[n_chan];
1058 int i;
1059 int tmp;
1060 int scale;
1061
1062 dst[n_chan] = src_alpha_g;
1063
1064 if (src_alpha_g == 0)
1065 return;
1066
1067 scale = (backdrop_alpha * 255 * 2 + src_alpha_g) / (src_alpha_g << 1) -
1068 backdrop_alpha;
1069 for (i = 0; i < n_chan; i++) {
1070 int si, di;
1071
1072 si = src[i];
1073 di = backdrop[i];
1074 tmp = (si - di) * scale + 0x80;
1075 tmp = si + ((tmp + (tmp >> 8)) >> 8);
1076
1077 /* todo: it should be possible to optimize these cond branches */
1078 if (tmp < 0)
1079 tmp = 0;
1080 if (tmp > 255)
1081 tmp = 255;
1082 dst[i] = tmp;
1083 }
1084
1085 }
1086
1087 void
art_pdf_recomposite_group_8(byte * dst,byte * dst_alpha_g,const byte * src,byte src_alpha_g,int n_chan,byte alpha,gs_blend_mode_t blend_mode,const pdf14_nonseparable_blending_procs_t * pblend_procs)1088 art_pdf_recomposite_group_8(byte *dst, byte *dst_alpha_g,
1089 const byte *src, byte src_alpha_g, int n_chan,
1090 byte alpha, gs_blend_mode_t blend_mode,
1091 const pdf14_nonseparable_blending_procs_t * pblend_procs)
1092 {
1093 byte dst_alpha;
1094 int i;
1095 int tmp;
1096 int scale;
1097
1098 if (src_alpha_g == 0)
1099 return;
1100
1101 if (blend_mode == BLEND_MODE_Normal && alpha == 255) {
1102 /* In this case, uncompositing and recompositing cancel each
1103 other out. Note: if the reason that alpha == 255 is that
1104 there is no constant mask and no soft mask, then this
1105 operation should be optimized away at a higher level. */
1106 for (i = 0; i <= n_chan >> 2; i++)
1107 ((bits32 *) dst)[i] = ((const bits32 *)src)[i];
1108 if (dst_alpha_g != NULL) {
1109 tmp = (255 - *dst_alpha_g) * (255 - src_alpha_g) + 0x80;
1110 *dst_alpha_g = 255 - ((tmp + (tmp >> 8)) >> 8);
1111 }
1112 return;
1113 } else {
1114 /* "interesting" blend mode */
1115 byte ca[ART_MAX_CHAN + 1]; /* $C, \alpha$ */
1116
1117 dst_alpha = dst[n_chan];
1118 if (src_alpha_g == 255 || dst_alpha == 0) {
1119 for (i = 0; i < (n_chan + 3) >> 2; i++)
1120 ((bits32 *) ca)[i] = ((const bits32 *)src)[i];
1121 } else {
1122 /* Uncomposite the color. In other words, solve
1123 "src = (ca, src_alpha_g) over dst" for ca */
1124
1125 /* todo (maybe?): replace this code with call to
1126 art_pdf_uncomposite_group_8() to reduce code
1127 duplication. */
1128
1129 scale = (dst_alpha * 255 * 2 + src_alpha_g) / (src_alpha_g << 1) -
1130 dst_alpha;
1131 for (i = 0; i < n_chan; i++) {
1132 int si, di;
1133
1134 si = src[i];
1135 di = dst[i];
1136 tmp = (si - di) * scale + 0x80;
1137 tmp = si + ((tmp + (tmp >> 8)) >> 8);
1138
1139 /* todo: it should be possible to optimize these cond branches */
1140 if (tmp < 0)
1141 tmp = 0;
1142 if (tmp > 255)
1143 tmp = 255;
1144 ca[i] = tmp;
1145 }
1146 }
1147
1148 tmp = src_alpha_g * alpha + 0x80;
1149 tmp = (tmp + (tmp >> 8)) >> 8;
1150 ca[n_chan] = tmp;
1151 if (dst_alpha_g != NULL) {
1152 tmp = (255 - *dst_alpha_g) * (255 - tmp) + 0x80;
1153 *dst_alpha_g = 255 - ((tmp + (tmp >> 8)) >> 8);
1154 }
1155 art_pdf_composite_pixel_alpha_8(dst, ca, n_chan,
1156 blend_mode, pblend_procs);
1157 }
1158 /* todo: optimize BLEND_MODE_Normal buf alpha != 255 case */
1159 }
1160
1161 void
art_pdf_composite_group_8(byte * dst,byte * dst_alpha_g,const byte * src,int n_chan,byte alpha,gs_blend_mode_t blend_mode,const pdf14_nonseparable_blending_procs_t * pblend_procs)1162 art_pdf_composite_group_8(byte *dst, byte *dst_alpha_g,
1163 const byte *src, int n_chan, byte alpha, gs_blend_mode_t blend_mode,
1164 const pdf14_nonseparable_blending_procs_t * pblend_procs)
1165 {
1166 byte src_alpha; /* $\alpha g_n$ */
1167 byte src_tmp[ART_MAX_CHAN + 1];
1168 int i;
1169 int tmp;
1170
1171 if (alpha == 255) {
1172 art_pdf_composite_pixel_alpha_8(dst, src, n_chan,
1173 blend_mode, pblend_procs);
1174 if (dst_alpha_g != NULL) {
1175 tmp = (255 - *dst_alpha_g) * (255 - src[n_chan]) + 0x80;
1176 *dst_alpha_g = 255 - ((tmp + (tmp >> 8)) >> 8);
1177 }
1178 } else {
1179 src_alpha = src[n_chan];
1180 if (src_alpha == 0)
1181 return;
1182 for (i = 0; i < (n_chan + 3) >> 2; i++)
1183 ((bits32 *) src_tmp)[i] = ((const bits32 *)src)[i];
1184 tmp = src_alpha * alpha + 0x80;
1185 src_tmp[n_chan] = (tmp + (tmp >> 8)) >> 8;
1186 art_pdf_composite_pixel_alpha_8(dst, src_tmp, n_chan,
1187 blend_mode, pblend_procs);
1188 if (dst_alpha_g != NULL) {
1189 tmp = (255 - *dst_alpha_g) * (255 - src_tmp[n_chan]) + 0x80;
1190 *dst_alpha_g = 255 - ((tmp + (tmp >> 8)) >> 8);
1191 }
1192 }
1193 }
1194
1195 void
art_pdf_composite_knockout_simple_8(byte * dst,byte * dst_shape,const byte * src,int n_chan,byte opacity)1196 art_pdf_composite_knockout_simple_8(byte *dst,
1197 byte *dst_shape,
1198 const byte *src,
1199 int n_chan, byte opacity)
1200 {
1201 byte src_shape = src[n_chan];
1202 int i;
1203
1204 if (src_shape == 0)
1205 return;
1206 else if (src_shape == 255) {
1207 for (i = 0; i < (n_chan + 3) >> 2; i++)
1208 ((bits32 *) dst)[i] = ((const bits32 *)src)[i];
1209 dst[n_chan] = opacity;
1210 if (dst_shape != NULL)
1211 *dst_shape = 255;
1212 } else {
1213 /* Use src_shape to interpolate (in premultiplied alpha space)
1214 between dst and (src, opacity). */
1215 int dst_alpha = dst[n_chan];
1216 byte result_alpha;
1217 int tmp;
1218
1219 tmp = (opacity - dst_alpha) * src_shape + 0x80;
1220 result_alpha = dst_alpha + ((tmp + (tmp >> 8)) >> 8);
1221
1222 if (result_alpha != 0)
1223 for (i = 0; i < n_chan; i++) {
1224 /* todo: optimize this - can strength-reduce so that
1225 inner loop is a single interpolation */
1226 tmp = dst[i] * dst_alpha * (255 - src_shape) +
1227 ((int)src[i]) * opacity * src_shape + (result_alpha << 7);
1228 dst[i] = tmp / (result_alpha * 255);
1229 }
1230 dst[n_chan] = result_alpha;
1231
1232 /* union in dst_shape if non-null */
1233 if (dst_shape != NULL) {
1234 tmp = (255 - *dst_shape) * (255 - src_shape) + 0x80;
1235 *dst_shape = 255 - ((tmp + (tmp >> 8)) >> 8);
1236 }
1237 }
1238 }
1239
1240 void
art_pdf_composite_knockout_isolated_8(byte * dst,byte * dst_shape,const byte * src,int n_chan,byte shape,byte alpha_mask,byte shape_mask)1241 art_pdf_composite_knockout_isolated_8(byte *dst,
1242 byte *dst_shape,
1243 const byte *src,
1244 int n_chan,
1245 byte shape,
1246 byte alpha_mask, byte shape_mask)
1247 {
1248 int tmp;
1249 int i;
1250
1251 if (shape == 0)
1252 return;
1253 else if ((shape & shape_mask) == 255) {
1254 for (i = 0; i < (n_chan + 3) >> 2; i++)
1255 ((bits32 *) dst)[i] = ((const bits32 *)src)[i];
1256 tmp = src[n_chan] * alpha_mask + 0x80;
1257 dst[n_chan] = (tmp + (tmp >> 8)) >> 8;
1258 if (dst_shape != NULL)
1259 *dst_shape = 255;
1260 } else {
1261 /* Use src_shape to interpolate (in premultiplied alpha space)
1262 between dst and (src, opacity). */
1263 byte src_shape, src_alpha;
1264 int dst_alpha = dst[n_chan];
1265 byte result_alpha;
1266 int tmp;
1267
1268 tmp = shape * shape_mask + 0x80;
1269 src_shape = (tmp + (tmp >> 8)) >> 8;
1270
1271 tmp = src[n_chan] * alpha_mask + 0x80;
1272 src_alpha = (tmp + (tmp >> 8)) >> 8;
1273
1274 tmp = (src_alpha - dst_alpha) * src_shape + 0x80;
1275 result_alpha = dst_alpha + ((tmp + (tmp >> 8)) >> 8);
1276
1277 if (result_alpha != 0)
1278 for (i = 0; i < n_chan; i++) {
1279 /* todo: optimize this - can strength-reduce so that
1280 inner loop is a single interpolation */
1281 tmp = dst[i] * dst_alpha * (255 - src_shape) +
1282 ((int)src[i]) * src_alpha * src_shape +
1283 (result_alpha << 7);
1284 dst[i] = tmp / (result_alpha * 255);
1285 }
1286 dst[n_chan] = result_alpha;
1287
1288 /* union in dst_shape if non-null */
1289 if (dst_shape != NULL) {
1290 tmp = (255 - *dst_shape) * (255 - src_shape) + 0x80;
1291 *dst_shape = 255 - ((tmp + (tmp >> 8)) >> 8);
1292 }
1293 }
1294 }
1295
1296 void
art_pdf_composite_knockout_8(byte * dst,byte * dst_alpha_g,const byte * backdrop,const byte * src,int n_chan,byte shape,byte alpha_mask,byte shape_mask,gs_blend_mode_t blend_mode,const pdf14_nonseparable_blending_procs_t * pblend_procs)1297 art_pdf_composite_knockout_8(byte *dst,
1298 byte *dst_alpha_g, const byte *backdrop, const byte *src,
1299 int n_chan, byte shape, byte alpha_mask,
1300 byte shape_mask, gs_blend_mode_t blend_mode,
1301 const pdf14_nonseparable_blending_procs_t * pblend_procs)
1302 {
1303 /* This implementation follows the Adobe spec pretty closely, rather
1304 than trying to do anything clever. For example, in the case of a
1305 Normal blend_mode when the top group is non-isolated, uncompositing
1306 and recompositing is more work than needed. So be it. Right now,
1307 I'm more worried about manageability than raw performance. */
1308 byte alpha_t;
1309 byte src_alpha, src_shape;
1310 byte src_opacity;
1311 byte ct[ART_MAX_CHAN];
1312 byte backdrop_alpha;
1313 byte alpha_g_i_1, alpha_g_i, alpha_i;
1314 int tmp;
1315 int i;
1316 int scale_b;
1317 int scale_src;
1318
1319 if (shape == 0 || shape_mask == 0)
1320 return;
1321
1322 tmp = shape * shape_mask + 0x80;
1323 /* $f s_i$ */
1324 src_shape = (tmp + (tmp >> 8)) >> 8;
1325
1326 tmp = src[n_chan] * alpha_mask + 0x80;
1327 src_alpha = (tmp + (tmp >> 8)) >> 8;
1328
1329 /* $q s_i$ */
1330 src_opacity = (src_alpha * 510 + src_shape) / (2 * src_shape);
1331
1332 /* $\alpha t$, \alpha g_b is always zero for knockout groups */
1333 alpha_t = src_opacity;
1334
1335 /* $\alpha b$ */
1336 backdrop_alpha = backdrop[n_chan];
1337
1338 tmp = (0xff - src_opacity) * backdrop_alpha;
1339 /* $(1 - q s_i) \cdot alpha_b$ scaled by 2^16 */
1340 scale_b = tmp + (tmp >> 7) + (tmp >> 14);
1341
1342 /* $q s_i$ scaled by 2^16 */
1343 scale_src = (src_opacity << 8) + (src_opacity) + (src_opacity >> 7);
1344
1345 /* Do simple compositing of source over backdrop */
1346 if (blend_mode == BLEND_MODE_Normal) {
1347 for (i = 0; i < n_chan; i++) {
1348 int c_s;
1349 int c_b;
1350
1351 c_s = src[i];
1352 c_b = backdrop[i];
1353 tmp = (c_b << 16) * scale_b + (c_s - c_b) + scale_src + 0x8000;
1354 ct[i] = tmp >> 16;
1355 }
1356 } else {
1357 byte blend[ART_MAX_CHAN];
1358
1359 art_blend_pixel_8(blend, backdrop, src, n_chan,
1360 blend_mode, pblend_procs);
1361 for (i = 0; i < n_chan; i++) {
1362 int c_s;
1363 int c_b;
1364 int c_bl; /* Result of blend function */
1365 int c_mix; /* Blend result mixed with source color */
1366
1367 c_s = src[i];
1368 c_b = backdrop[i];
1369 c_bl = blend[i];
1370 tmp = backdrop_alpha * (c_bl - ((int)c_s)) + 0x80;
1371 c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
1372 tmp = (c_b << 16) * scale_b + (c_mix - c_b) + scale_src + 0x8000;
1373 ct[i] = tmp >> 16;
1374 }
1375 }
1376
1377 /* $\alpha g_{i - 1}$ */
1378 alpha_g_i_1 = *dst_alpha_g;
1379
1380 tmp = src_shape * (((int)alpha_t) - alpha_g_i_1) + 0x80;
1381 /* $\alpha g_i$ */
1382 alpha_g_i = alpha_g_i_1 + ((tmp + (tmp >> 8)) >> 8);
1383
1384 tmp = (0xff - backdrop_alpha) * (0xff - alpha_g_i) + 0x80;
1385 /* $\alpha_i$ */
1386 alpha_i = 0xff - ((tmp + (tmp >> 8)) >> 8);
1387
1388 if (alpha_i > 0) {
1389 int scale_dst;
1390 int scale_t;
1391 byte dst_alpha;
1392
1393 /* $f s_i / \alpha_i$ scaled by 2^16 */
1394 scale_t = ((src_shape << 17) + alpha_i) / (2 * alpha_i);
1395
1396 /* $\alpha_{i - 1}$ */
1397 dst_alpha = dst[n_chan];
1398
1399 tmp = (1 - src_shape) * dst_alpha;
1400 tmp = (tmp << 9) + (tmp << 1) + (tmp >> 7) + alpha_i;
1401 scale_dst = tmp / (2 * alpha_i);
1402
1403 for (i = 0; i < n_chan; i++) {
1404 tmp = dst[i] * scale_dst + ct[i] * scale_t + 0x8000;
1405 /* todo: clamp? */
1406 dst[i] = tmp >> 16;
1407 }
1408 }
1409 dst[n_chan] = alpha_i;
1410 *dst_alpha_g = alpha_g_i;
1411 }
1412
1413 #if RAW_DUMP
1414
1415 /* Debug dump of buffer data from pdf14 device. Saved in
1416 planar form with global indexing and tag information in
1417 file name */
1418
1419 void
dump_raw_buffer(int num_rows,int width,int n_chan,int plane_stride,int rowstride,char filename[],byte * Buffer)1420 dump_raw_buffer(int num_rows, int width, int n_chan,
1421 int plane_stride, int rowstride,
1422 char filename[],byte *Buffer)
1423
1424 {
1425 char full_file_name[50];
1426 FILE *fid;
1427 int z,y;
1428 byte *buff_ptr;
1429 int max_bands;
1430
1431 /* clist_band_count is incremented at every pdf14putimage */
1432 /* Useful for catching this thing and only dumping */
1433 /* during a particular band if we have a large file */
1434 /* if (clist_band_count != 80) return; */
1435
1436 buff_ptr = Buffer;
1437
1438 max_bands = ( n_chan < 57 ? n_chan : 56); /* Photoshop handles at most 56 bands */
1439 sprintf(full_file_name,"%d)%s_%dx%dx%d.raw",global_index,filename,width,num_rows,max_bands);
1440 fid = fopen(full_file_name,"wb");
1441
1442 for (z = 0; z < max_bands; ++z) {
1443
1444 /* grab pointer to the next plane */
1445
1446 buff_ptr = &(Buffer[z*plane_stride]);
1447
1448 for ( y = 0; y < num_rows; y++ ) {
1449
1450 /* write out each row */
1451 fwrite(buff_ptr,sizeof(unsigned char),width,fid);
1452
1453 buff_ptr += rowstride;
1454
1455 }
1456
1457 }
1458
1459 fclose(fid);
1460
1461 }
1462
1463
1464 #endif
1465