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