Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
  Copyright (C) 2001 artofcode LLC.
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
  For more information about licensing, please refer to
12
  http://www.ghostscript.com/licensing/. For information on
13
  commercial licensing, go to http://www.artifex.com/licensing/ or
14
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
15
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
16
 
17
  Author: Raph Levien <raph@artofcode.com>
18
*/
19
/* $Id: gxblend.c,v 1.6 2004/08/18 04:48:56 dan Exp $ */
20
/* PDF 1.4 blending functions */
21
 
22
#include "memory_.h"
23
#include "gx.h"
24
#include "gstparam.h"
25
#include "gxblend.h"
26
 
27
typedef int art_s32;
28
 
29
static void
30
art_blend_luminosity_rgb_8(byte *dst, const byte *backdrop,
31
			   const byte *src)
32
{
33
    int rb = backdrop[0], gb = backdrop[1], bb = backdrop[2];
34
    int rs = src[0], gs = src[1], bs = src[2];
35
    int delta_y;
36
    int r, g, b;
37
 
38
    /*
39
     * From section 7.4 of the PDF 1.5 specification, for RGB, the luminosity
40
     * is:  Y = 0.30 R + 0.59 G + 0.11 B)
41
     */
42
    delta_y = ((rs - rb) * 77 + (gs - gb) * 151 + (bs - bb) * 28 + 0x80) >> 8;
43
    r = rb + delta_y;
44
    g = gb + delta_y;
45
    b = bb + delta_y;
46
    if ((r | g | b) & 0x100) {
47
	int y;
48
	int scale;
49
 
50
	y = (rs * 77 + gs * 151 + bs * 28 + 0x80) >> 8;
51
	if (delta_y > 0) {
52
	    int max;
53
 
54
	    max = r > g ? r : g;
55
	    max = b > max ? b : max;
56
	    scale = ((255 - y) << 16) / (max - y);
57
	} else {
58
	    int min;
59
 
60
	    min = r < g ? r : g;
61
	    min = b < min ? b : min;
62
	    scale = (y << 16) / (y - min);
63
	}
64
	r = y + (((r - y) * scale + 0x8000) >> 16);
65
	g = y + (((g - y) * scale + 0x8000) >> 16);
66
	b = y + (((b - y) * scale + 0x8000) >> 16);
67
    }
68
    dst[0] = r;
69
    dst[1] = g;
70
    dst[2] = b;
71
}
72
 
73
/*
74
 * The PDF 1.4 spec. does not give the details of the math involved in the
75
 * luminosity blending.  All we are given is:
76
 *   "Creates a color with the luminance of the source color and the hue
77
 *    and saturation of the backdrop color. This produces an inverse
78
 *    effect to that of the Color mode."
79
 * From section 7.4 of the PDF 1.5 specification, which is duscussing soft
80
 * masks, we are given that, for CMYK, the luminosity is:
81
 *    Y = 0.30 (1 - C)(1 - K) + 0.59 (1 - M)(1 - K) + 0.11 (1 - Y)(1 - K)
82
 * However the results of this equation do not match the results seen from
83
 * Illustrator CS.  Very different results are obtained if process gray
84
 * (.5, .5, .5, 0) is blended over pure cyan, versus gray (0, 0, 0, .5) over
85
 * the same pure cyan.  The first gives a medium cyan while the later gives a
86
 * medium gray.  This routine seems to match Illustrator's actions.  C, M and Y
87
 * are treated similar to RGB in the previous routine and black is treated
88
 * separately.
89
 *
90
 * Our component values have already been complemented, i.e. (1 - X).
91
 */
92
static void
93
art_blend_luminosity_cmyk_8(byte *dst, const byte *backdrop,
94
			   const byte *src)
95
{
96
    /* Treat CMY the same as RGB. */
97
    art_blend_luminosity_rgb_8(dst, backdrop, src);
98
    dst[3] = src[3];
99
}
100
 
101
static void
102
art_blend_saturation_rgb_8(byte *dst, const byte *backdrop,
103
			   const byte *src)
104
{
105
    int rb = backdrop[0], gb = backdrop[1], bb = backdrop[2];
106
    int rs = src[0], gs = src[1], bs = src[2];
107
    int minb, maxb;
108
    int mins, maxs;
109
    int y;
110
    int scale;
111
    int r, g, b;
112
 
113
    minb = rb < gb ? rb : gb;
114
    minb = minb < bb ? minb : bb;
115
    maxb = rb > gb ? rb : gb;
116
    maxb = maxb > bb ? maxb : bb;
117
    if (minb == maxb) {
118
	/* backdrop has zero saturation, avoid divide by 0 */
119
	dst[0] = gb;
120
	dst[1] = gb;
121
	dst[2] = gb;
122
	return;
123
    }
124
 
125
    mins = rs < gs ? rs : gs;
126
    mins = mins < bs ? mins : bs;
127
    maxs = rs > gs ? rs : gs;
128
    maxs = maxs > bs ? maxs : bs;
129
 
130
    scale = ((maxs - mins) << 16) / (maxb - minb);
131
    y = (rb * 77 + gb * 151 + bb * 28 + 0x80) >> 8;
132
    r = y + ((((rb - y) * scale) + 0x8000) >> 16);
133
    g = y + ((((gb - y) * scale) + 0x8000) >> 16);
134
    b = y + ((((bb - y) * scale) + 0x8000) >> 16);
135
 
136
    if ((r | g | b) & 0x100) {
137
	int scalemin, scalemax;
138
	int min, max;
139
 
140
	min = r < g ? r : g;
141
	min = min < b ? min : b;
142
	max = r > g ? r : g;
143
	max = max > b ? max : b;
144
 
145
	if (min < 0)
146
	    scalemin = (y << 16) / (y - min);
147
	else
148
	    scalemin = 0x10000;
149
 
150
	if (max > 255)
151
	    scalemax = ((255 - y) << 16) / (max - y);
152
	else
153
	    scalemax = 0x10000;
154
 
155
	scale = scalemin < scalemax ? scalemin : scalemax;
156
	r = y + (((r - y) * scale + 0x8000) >> 16);
157
	g = y + (((g - y) * scale + 0x8000) >> 16);
158
	b = y + (((b - y) * scale + 0x8000) >> 16);
159
    }
160
 
161
    dst[0] = r;
162
    dst[1] = g;
163
    dst[2] = b;
164
}
165
 
166
/* Our component values have already been complemented, i.e. (1 - X). */
167
static void
168
art_blend_saturation_cmyk_8(byte *dst, const byte *backdrop,
169
			   const byte *src)
170
{
171
    /* Treat CMY the same as RGB */
172
    art_blend_saturation_rgb_8(dst, backdrop, src);
173
    dst[3] = backdrop[3];
174
}
175
 
176
/* This array consists of floor ((x - x * x / 255.0) * 65536 / 255 +
177
   0.5) for x in [0..255]. */
178
const unsigned int art_blend_sq_diff_8[256] = {
179
    0, 256, 510, 762, 1012, 1260, 1506, 1750, 1992, 2231, 2469, 2705,
180
    2939, 3171, 3401, 3628, 3854, 4078, 4300, 4519, 4737, 4953, 5166,
181
    5378, 5588, 5795, 6001, 6204, 6406, 6606, 6803, 6999, 7192, 7384,
182
    7573, 7761, 7946, 8129, 8311, 8490, 8668, 8843, 9016, 9188, 9357,
183
    9524, 9690, 9853, 10014, 10173, 10331, 10486, 10639, 10790, 10939,
184
    11086, 11232, 11375, 11516, 11655, 11792, 11927, 12060, 12191, 12320,
185
    12447, 12572, 12695, 12816, 12935, 13052, 13167, 13280, 13390, 13499,
186
    13606, 13711, 13814, 13914, 14013, 14110, 14205, 14297, 14388, 14477,
187
    14564, 14648, 14731, 14811, 14890, 14967, 15041, 15114, 15184, 15253,
188
    15319, 15384, 15446, 15507, 15565, 15622, 15676, 15729, 15779, 15827,
189
    15874, 15918, 15960, 16001, 16039, 16075, 16110, 16142, 16172, 16200,
190
    16227, 16251, 16273, 16293, 16311, 16327, 16341, 16354, 16364, 16372,
191
    16378, 16382, 16384, 16384, 16382, 16378, 16372, 16364, 16354, 16341,
192
    16327, 16311, 16293, 16273, 16251, 16227, 16200, 16172, 16142, 16110,
193
    16075, 16039, 16001, 15960, 15918, 15874, 15827, 15779, 15729, 15676,
194
    15622, 15565, 15507, 15446, 15384, 15319, 15253, 15184, 15114, 15041,
195
    14967, 14890, 14811, 14731, 14648, 14564, 14477, 14388, 14297, 14205,
196
    14110, 14013, 13914, 13814, 13711, 13606, 13499, 13390, 13280, 13167,
197
    13052, 12935, 12816, 12695, 12572, 12447, 12320, 12191, 12060, 11927,
198
    11792, 11655, 11516, 11375, 11232, 11086, 10939, 10790, 10639, 10486,
199
    10331, 10173, 10014, 9853, 9690, 9524, 9357, 9188, 9016, 8843, 8668,
200
    8490, 8311, 8129, 7946, 7761, 7573, 7384, 7192, 6999, 6803, 6606,
201
    6406, 6204, 6001, 5795, 5588, 5378, 5166, 4953, 4737, 4519, 4300,
202
    4078, 3854, 3628, 3401, 3171, 2939, 2705, 2469, 2231, 1992, 1750,
203
    1506, 1260, 1012, 762, 510, 256, 0
204
};
205
 
206
/* This array consists of SoftLight (x, 255) - x, for values of x in
207
   the range [0..255] (normalized to [0..255 range). The original
208
   values were directly sampled from Adobe Illustrator 9. I've fit a
209
   quadratic spline to the SoftLight (x, 1) function as follows
210
   (normalized to [0..1] range):
211
 
212
   Anchor point (0, 0)
213
   Control point (0.0755, 0.302)
214
   Anchor point (0.18, 0.4245)
215
   Control point (0.4263, 0.7131)
216
   Anchor point (1, 1)
217
 
218
   I don't believe this is _exactly_ the function that Adobe uses,
219
   but it really should be close enough for all practical purposes.  */
220
const byte art_blend_soft_light_8[256] = {
221
    0, 3, 6, 9, 11, 14, 16, 19, 21, 23, 26, 28, 30, 32, 33, 35, 37, 39,
222
    40, 42, 43, 45, 46, 47, 48, 49, 51, 52, 53, 53, 54, 55, 56, 57, 57,
223
    58, 58, 59, 60, 60, 60, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, 63,
224
    63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
225
    64, 64, 64, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, 62,
226
    62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 59, 59,
227
    59, 59, 59, 58, 58, 58, 58, 57, 57, 57, 57, 56, 56, 56, 56, 55, 55,
228
    55, 55, 54, 54, 54, 54, 53, 53, 53, 52, 52, 52, 51, 51, 51, 51, 50,
229
    50, 50, 49, 49, 49, 48, 48, 48, 47, 47, 47, 46, 46, 46, 45, 45, 45,
230
    44, 44, 43, 43, 43, 42, 42, 42, 41, 41, 40, 40, 40, 39, 39, 39, 38,
231
    38, 37, 37, 37, 36, 36, 35, 35, 35, 34, 34, 33, 33, 33, 32, 32, 31,
232
    31, 31, 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, 26, 25, 25, 25, 24,
233
    24, 23, 23, 22, 22, 21, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16,
234
    16, 15, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7,
235
    7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0
236
};
237
 
238
void
239
art_blend_pixel_8(byte *dst, const byte *backdrop,
240
		  const byte *src, int n_chan, gs_blend_mode_t blend_mode)
241
{
242
    int i;
243
    byte b, s;
244
    bits32 t;
245
 
246
    switch (blend_mode) {
247
	case BLEND_MODE_Normal:
248
	case BLEND_MODE_Compatible:	/* todo */
249
	    memcpy(dst, src, n_chan);
250
	    break;
251
	case BLEND_MODE_Multiply:
252
	    for (i = 0; i < n_chan; i++) {
253
		t = ((bits32) backdrop[i]) * ((bits32) src[i]);
254
		t += 0x80;
255
		t += (t >> 8);
256
		dst[i] = t >> 8;
257
	    }
258
	    break;
259
	case BLEND_MODE_Screen:
260
	    for (i = 0; i < n_chan; i++) {
261
		t =
262
		    ((bits32) (0xff - backdrop[i])) *
263
		    ((bits32) (0xff - src[i]));
264
		t += 0x80;
265
		t += (t >> 8);
266
		dst[i] = 0xff - (t >> 8);
267
	    }
268
	    break;
269
	case BLEND_MODE_Overlay:
270
	    for (i = 0; i < n_chan; i++) {
271
		b = backdrop[i];
272
		s = src[i];
273
		if (b < 0x80)
274
		    t = 2 * ((bits32) b) * ((bits32) s);
275
		else
276
		    t = 0xfe01 -
277
			2 * ((bits32) (0xff - b)) * ((bits32) (0xff - s));
278
		t += 0x80;
279
		t += (t >> 8);
280
		dst[i] = t >> 8;
281
	    }
282
	    break;
283
	case BLEND_MODE_SoftLight:
284
	    for (i = 0; i < n_chan; i++) {
285
		b = backdrop[i];
286
		s = src[i];
287
		if (s < 0x80) {
288
		    t = (0xff - (s << 1)) * art_blend_sq_diff_8[b];
289
		    t += 0x8000;
290
		    dst[i] = b - (t >> 16);
291
		} else {
292
		    t =
293
			((s << 1) -
294
			 0xff) * ((bits32) (art_blend_soft_light_8[b]));
295
		    t += 0x80;
296
		    t += (t >> 8);
297
		    dst[i] = b + (t >> 8);
298
		}
299
	    }
300
	    break;
301
	case BLEND_MODE_HardLight:
302
	    for (i = 0; i < n_chan; i++) {
303
		b = backdrop[i];
304
		s = src[i];
305
		if (s < 0x80)
306
		    t = 2 * ((bits32) b) * ((bits32) s);
307
		else
308
		    t = 0xfe01 -
309
			2 * ((bits32) (0xff - b)) * ((bits32) (0xff - s));
310
		t += 0x80;
311
		t += (t >> 8);
312
		dst[i] = t >> 8;
313
	    }
314
	    break;
315
	case BLEND_MODE_ColorDodge:
316
	    for (i = 0; i < n_chan; i++) {
317
		b = backdrop[i];
318
		s = 0xff - src[i];
319
		if (b == 0)
320
		    dst[i] = 0;
321
		else if (b >= s)
322
		    dst[i] = 0xff;
323
		else
324
		    dst[i] = (0x1fe * b + s) / (s << 1);
325
	    }
326
	    break;
327
	case BLEND_MODE_ColorBurn:
328
	    for (i = 0; i < n_chan; i++) {
329
		b = 0xff - backdrop[i];
330
		s = src[i];
331
		if (b == 0)
332
		    dst[i] = 0xff;
333
		else if (b >= s)
334
		    dst[i] = 0;
335
		else
336
		    dst[i] = 0xff - (0x1fe * b + s) / (s << 1);
337
	    }
338
	    break;
339
	case BLEND_MODE_Darken:
340
	    for (i = 0; i < n_chan; i++) {
341
		b = backdrop[i];
342
		s = src[i];
343
		dst[i] = b < s ? b : s;
344
	    }
345
	    break;
346
	case BLEND_MODE_Lighten:
347
	    for (i = 0; i < n_chan; i++) {
348
		b = backdrop[i];
349
		s = src[i];
350
		dst[i] = b > s ? b : s;
351
	    }
352
	    break;
353
	case BLEND_MODE_Difference:
354
	    for (i = 0; i < n_chan; i++) {
355
		art_s32 tmp;
356
 
357
		tmp = ((art_s32) backdrop[i]) - ((art_s32) src[i]);
358
		dst[i] = tmp < 0 ? -tmp : tmp;
359
	    }
360
	    break;
361
	case BLEND_MODE_Exclusion:
362
	    for (i = 0; i < n_chan; i++) {
363
		b = backdrop[i];
364
		s = src[i];
365
		t = ((bits32) (0xff - b)) * ((bits32) s) +
366
		    ((bits32) b) * ((bits32) (0xff - s));
367
		t += 0x80;
368
		t += (t >> 8);
369
		dst[i] = t >> 8;
370
	    }
371
	    break;
372
	case BLEND_MODE_Luminosity:
373
	    switch (n_chan) {
374
		case 1:			/* DeviceGray */
375
	    	    dlprintf(
376
			"art_blend_pixel_8: DeviceGray luminosity blend mode not implemented\n");
377
		    break;
378
		case 3:			/* DeviceRGB */
379
	    	    art_blend_luminosity_rgb_8(dst, backdrop, src);
380
		    break;
381
		case 4:			/* DeviceCMYK */
382
	    	    art_blend_luminosity_cmyk_8(dst, backdrop, src);
383
		    break;
384
		default:		/* Should not happen */
385
		    break;
386
	    }
387
	    break;
388
	case BLEND_MODE_Color:
389
	    switch (n_chan) {
390
		case 1:			/* DeviceGray */
391
	    	    dlprintf(
392
			"art_blend_pixel_8: DeviceGray color blend mode not implemented\n");
393
		    break;
394
		case 3:			/* DeviceRGB */
395
		    art_blend_luminosity_rgb_8(dst, src, backdrop);
396
		    break;
397
		case 4:			/* DeviceCMYK */
398
		    art_blend_luminosity_cmyk_8(dst, src, backdrop);
399
		    break;
400
		default:		/* Should not happen */
401
		    break;
402
	    }
403
	    break;
404
	case BLEND_MODE_Saturation:
405
	    switch (n_chan) {
406
		case 1:			/* DeviceGray */
407
	    	    dlprintf(
408
			"art_blend_pixel_8: DeviceGray saturation blend mode not implemented\n");
409
		    break;
410
		case 3:			/* DeviceRGB */
411
	    	    art_blend_saturation_rgb_8(dst, backdrop, src);
412
		    break;
413
		case 4:			/* DeviceCMYK */
414
	    	    art_blend_saturation_cmyk_8(dst, backdrop, src);
415
		    break;
416
		default:		/* Should not happen */
417
		    break;
418
	    }
419
	    break;
420
	case BLEND_MODE_Hue:
421
	    {
422
		byte tmp[4];
423
 
424
	        switch (n_chan) {
425
		    case 1:		/* DeviceGray */
426
	    		dlprintf(
427
			    "art_blend_pixel_8: DeviceGray hue blend mode not implemented\n");
428
		        break;
429
		    case 3:		/* DeviceRGB */
430
			art_blend_luminosity_rgb_8(tmp, src, backdrop);
431
			art_blend_saturation_rgb_8(dst, tmp, backdrop);
432
		        break;
433
		    case 4:		/* DeviceCMYK */
434
		        art_blend_luminosity_cmyk_8(tmp, src, backdrop);
435
			art_blend_saturation_cmyk_8(dst, tmp, backdrop);
436
		        break;
437
		    default:		/* Should not happen */
438
		        break;
439
	        }
440
	    }
441
	    break;
442
	default:
443
	    dlprintf1("art_blend_pixel_8: blend mode %d not implemented\n",
444
		      blend_mode);
445
	    memcpy(dst, src, n_chan);
446
	    break;
447
    }
448
}
449
 
450
void
451
art_blend_pixel(ArtPixMaxDepth* dst, const ArtPixMaxDepth *backdrop,
452
		const ArtPixMaxDepth* src, int n_chan,
453
		gs_blend_mode_t blend_mode)
454
{
455
    int i;
456
    ArtPixMaxDepth b, s;
457
    bits32 t;
458
 
459
    switch (blend_mode) {
460
	case BLEND_MODE_Normal:
461
	case BLEND_MODE_Compatible:	/* todo */
462
	    memcpy(dst, src, n_chan * sizeof(ArtPixMaxDepth));
463
	    break;
464
	case BLEND_MODE_Multiply:
465
	    for (i = 0; i < n_chan; i++) {
466
		t = ((bits32) backdrop[i]) * ((bits32) src[i]);
467
		t += 0x8000;
468
		t += (t >> 16);
469
		dst[i] = t >> 16;
470
	    }
471
	    break;
472
	case BLEND_MODE_Screen:
473
	    for (i = 0; i < n_chan; i++) {
474
		t =
475
		    ((bits32) (0xffff - backdrop[i])) *
476
		    ((bits32) (0xffff - src[i]));
477
		t += 0x8000;
478
		t += (t >> 16);
479
		dst[i] = 0xffff - (t >> 16);
480
	    }
481
	    break;
482
	case BLEND_MODE_Overlay:
483
	    for (i = 0; i < n_chan; i++) {
484
		b = backdrop[i];
485
		s = src[i];
486
		if (b < 0x8000)
487
		    t = 2 * ((bits32) b) * ((bits32) s);
488
		else
489
		    t = 0xfffe0001u -
490
			2 * ((bits32) (0xffff - b)) * ((bits32) (0xffff - s));
491
		t += 0x8000;
492
		t += (t >> 16);
493
		dst[i] = t >> 16;
494
	    }
495
	    break;
496
	case BLEND_MODE_HardLight:
497
	    for (i = 0; i < n_chan; i++) {
498
		b = backdrop[i];
499
		s = src[i];
500
		if (s < 0x8000)
501
		    t = 2 * ((bits32) b) * ((bits32) s);
502
		else
503
		    t = 0xfffe0001u -
504
			2 * ((bits32) (0xffff - b)) * ((bits32) (0xffff - s));
505
		t += 0x8000;
506
		t += (t >> 16);
507
		dst[i] = t >> 16;
508
	    }
509
	    break;
510
	case BLEND_MODE_ColorDodge:
511
	    for (i = 0; i < n_chan; i++) {
512
		b = backdrop[i];
513
		s = src[i];
514
		if (b == 0)
515
		    dst[i] = 0;
516
		else if (s >= b)
517
		    dst[i] = 0xffff;
518
		else
519
		    dst[i] = (0x1fffe * s + b) / (b << 1);
520
	    }
521
	    break;
522
	case BLEND_MODE_ColorBurn:
523
	    for (i = 0; i < n_chan; i++) {
524
		b = 0xffff - backdrop[i];
525
		s = src[i];
526
		if (b == 0)
527
		    dst[i] = 0xffff;
528
		else if (b >= s)
529
		    dst[i] = 0;
530
		else
531
		    dst[i] = 0xffff - (0x1fffe * b + s) / (s << 1);
532
	    }
533
	case BLEND_MODE_Darken:
534
	    for (i = 0; i < n_chan; i++) {
535
		b = backdrop[i];
536
		s = src[i];
537
		dst[i] = b < s ? b : s;
538
	    }
539
	    break;
540
	case BLEND_MODE_Lighten:
541
	    for (i = 0; i < n_chan; i++) {
542
		b = backdrop[i];
543
		s = src[i];
544
		dst[i] = b > s ? b : s;
545
	    }
546
	    break;
547
	case BLEND_MODE_Difference:
548
	    for (i = 0; i < n_chan; i++) {
549
		art_s32 tmp;
550
 
551
		tmp = ((art_s32) backdrop[i]) - ((art_s32) src[i]);
552
		dst[i] = tmp < 0 ? -tmp : tmp;
553
	    }
554
	    break;
555
	case BLEND_MODE_Exclusion:
556
	    for (i = 0; i < n_chan; i++) {
557
		b = backdrop[i];
558
		s = src[i];
559
		t = ((bits32) (0xffff - b)) * ((bits32) s) +
560
		    ((bits32) b) * ((bits32) (0xffff - s));
561
		t += 0x8000;
562
		t += (t >> 16);
563
		dst[i] = t >> 16;
564
	    }
565
	    break;
566
	default:
567
	    dlprintf1("art_blend_pixel: blend mode %d not implemented\n",
568
		      blend_mode);
569
	    memcpy(dst, src, n_chan);
570
	    break;
571
    }
572
}
573
 
574
byte
575
art_pdf_union_8(byte alpha1, byte alpha2)
576
{
577
    int tmp;
578
 
579
    tmp = (0xff - alpha1) * (0xff - alpha2) + 0x80;
580
    return 0xff - ((tmp + (tmp >> 8)) >> 8);
581
}
582
 
583
byte
584
art_pdf_union_mul_8(byte alpha1, byte alpha2, byte alpha_mask)
585
{
586
    int tmp;
587
 
588
    if (alpha_mask == 0xff) {
589
	tmp = (0xff - alpha1) * (0xff - alpha2) + 0x80;
590
	return 0xff - ((tmp + (tmp >> 8)) >> 8);
591
    } else {
592
	tmp = alpha2 * alpha_mask + 0x80;
593
	tmp = (tmp + (tmp >> 8)) >> 8;
594
	tmp = (0xff - alpha1) * (0xff - tmp) + 0x80;
595
	return 0xff - ((tmp + (tmp >> 8)) >> 8);
596
    }
597
}
598
 
599
void
600
art_pdf_composite_pixel_alpha_8(byte *dst, const byte *src, int n_chan,
601
				gs_blend_mode_t blend_mode)
602
{
603
    byte a_b, a_s;
604
    unsigned int a_r;
605
    int tmp;
606
    int src_scale;
607
    int c_b, c_s;
608
    int i;
609
 
610
    a_s = src[n_chan];
611
    if (a_s == 0) {
612
	/* source alpha is zero, avoid all computations and possible
613
	   divide by zero errors. */
614
	return;
615
    }
616
 
617
    a_b = dst[n_chan];
618
    if (a_b == 0) {
619
	/* backdrop alpha is zero, just copy source pixels and avoid
620
	   computation. */
621
 
622
	/* this idiom is faster than memcpy (dst, src, n_chan + 1); for
623
	   expected small values of n_chan. */
624
	for (i = 0; i <= n_chan >> 2; i++) {
625
	    ((bits32 *) dst)[i] = ((const bits32 *)src)[i];
626
	}
627
 
628
	return;
629
    }
630
 
631
    /* Result alpha is Union of backdrop and source alpha */
632
    tmp = (0xff - a_b) * (0xff - a_s) + 0x80;
633
    a_r = 0xff - (((tmp >> 8) + tmp) >> 8);
634
    /* todo: verify that a_r is nonzero in all cases */
635
 
636
    /* Compute a_s / a_r in 16.16 format */
637
    src_scale = ((a_s << 16) + (a_r >> 1)) / a_r;
638
 
639
    if (blend_mode == BLEND_MODE_Normal) {
640
	/* Do simple compositing of source over backdrop */
641
	for (i = 0; i < n_chan; i++) {
642
	    c_s = src[i];
643
	    c_b = dst[i];
644
	    tmp = (c_b << 16) + src_scale * (c_s - c_b) + 0x8000;
645
	    dst[i] = tmp >> 16;
646
	}
647
    } else {
648
	/* Do compositing with blending */
649
	byte blend[ART_MAX_CHAN];
650
 
651
	art_blend_pixel_8(blend, dst, src, n_chan, blend_mode);
652
	for (i = 0; i < n_chan; i++) {
653
	    int c_bl;		/* Result of blend function */
654
	    int c_mix;		/* Blend result mixed with source color */
655
 
656
	    c_s = src[i];
657
	    c_b = dst[i];
658
	    c_bl = blend[i];
659
	    tmp = a_b * (c_bl - ((int)c_s)) + 0x80;
660
	    c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
661
	    tmp = (c_b << 16) + src_scale * (c_mix - c_b) + 0x8000;
662
	    dst[i] = tmp >> 16;
663
	}
664
    }
665
    dst[n_chan] = a_r;
666
}
667
 
668
#if 0
669
/**
670
 * art_pdf_composite_pixel_knockout_8: Composite two pixels with knockout.
671
 * @dst: Where to store resulting pixel, also immediate backdrop.
672
 * @backdrop: Initial backdrop color.
673
 * @src: Source pixel color.
674
 * @n_chan: Number of channels.
675
 * @blend_mode: Blend mode.
676
 *
677
 * Composites two pixels using the compositing operation specialized
678
 * for knockout groups (Section 5.5). A few things to keep in mind:
679
 *
680
 * 1. This is a reference implementation, not a high-performance one.
681
 *
682
 * 2. All pixels are assumed to have a single alpha channel.
683
 *
684
 * 3. Zero is black, one is white.
685
 *
686
 * Also note that src and dst are expected to be allocated aligned to
687
 * 32 bit boundaries, ie bytes from [0] to [(n_chan + 3) & -4] may
688
 * be accessed.
689
 *
690
 * All pixel values have both alpha and shape channels, ie with those
691
 * included the total number of channels is @n_chan + 2.
692
 *
693
 * An invariant: shape >= alpha.
694
 **/
695
void
696
art_pdf_composite_pixel_knockout_8(byte *dst,
697
				   const byte *backdrop, const byte *src,
698
				   int n_chan, gs_blend_mode_t blend_mode)
699
{
700
    int i;
701
    byte ct[ART_MAX_CHAN + 1];
702
    byte src_shape;
703
    byte backdrop_alpha;
704
    byte dst_alpha;
705
    bits32 src_opacity;
706
    bits32 backdrop_weight, t_weight;
707
    int tmp;
708
 
709
    if (src[n_chan] == 0)
710
	return;
711
    if (src[n_chan + 1] == 255 && blend_mode == BLEND_MODE_Normal ||
712
	dst[n_chan] == 0) {
713
	/* this idiom is faster than memcpy (dst, src, n_chan + 2); for
714
	   expected small values of n_chan. */
715
	for (i = 0; i <= (n_chan + 1) >> 2; i++) {
716
	    ((bits32 *) dst)[i] = ((const bits32 *)src[i]);
717
	}
718
 
719
	return;
720
    }
721
 
722
 
723
    src_shape = src[n_chan + 1];	/* $fs_i$ */
724
    src_opacity = (255 * src[n_chan] + 0x80) / src_shape;	/* $qs_i$ */
725
#if 0
726
    for (i = 0; i < (n_chan + 3) >> 2; i++) {
727
	((bits32 *) src_tmp)[i] = ((const bits32 *)src[i]);
728
    }
729
    src_tmp[n_chan] = src_opacity;
730
 
731
    for (i = 0; i <= n_chan >> 2; i++) {
732
	((bits32 *) tmp)[i] = ((bits32 *) backdrop[i]);
733
    }
734
#endif
735
 
736
    backdrop_scale = if (blend_mode == BLEND_MODE_Normal) {
737
	/* Do simple compositing of source over backdrop */
738
	for (i = 0; i < n_chan; i++) {
739
	    c_s = src[i];
740
	    c_b = dst[i];
741
	    tmp = (c_b << 16) + ct_scale * (c_s - c_b) + 0x8000;
742
	    ct[i] = tmp >> 16;
743
	}
744
    } else {
745
	/* Do compositing with blending */
746
	byte blend[ART_MAX_CHAN];
747
 
748
	art_blend_pixel_8(blend, backdrop, src, n_chan, blend_mode);
749
	for (i = 0; i < n_chan; i++) {
750
	    int c_bl;		/* Result of blend function */
751
	    int c_mix;		/* Blend result mixed with source color */
752
 
753
	    c_s = src[i];
754
	    c_b = dst[i];
755
	    c_bl = blend[i];
756
	    tmp = a_b * (((int)c_bl) - ((int)c_s)) + 0x80;
757
	    c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
758
	    tmp = (c_b << 16) + ct_scale * (c_mix - c_b) + 0x8000;
759
	    ct[i] = tmp >> 16;
760
	}
761
    }
762
 
763
    /* do weighted average of $Ct$ using relative alpha contribution as weight */
764
    backdrop_alpha = backdrop[n_chan];
765
    tmp = (0xff - blend_alpha) * (0xff - backdrop_alpha) + 0x80;
766
    dst_alpha = 0xff - (((tmp >> 8) + tmp) >> 8);
767
    dst[n_chan] = dst_alpha;
768
    t_weight = ((blend_alpha << 16) + 0x8000) / dst_alpha;
769
    for (i = 0; i < n_chan; i++) {
770
 
771
    }
772
}
773
#endif
774
 
775
void
776
art_pdf_uncomposite_group_8(byte *dst,
777
			    const byte *backdrop,
778
			    const byte *src, byte src_alpha_g, int n_chan)
779
{
780
    byte backdrop_alpha = backdrop[n_chan];
781
    int i;
782
    int tmp;
783
    int scale;
784
 
785
    dst[n_chan] = src_alpha_g;
786
 
787
    if (src_alpha_g == 0)
788
	return;
789
 
790
    scale = (backdrop_alpha * 255 * 2 + src_alpha_g) / (src_alpha_g << 1) -
791
	backdrop_alpha;
792
    for (i = 0; i < n_chan; i++) {
793
	int si, di;
794
 
795
	si = src[i];
796
	di = backdrop[i];
797
	tmp = (si - di) * scale + 0x80;
798
	tmp = si + ((tmp + (tmp >> 8)) >> 8);
799
 
800
	/* todo: it should be possible to optimize these cond branches */
801
	if (tmp < 0)
802
	    tmp = 0;
803
	if (tmp > 255)
804
	    tmp = 255;
805
	dst[i] = tmp;
806
    }
807
 
808
}
809
 
810
void
811
art_pdf_recomposite_group_8(byte *dst, byte *dst_alpha_g,
812
			    const byte *src, byte src_alpha_g,
813
			    int n_chan,
814
			    byte alpha, gs_blend_mode_t blend_mode)
815
{
816
    byte dst_alpha;
817
    int i;
818
    int tmp;
819
    int scale;
820
 
821
    if (src_alpha_g == 0)
822
	return;
823
 
824
    if (blend_mode == BLEND_MODE_Normal && alpha == 255) {
825
	/* In this case, uncompositing and recompositing cancel each
826
	   other out. Note: if the reason that alpha == 255 is that
827
	   there is no constant mask and no soft mask, then this
828
	   operation should be optimized away at a higher level. */
829
	for (i = 0; i <= n_chan >> 2; i++)
830
	    ((bits32 *) dst)[i] = ((const bits32 *)src)[i];
831
	if (dst_alpha_g != NULL) {
832
	    tmp = (255 - *dst_alpha_g) * (255 - src_alpha_g) + 0x80;
833
	    *dst_alpha_g = 255 - ((tmp + (tmp >> 8)) >> 8);
834
	}
835
	return;
836
    } else {
837
	/* "interesting" blend mode */
838
	byte ca[ART_MAX_CHAN + 1];	/* $C, \alpha$ */
839
 
840
	dst_alpha = dst[n_chan];
841
	if (src_alpha_g == 255 || dst_alpha == 0) {
842
	    for (i = 0; i < (n_chan + 3) >> 2; i++)
843
		((bits32 *) ca)[i] = ((const bits32 *)src)[i];
844
	} else {
845
	    /* Uncomposite the color. In other words, solve
846
	       "src = (ca, src_alpha_g) over dst" for ca */
847
 
848
	    /* todo (maybe?): replace this code with call to
849
	       art_pdf_uncomposite_group_8() to reduce code
850
	       duplication. */
851
 
852
	    scale = (dst_alpha * 255 * 2 + src_alpha_g) / (src_alpha_g << 1) -
853
		dst_alpha;
854
	    for (i = 0; i < n_chan; i++) {
855
		int si, di;
856
 
857
		si = src[i];
858
		di = dst[i];
859
		tmp = (si - di) * scale + 0x80;
860
		tmp = si + ((tmp + (tmp >> 8)) >> 8);
861
 
862
		/* todo: it should be possible to optimize these cond branches */
863
		if (tmp < 0)
864
		    tmp = 0;
865
		if (tmp > 255)
866
		    tmp = 255;
867
		ca[i] = tmp;
868
	    }
869
	}
870
 
871
	tmp = src_alpha_g * alpha + 0x80;
872
	tmp = (tmp + (tmp >> 8)) >> 8;
873
	ca[n_chan] = tmp;
874
	if (dst_alpha_g != NULL) {
875
	    tmp = (255 - *dst_alpha_g) * (255 - tmp) + 0x80;
876
	    *dst_alpha_g = 255 - ((tmp + (tmp >> 8)) >> 8);
877
	}
878
	art_pdf_composite_pixel_alpha_8(dst, ca, n_chan, blend_mode);
879
    }
880
    /* todo: optimize BLEND_MODE_Normal buf alpha != 255 case */
881
}
882
 
883
void
884
art_pdf_composite_group_8(byte *dst, byte *dst_alpha_g,
885
			  const byte *src,
886
			  int n_chan, byte alpha, gs_blend_mode_t blend_mode)
887
{
888
    byte src_alpha;		/* $\alpha g_n$ */
889
    byte src_tmp[ART_MAX_CHAN + 1];
890
    int i;
891
    int tmp;
892
 
893
    if (alpha == 255) {
894
	art_pdf_composite_pixel_alpha_8(dst, src, n_chan, blend_mode);
895
	if (dst_alpha_g != NULL) {
896
	    tmp = (255 - *dst_alpha_g) * (255 - src[n_chan]) + 0x80;
897
	    *dst_alpha_g = 255 - ((tmp + (tmp >> 8)) >> 8);
898
	}
899
    } else {
900
	src_alpha = src[n_chan];
901
	if (src_alpha == 0)
902
	    return;
903
	for (i = 0; i < (n_chan + 3) >> 2; i++)
904
	    ((bits32 *) src_tmp)[i] = ((const bits32 *)src)[i];
905
	tmp = src_alpha * alpha + 0x80;
906
	src_tmp[n_chan] = (tmp + (tmp >> 8)) >> 8;
907
	art_pdf_composite_pixel_alpha_8(dst, src_tmp, n_chan, blend_mode);
908
	if (dst_alpha_g != NULL) {
909
	    tmp = (255 - *dst_alpha_g) * (255 - src_tmp[n_chan]) + 0x80;
910
	    *dst_alpha_g = 255 - ((tmp + (tmp >> 8)) >> 8);
911
	}
912
    }
913
}
914
 
915
void
916
art_pdf_composite_knockout_simple_8(byte *dst,
917
				    byte *dst_shape,
918
				    const byte *src,
919
				    int n_chan, byte opacity)
920
{
921
    byte src_shape = src[n_chan];
922
    int i;
923
 
924
    if (src_shape == 0)
925
	return;
926
    else if (src_shape == 255) {
927
	for (i = 0; i < (n_chan + 3) >> 2; i++)
928
	    ((bits32 *) dst)[i] = ((const bits32 *)src)[i];
929
	dst[n_chan] = opacity;
930
	if (dst_shape != NULL)
931
	    *dst_shape = 255;
932
    } else {
933
	/* Use src_shape to interpolate (in premultiplied alpha space)
934
	   between dst and (src, opacity). */
935
	int dst_alpha = dst[n_chan];
936
	byte result_alpha;
937
	int tmp;
938
 
939
	tmp = (opacity - dst_alpha) * src_shape + 0x80;
940
	result_alpha = dst_alpha + ((tmp + (tmp >> 8)) >> 8);
941
 
942
	if (result_alpha != 0)
943
	    for (i = 0; i < n_chan; i++) {
944
		/* todo: optimize this - can strength-reduce so that
945
		   inner loop is a single interpolation */
946
		tmp = dst[i] * dst_alpha * (255 - src_shape) +
947
		    ((int)src[i]) * opacity * src_shape + (result_alpha << 7);
948
		dst[i] = tmp / (result_alpha * 255);
949
	    }
950
	dst[n_chan] = result_alpha;
951
 
952
	/* union in dst_shape if non-null */
953
	if (dst_shape != NULL) {
954
	    tmp = (255 - *dst_shape) * (255 - src_shape) + 0x80;
955
	    *dst_shape = 255 - ((tmp + (tmp >> 8)) >> 8);
956
	}
957
    }
958
}
959
 
960
void
961
art_pdf_composite_knockout_isolated_8(byte *dst,
962
				      byte *dst_shape,
963
				      const byte *src,
964
				      int n_chan,
965
				      byte shape,
966
				      byte alpha_mask, byte shape_mask)
967
{
968
    int tmp;
969
    int i;
970
 
971
    if (shape == 0)
972
	return;
973
    else if ((shape & shape_mask) == 255) {
974
	for (i = 0; i < (n_chan + 3) >> 2; i++)
975
	    ((bits32 *) dst)[i] = ((const bits32 *)src)[i];
976
	tmp = src[n_chan] * alpha_mask + 0x80;
977
	dst[n_chan] = (tmp + (tmp >> 8)) >> 8;
978
	if (dst_shape != NULL)
979
	    *dst_shape = 255;
980
    } else {
981
	/* Use src_shape to interpolate (in premultiplied alpha space)
982
	   between dst and (src, opacity). */
983
	byte src_shape, src_alpha;
984
	int dst_alpha = dst[n_chan];
985
	byte result_alpha;
986
	int tmp;
987
 
988
	tmp = shape * shape_mask + 0x80;
989
	src_shape = (tmp + (tmp >> 8)) >> 8;
990
 
991
	tmp = src[n_chan] * alpha_mask + 0x80;
992
	src_alpha = (tmp + (tmp >> 8)) >> 8;
993
 
994
	tmp = (src_alpha - dst_alpha) * src_shape + 0x80;
995
	result_alpha = dst_alpha + ((tmp + (tmp >> 8)) >> 8);
996
 
997
	if (result_alpha != 0)
998
	    for (i = 0; i < n_chan; i++) {
999
		/* todo: optimize this - can strength-reduce so that
1000
		   inner loop is a single interpolation */
1001
		tmp = dst[i] * dst_alpha * (255 - src_shape) +
1002
		    ((int)src[i]) * src_alpha * src_shape +
1003
		    (result_alpha << 7);
1004
		dst[i] = tmp / (result_alpha * 255);
1005
	    }
1006
	dst[n_chan] = result_alpha;
1007
 
1008
	/* union in dst_shape if non-null */
1009
	if (dst_shape != NULL) {
1010
	    tmp = (255 - *dst_shape) * (255 - src_shape) + 0x80;
1011
	    *dst_shape = 255 - ((tmp + (tmp >> 8)) >> 8);
1012
	}
1013
    }
1014
}
1015
 
1016
void
1017
art_pdf_composite_knockout_8(byte *dst,
1018
			     byte *dst_alpha_g,
1019
			     const byte *backdrop,
1020
			     const byte *src,
1021
			     int n_chan,
1022
			     byte shape,
1023
			     byte alpha_mask,
1024
			     byte shape_mask, gs_blend_mode_t blend_mode)
1025
{
1026
    /* This implementation follows the Adobe spec pretty closely, rather
1027
       than trying to do anything clever. For example, in the case of a
1028
       Normal blend_mode when the top group is non-isolated, uncompositing
1029
       and recompositing is more work than needed. So be it. Right now,
1030
       I'm more worried about manageability than raw performance. */
1031
    byte alpha_t;
1032
    byte src_alpha, src_shape;
1033
    byte src_opacity;
1034
    byte ct[ART_MAX_CHAN];
1035
    byte backdrop_alpha;
1036
    byte alpha_g_i_1, alpha_g_i, alpha_i;
1037
    int tmp;
1038
    int i;
1039
    int scale_b;
1040
    int scale_src;
1041
 
1042
    if (shape == 0 || shape_mask == 0)
1043
	return;
1044
 
1045
    tmp = shape * shape_mask + 0x80;
1046
    /* $f s_i$ */
1047
    src_shape = (tmp + (tmp >> 8)) >> 8;
1048
 
1049
    tmp = src[n_chan] * alpha_mask + 0x80;
1050
    src_alpha = (tmp + (tmp >> 8)) >> 8;
1051
 
1052
    /* $q s_i$ */
1053
    src_opacity = (src_alpha * 510 + src_shape) / (2 * src_shape);
1054
 
1055
    /* $\alpha t$, \alpha g_b is always zero for knockout groups */
1056
    alpha_t = src_opacity;
1057
 
1058
    /* $\alpha b$ */
1059
    backdrop_alpha = backdrop[n_chan];
1060
 
1061
    tmp = (0xff - src_opacity) * backdrop_alpha;
1062
    /* $(1 - q s_i) \cdot alpha_b$ scaled by 2^16 */
1063
    scale_b = tmp + (tmp >> 7) + (tmp >> 14);
1064
 
1065
    /* $q s_i$ scaled by 2^16 */
1066
    scale_src = (src_opacity << 8) + (src_opacity) + (src_opacity >> 7);
1067
 
1068
    /* Do simple compositing of source over backdrop */
1069
    if (blend_mode == BLEND_MODE_Normal) {
1070
	for (i = 0; i < n_chan; i++) {
1071
	    int c_s;
1072
	    int c_b;
1073
 
1074
	    c_s = src[i];
1075
	    c_b = backdrop[i];
1076
	    tmp = (c_b << 16) * scale_b + (c_s - c_b) + scale_src + 0x8000;
1077
	    ct[i] = tmp >> 16;
1078
	}
1079
    } else {
1080
	byte blend[ART_MAX_CHAN];
1081
 
1082
	art_blend_pixel_8(blend, backdrop, src, n_chan, blend_mode);
1083
	for (i = 0; i < n_chan; i++) {
1084
	    int c_s;
1085
	    int c_b;
1086
	    int c_bl;		/* Result of blend function */
1087
	    int c_mix;		/* Blend result mixed with source color */
1088
 
1089
	    c_s = src[i];
1090
	    c_b = backdrop[i];
1091
	    c_bl = blend[i];
1092
	    tmp = backdrop_alpha * (c_bl - ((int)c_s)) + 0x80;
1093
	    c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
1094
	    tmp = (c_b << 16) * scale_b + (c_mix - c_b) + scale_src + 0x8000;
1095
	    ct[i] = tmp >> 16;
1096
	}
1097
    }
1098
 
1099
    /* $\alpha g_{i - 1}$ */
1100
    alpha_g_i_1 = *dst_alpha_g;
1101
 
1102
    tmp = src_shape * (((int)alpha_t) - alpha_g_i_1) + 0x80;
1103
    /* $\alpha g_i$ */
1104
    alpha_g_i = alpha_g_i_1 + ((tmp + (tmp >> 8)) >> 8);
1105
 
1106
    tmp = (0xff - backdrop_alpha) * (0xff - alpha_g_i) + 0x80;
1107
    /* $\alpha_i$ */
1108
    alpha_i = 0xff - ((tmp + (tmp >> 8)) >> 8);
1109
 
1110
    if (alpha_i > 0) {
1111
	int scale_dst;
1112
	int scale_t;
1113
	byte dst_alpha;
1114
 
1115
	/* $f s_i / \alpha_i$ scaled by 2^16 */
1116
	scale_t = ((src_shape << 17) + alpha_i) / (2 * alpha_i);
1117
 
1118
	/* $\alpha_{i - 1}$ */
1119
	dst_alpha = dst[n_chan];
1120
 
1121
	tmp = (1 - src_shape) * dst_alpha;
1122
	tmp = (tmp << 9) + (tmp << 1) + (tmp >> 7) + alpha_i;
1123
	scale_dst = tmp / (2 * alpha_i);
1124
 
1125
	for (i = 0; i < n_chan; i++) {
1126
	    tmp = dst[i] * scale_dst + ct[i] * scale_t + 0x8000;
1127
	    /* todo: clamp? */
1128
	    dst[i] = tmp >> 16;
1129
	}
1130
    }
1131
    dst[n_chan] = alpha_i;
1132
    *dst_alpha_g = alpha_g_i;
1133
}