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