1#include "mupdf/fitz.h"
2#include "draw-imp.h"
3
4#include <string.h>
5#include <math.h>
6#include <assert.h>
7
8/* PDF 1.4 blend modes. These are slow. */
9
10/* Define PARANOID_PREMULTIPLY to check premultiplied values are
11 * properly in range. */
12#undef PARANOID_PREMULTIPLY
13
14/*
15
16Some notes on the transparency maths:
17
18Compositing equation:
19=====================
20
21In section 7.2.2 (page 517) of pdf_reference17.pdf, it says:
22
23 Cr = (1 - As/Ar) * Cb + As/Ar * [ (1-Ab) * Cs + Ab * B(Cb,Cs) ]
24
25It says that this is a simplified version of the more general form.
26
27This equation is then restated in section 7.2.2 and it says:
28
29The formula shown above is a simplification of the following formula:
30
31 Ar * Cr = [(1-As)*Ab*Cb] + [(1-Ab)*As*Cs] + [Ab*As*B(Cb, Cs)]
32
33At first glange this always appears to be a mistake to me, as it looks
34like they have make a mistake in the division.
35
36However, if we consider the result alpha equation:
37
38 Ar = Union(Ab, As) = Ab + As - Ab * As
39
40we can rearrange that to give:
41
42 Ar - As = (1 - As) * Ab
43
44 1 - As/Ar = (1 - As) * Ab / Ar
45
46So substituting into the first equation above, we get:
47
48 Cr = ((1 - As) * Ab/Ar) * Cb + As/Ar * [ (1-Ab) * Cs + Ab * B(Cb,Cs) ]
49
50And thus:
51
52 Ar * Cr = (1 - As) * Ab * Cb + As * [ (1-Ab)*Cs + Ab * B(Cb,Cs) ]
53
54as required.
55
56Alpha blending on top of compositing:
57=====================================
58
59Suppose we have a group to blend using blend mode B, and we want
60to apply alpha too. Let's apply the blending first to get an
61intermediate result (Ir), then apply the alpha to that to get the
62result (Cr):
63
64 Ir = (1 - As/Ar) * Cb + As/Ar * [ (1-Ab) * Cs + Ab * B(Cb,Cs) ]
65
66 Cr = (1-alpha) * Cb + alpha * Ir
67 = Cb - alpha * Cb + alpha * Cb - alpha * Cb * As / Ar + alpha * As / Ar * [ (1 - Ab) * Cs + Ab * B(Cb, Cs) ]
68 = Cb - alpha * Cb * As / Ar + alpha * As / Ar * [ (1 - Ab) * Cs + Ab * B(Cb, Cs) ]
69 = Cb * (1 - alpha * As / Ar) + alpha * As / Ar * [ (1 - Ab) * Cs + Ab * B(Cb, Cs) ]
70
71We want premultiplied results, so:
72
73 Ar*Cr = Cb * (Ar - alpha * As) + alpha * As * (1 - Ab) * Cs + alpha * As * Ab * B(Cb, Cs) ]
74
75In the same way, for the alpha values:
76
77 Ia = Union(Ab, As) = Ab + As - As*Ab
78 Ar = (1-alpha) * Ab + alpha * Ia
79 = Ab - alpha * Ab + alpha * Ab + alpha * As - alpha * As * Ab
80 = Ab + alpha * As - alpha * As * Ab
81 = Union(Ab, alpha * As)
82
83*/
84
85typedef unsigned char byte;
86
87static const char *fz_blendmode_names[] =
88{
89 "Normal",
90 "Multiply",
91 "Screen",
92 "Overlay",
93 "Darken",
94 "Lighten",
95 "ColorDodge",
96 "ColorBurn",
97 "HardLight",
98 "SoftLight",
99 "Difference",
100 "Exclusion",
101 "Hue",
102 "Saturation",
103 "Color",
104 "Luminosity",
105};
106
107int fz_lookup_blendmode(const char *name)
108{
109 int i;
110 for (i = 0; i < nelem(fz_blendmode_names); i++)
111 if (!strcmp(name, fz_blendmode_names[i]))
112 return i;
113 return FZ_BLEND_NORMAL;
114}
115
116char *fz_blendmode_name(int blendmode)
117{
118 if (blendmode >= 0 && blendmode < nelem(fz_blendmode_names))
119 return (char*)fz_blendmode_names[blendmode];
120 return "Normal";
121}
122
123/* Separable blend modes */
124
125static inline int fz_screen_byte(int b, int s)
126{
127 return b + s - fz_mul255(b, s);
128}
129
130static inline int fz_hard_light_byte(int b, int s)
131{
132 int s2 = s << 1;
133 if (s <= 127)
134 return fz_mul255(b, s2);
135 else
136 return fz_screen_byte(b, s2 - 255);
137}
138
139static inline int fz_overlay_byte(int b, int s)
140{
141 return fz_hard_light_byte(s, b); /* note swapped order */
142}
143
144static inline int fz_darken_byte(int b, int s)
145{
146 return fz_mini(b, s);
147}
148
149static inline int fz_lighten_byte(int b, int s)
150{
151 return fz_maxi(b, s);
152}
153
154static inline int fz_color_dodge_byte(int b, int s)
155{
156 s = 255 - s;
157 if (b <= 0)
158 return 0;
159 else if (b >= s)
160 return 255;
161 else
162 return (0x1fe * b + s) / (s << 1);
163}
164
165static inline int fz_color_burn_byte(int b, int s)
166{
167 b = 255 - b;
168 if (b <= 0)
169 return 255;
170 else if (b >= s)
171 return 0;
172 else
173 return 0xff - (0x1fe * b + s) / (s << 1);
174}
175
176static inline int fz_soft_light_byte(int b, int s)
177{
178 if (s < 128) {
179 return b - fz_mul255(fz_mul255((255 - (s<<1)), b), 255 - b);
180 }
181 else {
182 int dbd;
183 if (b < 64)
184 dbd = fz_mul255(fz_mul255((b << 4) - 3060, b) + 1020, b);
185 else
186 dbd = (int)sqrtf(255.0f * b);
187 return b + fz_mul255(((s<<1) - 255), (dbd - b));
188 }
189}
190
191static inline int fz_difference_byte(int b, int s)
192{
193 return fz_absi(b - s);
194}
195
196static inline int fz_exclusion_byte(int b, int s)
197{
198 return b + s - (fz_mul255(b, s)<<1);
199}
200
201/* Non-separable blend modes */
202
203static void
204fz_luminosity_rgb(unsigned char *rd, unsigned char *gd, unsigned char *bd, int rb, int gb, int bb, int rs, int gs, int bs)
205{
206 int delta, scale;
207 int r, g, b, y;
208
209 /* 0.3f, 0.59f, 0.11f in fixed point */
210 delta = ((rs - rb) * 77 + (gs - gb) * 151 + (bs - bb) * 28 + 0x80) >> 8;
211 r = rb + delta;
212 g = gb + delta;
213 b = bb + delta;
214
215 if ((r | g | b) & 0x100)
216 {
217 y = (rs * 77 + gs * 151 + bs * 28 + 0x80) >> 8;
218 if (delta > 0)
219 {
220 int max;
221 max = fz_maxi(r, fz_maxi(g, b));
222 scale = (max == y ? 0 : ((255 - y) << 16) / (max - y));
223 }
224 else
225 {
226 int min;
227 min = fz_mini(r, fz_mini(g, b));
228 scale = (y == min ? 0 : (y << 16) / (y - min));
229 }
230 r = y + (((r - y) * scale + 0x8000) >> 16);
231 g = y + (((g - y) * scale + 0x8000) >> 16);
232 b = y + (((b - y) * scale + 0x8000) >> 16);
233 }
234
235 *rd = fz_clampi(r, 0, 255);
236 *gd = fz_clampi(g, 0, 255);
237 *bd = fz_clampi(b, 0, 255);
238}
239
240static void
241fz_saturation_rgb(unsigned char *rd, unsigned char *gd, unsigned char *bd, int rb, int gb, int bb, int rs, int gs, int bs)
242{
243 int minb, maxb;
244 int mins, maxs;
245 int y;
246 int scale;
247 int r, g, b;
248
249 minb = fz_mini(rb, fz_mini(gb, bb));
250 maxb = fz_maxi(rb, fz_maxi(gb, bb));
251 if (minb == maxb)
252 {
253 /* backdrop has zero saturation, avoid divide by 0 */
254 gb = fz_clampi(gb, 0, 255);
255 *rd = gb;
256 *gd = gb;
257 *bd = gb;
258 return;
259 }
260
261 mins = fz_mini(rs, fz_mini(gs, bs));
262 maxs = fz_maxi(rs, fz_maxi(gs, bs));
263
264 scale = ((maxs - mins) << 16) / (maxb - minb);
265 y = (rb * 77 + gb * 151 + bb * 28 + 0x80) >> 8;
266 r = y + ((((rb - y) * scale) + 0x8000) >> 16);
267 g = y + ((((gb - y) * scale) + 0x8000) >> 16);
268 b = y + ((((bb - y) * scale) + 0x8000) >> 16);
269
270 if ((r | g | b) & 0x100)
271 {
272 int scalemin, scalemax;
273 int min, max;
274
275 min = fz_mini(r, fz_mini(g, b));
276 max = fz_maxi(r, fz_maxi(g, b));
277
278 if (min < 0)
279 scalemin = (y << 16) / (y - min);
280 else
281 scalemin = 0x10000;
282
283 if (max > 255)
284 scalemax = ((255 - y) << 16) / (max - y);
285 else
286 scalemax = 0x10000;
287
288 scale = fz_mini(scalemin, scalemax);
289 r = y + (((r - y) * scale + 0x8000) >> 16);
290 g = y + (((g - y) * scale + 0x8000) >> 16);
291 b = y + (((b - y) * scale + 0x8000) >> 16);
292 }
293
294 *rd = fz_clampi(r, 0, 255);
295 *gd = fz_clampi(g, 0, 255);
296 *bd = fz_clampi(b, 0, 255);
297}
298
299static void
300fz_color_rgb(unsigned char *rr, unsigned char *rg, unsigned char *rb, int br, int bg, int bb, int sr, int sg, int sb)
301{
302 fz_luminosity_rgb(rr, rg, rb, sr, sg, sb, br, bg, bb);
303}
304
305static void
306fz_hue_rgb(unsigned char *rr, unsigned char *rg, unsigned char *rb, int br, int bg, int bb, int sr, int sg, int sb)
307{
308 unsigned char tr, tg, tb;
309 fz_luminosity_rgb(&tr, &tg, &tb, sr, sg, sb, br, bg, bb);
310 fz_saturation_rgb(rr, rg, rb, tr, tg, tb, br, bg, bb);
311}
312
313/* Blending loops */
314
315static inline void
316fz_blend_separable(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n1, int w, int blendmode, int complement, int first_spot)
317{
318 int k;
319 do
320 {
321 int sa = (sal ? sp[n1] : 255);
322
323 if (sa != 0)
324 {
325 int ba = (bal ? bp[n1] : 255);
326 if (ba == 0)
327 {
328 memcpy(bp, sp, n1 + (sal && bal));
329 if (bal && !sal)
330 bp[n1+1] = 255;
331 }
332 else
333 {
334 int saba = fz_mul255(sa, ba);
335
336 /* ugh, division to get non-premul components */
337 int invsa = sa ? 255 * 256 / sa : 0;
338 int invba = ba ? 255 * 256 / ba : 0;
339
340 /* Process colorants */
341 for (k = 0; k < first_spot; k++)
342 {
343 int sc = (sp[k] * invsa) >> 8;
344 int bc = (bp[k] * invba) >> 8;
345 int rc;
346
347 if (complement)
348 {
349 sc = 255 - sc;
350 bc = 255 - bc;
351 }
352
353 switch (blendmode)
354 {
355 default:
356 case FZ_BLEND_NORMAL: rc = sc; break;
357 case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break;
358 case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break;
359 case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break;
360 case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break;
361 case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break;
362 case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break;
363 case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break;
364 case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break;
365 case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break;
366 case FZ_BLEND_DIFFERENCE: rc = fz_difference_byte(bc, sc); break;
367 case FZ_BLEND_EXCLUSION: rc = fz_exclusion_byte(bc, sc); break;
368 }
369
370 if (complement)
371 {
372 rc = 255 - rc;
373 }
374
375 bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, rc);
376 }
377
378 /* spots */
379 for (; k < n1; k++)
380 {
381 int sc = 255 - ((sp[k] * invsa) >> 8);
382 int bc = 255 - ((bp[k] * invba) >> 8);
383 int rc;
384
385 switch (blendmode)
386 {
387 default:
388 case FZ_BLEND_NORMAL:
389 case FZ_BLEND_DIFFERENCE:
390 case FZ_BLEND_EXCLUSION:
391 rc = sc; break;
392 case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break;
393 case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break;
394 case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break;
395 case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break;
396 case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break;
397 case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break;
398 case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break;
399 case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break;
400 case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break;
401 }
402 bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, 255 - rc);
403 }
404
405 if (bal)
406 bp[k] = ba + sa - saba;
407 }
408 }
409 sp += n1 + sal;
410 bp += n1 + bal;
411 }
412 while (--w);
413}
414
415static inline void
416fz_blend_nonseparable_gray(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n, int w, int blendmode, int first_spot)
417{
418 do
419 {
420 int sa = (sal ? sp[n] : 255);
421
422 if (sa != 0)
423 {
424 int ba = (bal ? bp[n] : 255);
425 if (ba == 0)
426 {
427 memcpy(bp, sp, n + (sal && bal));
428 if (bal && !sal)
429 bp [n + 1] = 255;
430 }
431 else
432 {
433 int saba = fz_mul255(sa, ba);
434
435 /* ugh, division to get non-premul components */
436 int invsa = sa ? 255 * 256 / sa : 0;
437 int invba = ba ? 255 * 256 / ba : 0;
438 int k;
439 int sg = (sp[0] * invsa) >> 8;
440 int bg = (bp[0] * invba) >> 8;
441
442 switch (blendmode)
443 {
444 default:
445 case FZ_BLEND_HUE:
446 case FZ_BLEND_SATURATION:
447 case FZ_BLEND_COLOR:
448 bp[0] = fz_mul255(bp[n], bg);
449 break;
450 case FZ_BLEND_LUMINOSITY:
451 bp[0] = fz_mul255(bp[n], sg);
452 break;
453 }
454
455 /* Normal blend for spots */
456 for (k = first_spot; k < n; k++)
457 {
458 int sc = (sp[k] * invsa) >> 8;
459 bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, sc);
460 }
461 if (bal)
462 bp[n] = ba + sa - saba;
463 }
464 }
465 sp += n + sal;
466 bp += n + bal;
467 } while (--w);
468}
469
470static inline void
471fz_blend_nonseparable(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n, int w, int blendmode, int complement, int first_spot)
472{
473 do
474 {
475 unsigned char rr, rg, rb;
476
477 int sa = (sal ? sp[n] : 255);
478
479 if (sa != 0)
480 {
481 int ba = (bal ? bp[n] : 255);
482 if (ba == 0)
483 {
484 memcpy(bp, sp, n + (sal && bal));
485 if (bal && !sal)
486 bp [n + 1] = 255;
487 }
488 else
489 {
490 int k;
491 int saba = fz_mul255(sa, ba);
492
493 /* ugh, division to get non-premul components */
494 int invsa = sa ? 255 * 256 / sa : 0;
495 int invba = ba ? 255 * 256 / ba : 0;
496
497 int sr = (sp[0] * invsa) >> 8;
498 int sg = (sp[1] * invsa) >> 8;
499 int sb = (sp[2] * invsa) >> 8;
500
501 int br = (bp[0] * invba) >> 8;
502 int bg = (bp[1] * invba) >> 8;
503 int bb = (bp[2] * invba) >> 8;
504
505 /* CMYK */
506 if (complement)
507 {
508 sr = 255 - sr;
509 sg = 255 - sg;
510 sb = 255 - sb;
511 br = 255 - br;
512 bg = 255 - bg;
513 bb = 255 - bb;
514 }
515
516 switch (blendmode)
517 {
518 default:
519 case FZ_BLEND_HUE:
520 fz_hue_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
521 break;
522 case FZ_BLEND_SATURATION:
523 fz_saturation_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
524 break;
525 case FZ_BLEND_COLOR:
526 fz_color_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
527 break;
528 case FZ_BLEND_LUMINOSITY:
529 fz_luminosity_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
530 break;
531 }
532
533 /* CMYK */
534 if (complement)
535 {
536 int sk = (sp[3] * invsa) >> 8;
537 int bk = (bp[3] * invba) >> 8;
538
539 rr = 255 - rr;
540 rg = 255 - rg;
541 rb = 255 - rb;
542 bp[0] = fz_mul255(255 - sa, 255 - bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, rr);
543 bp[1] = fz_mul255(255 - sa, 255 - bp[1]) + fz_mul255(255 - ba, sp[1]) + fz_mul255(saba, rg);
544 bp[2] = fz_mul255(255 - sa, 255 - bp[2]) + fz_mul255(255 - ba, sp[2]) + fz_mul255(saba, rb);
545
546 switch (blendmode)
547 {
548 default:
549 case FZ_BLEND_HUE:
550 case FZ_BLEND_SATURATION:
551 case FZ_BLEND_COLOR:
552 bp[3] = fz_mul255(bp[n], bk);
553 break;
554 case FZ_BLEND_LUMINOSITY:
555 bp[3] = fz_mul255(bp[n], sk);
556 break;
557 }
558 }
559 else
560 {
561 bp[0] = fz_mul255(255 - sa, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, rr);
562 bp[1] = fz_mul255(255 - sa, bp[1]) + fz_mul255(255 - ba, sp[1]) + fz_mul255(saba, rg);
563 bp[2] = fz_mul255(255 - sa, bp[2]) + fz_mul255(255 - ba, sp[2]) + fz_mul255(saba, rb);
564 }
565
566 if (bal)
567 bp[n] = ba + sa - saba;
568
569 /* Normal blend for spots */
570 for (k = first_spot; k < n; k++)
571 {
572 int sc = (sp[k] * invsa) >> 8;
573 bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, sc);
574 }
575 }
576 }
577 sp += n + sal;
578 bp += n + bal;
579 }
580 while (--w);
581}
582
583static inline void
584fz_blend_separable_nonisolated(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n1, int w, int blendmode, int complement, const byte * FZ_RESTRICT hp, int alpha, int first_spot)
585{
586 int k;
587
588 if (sal == 0 && alpha == 255 && blendmode == 0)
589 {
590 /* In this case, the uncompositing and the recompositing
591 * cancel one another out, and it's just a simple copy. */
592 /* FIXME: Maybe we can avoid using the shape plane entirely
593 * and just copy? */
594 do
595 {
596 int ha = fz_mul255(*hp++, alpha); /* ha = shape_alpha */
597 /* If ha == 0 then leave everything unchanged */
598 if (ha != 0)
599 {
600 for (k = 0; k < n1; k++)
601 bp[k] = sp[k];
602 if (bal)
603 bp[k] = 255;
604 }
605
606 sp += n1;
607 bp += n1 + bal;
608 }
609 while (--w);
610 return;
611 }
612 do
613 {
614 int ha = *hp++;
615 int haa = fz_mul255(ha, alpha); /* ha = shape_alpha */
616 /* If haa == 0 then leave everything unchanged */
617 while (haa != 0) /* Use while, so we can break out */
618 {
619 int sa, ba, bahaa, ra, ra0, invsa, invba, scale;
620 sa = (sal ? sp[n1] : 255);
621 if (sa == 0)
622 break; /* No change! */
623 invsa = 255 * 256 / sa;
624 ba = (bal ? bp[n1] : 255);
625 if (ba == 0)
626 {
627 /* Just copy pixels (allowing for change in
628 * premultiplied alphas) */
629 for (k = 0; k < n1; k++)
630 bp[k] = fz_mul255((sp[k] * invsa) >> 8, haa);
631 if (bal)
632 bp[n1] = haa;
633 break;
634 }
635 invba = 255 * 256 / ba;
636
637 /* Because we are in a non-isolated group, we need to
638 * do some 'uncomposition' magic before we blend.
639 * My attempts to understand what is going on here have
640 * utterly failed, so I've resorted (after much patient
641 * help from Michael) to copying what the gs code does.
642 * This seems to be an implementation of the equations
643 * given on page 236 (section 7.3.3) of pdf_reference17.
644 * My understanding is that this is "composition" when
645 * we actually want to do "decomposition", hence my
646 * confusion. It appears to work though.
647 */
648 scale = (512 * ba + ha) / (ha*2) - FZ_EXPAND(ba);
649
650 sa = haa;
651
652 /* Calculate result_alpha - a combination of the
653 * background alpha, and 'shape' */
654 bahaa = fz_mul255(ba, haa);
655 ra0 = ba - bahaa;
656 ra = ra0 + haa;
657 if (bal)
658 bp[n1] = ra;
659
660 if (ra == 0)
661 break;
662
663 /* Process colorants */
664 for (k = 0; k < first_spot; k++)
665 {
666 /* Read pixels (and convert to non-premultiplied form) */
667 int sc = (sp[k] * invsa) >> 8;
668 int bc = (bp[k] * invba) >> 8;
669 int rc;
670
671 if (complement)
672 {
673 sc = 255 - sc;
674 bc = 255 - bc;
675 }
676
677 /* Uncomposite (see above) */
678 sc = sc + (((sc-bc) * scale)>>8);
679 sc = fz_clampi(sc, 0, 255);
680
681 switch (blendmode)
682 {
683 default:
684 case FZ_BLEND_NORMAL: rc = sc; break;
685 case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break;
686 case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break;
687 case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break;
688 case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break;
689 case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break;
690 case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break;
691 case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break;
692 case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break;
693 case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break;
694 case FZ_BLEND_DIFFERENCE: rc = fz_difference_byte(bc, sc); break;
695 case FZ_BLEND_EXCLUSION: rc = fz_exclusion_byte(bc, sc); break;
696 }
697
698 /* From the notes at the top:
699 *
700 * Ar * Cr = Cb * (Ar - alpha * As) + alpha * As * (1 - Ab) * Cs + alpha * As * Ab * B(Cb, Cs) ]
701 *
702 * And:
703 *
704 * Ar = ba + haa - bahaa
705 *
706 * In our 0..255 world, with our current variables:
707 *
708 * ra.rc = bc * (ra - haa) + haa * (255 - ba) * sc + bahaa * B(Cb, Cs)
709 * = bc * ra0 + haa * (255 - ba) * sc + bahaa * B(Cb, Cs)
710 */
711
712 if (bahaa != 255)
713 rc = fz_mul255(bahaa, rc);
714 if (ba != 255)
715 {
716 int t = fz_mul255(255 - ba, haa);
717 rc += fz_mul255(t, sc);
718 }
719 if (ra0 != 0)
720 rc += fz_mul255(ra0, bc);
721
722 if (complement)
723 rc = ra - rc;
724
725 bp[k] = fz_clampi(rc, 0, ra);
726 }
727
728 /* Spots */
729 for (; k < n1; k++)
730 {
731 int sc = 255 - ((sp[k] * invsa + 128) >> 8);
732 int bc = 255 - ((bp[k] * invba + 128) >> 8);
733 int rc;
734
735 sc = sc + (((sc-bc) * scale)>>8);
736
737 /* Non-white preserving use Normal */
738 switch (blendmode)
739 {
740 default:
741 case FZ_BLEND_NORMAL:
742 case FZ_BLEND_DIFFERENCE:
743 case FZ_BLEND_EXCLUSION:
744 rc = sc; break;
745 case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break;
746 case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break;
747 case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break;
748 case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break;
749 case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break;
750 case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break;
751 case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break;
752 case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break;
753 case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break;
754 }
755
756 if (bahaa != 255)
757 rc = fz_mul255(bahaa, rc);
758 if (ba != 255)
759 {
760 int t = fz_mul255(255 - ba, haa);
761 rc += fz_mul255(t, sc);
762 }
763 if (ra0 != 0)
764 rc += fz_mul255(ra0, bc);
765
766 bp[k] = ra - rc;
767 }
768 break;
769 }
770
771 sp += n1 + sal;
772 bp += n1 + bal;
773 }
774 while (--w);
775}
776
777static inline void
778fz_blend_nonseparable_nonisolated_gray(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n, int w, int blendmode, const byte * FZ_RESTRICT hp, int alpha, int first_spot)
779{
780 do
781 {
782 int ha = *hp++;
783 int haa = fz_mul255(ha, alpha);
784 if (haa != 0)
785 {
786 int ba = (bal ? bp[n] : 255);
787
788 if (ba == 0 && alpha == 255)
789 {
790 memcpy(bp, sp, n + (sal && bal));
791 if (bal && !sal)
792 bp[n+1] = 255;
793 }
794 else
795 {
796 int sa = (sal ? sp[n] : 255);
797 int bahaa = fz_mul255(ba, haa);
798 int k;
799
800 /* Calculate result_alpha */
801 int ra = ba - bahaa + haa;
802 if (bal)
803 bp[n] = ra;
804 if (ra != 0)
805 {
806 int invha = ha ? 255 * 256 / ha : 0;
807
808 /* ugh, division to get non-premul components */
809 int invsa = sa ? 255 * 256 / sa : 0;
810 int invba = ba ? 255 * 256 / ba : 0;
811
812 int sg = (sp[0] * invsa) >> 8;
813 int bg = (bp[0] * invba) >> 8;
814
815 /* Uncomposite */
816 sg = (((sg - bg)*invha) >> 8) + bg;
817 sg = fz_clampi(sg, 0, 255);
818
819 switch (blendmode)
820 {
821 default:
822 case FZ_BLEND_HUE:
823 case FZ_BLEND_SATURATION:
824 case FZ_BLEND_COLOR:
825 bp[0] = fz_mul255(ra, bg);
826 break;
827 case FZ_BLEND_LUMINOSITY:
828 bp[0] = fz_mul255(ra, sg);
829 break;
830 }
831
832 /* Normal blend for spots */
833 for (k = first_spot; k < n; k++)
834 {
835 int sc = (sp[k] * invsa + 128) >> 8;
836 int bc = (bp[k] * invba + 128) >> 8;
837 int rc;
838
839 sc = (((sc - bc) * invha + 128) >> 8) + bc;
840 sc = fz_clampi(sc, 0, 255);
841 rc = bc + fz_mul255(sa, fz_mul255(255 - ba, sc) + fz_mul255(ba, sc) - bc);
842 rc = fz_clampi(rc, 0, 255);
843 bp[k] = fz_mul255(rc, ra);
844 }
845 }
846 }
847 }
848 sp += n + sal;
849 bp += n + bal;
850 } while (--w);
851}
852
853static inline void
854fz_blend_nonseparable_nonisolated(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n, int w, int blendmode, int complement, const byte * FZ_RESTRICT hp, int alpha, int first_spot)
855{
856 do
857 {
858 int ha = *hp++;
859 int haa = fz_mul255(ha, alpha);
860 if (haa != 0)
861 {
862 int sa = (sal ? sp[n] : 255);
863 int ba = (bal ? bp[n] : 255);
864
865 if (ba == 0 && alpha == 255)
866 {
867 memcpy(bp, sp, n + (sal && bal));
868 if (bal && !sal)
869 bp[n] = 255;
870 }
871 else
872 {
873 int bahaa = fz_mul255(ba, haa);
874
875 /* Calculate result_alpha */
876 int ra0 = ba - bahaa;
877 int ra = ra0 + haa;
878
879 if (bal)
880 bp[n] = ra;
881
882 if (ra != 0)
883 {
884 /* Because we are a non-isolated group, we
885 * need to 'uncomposite' before we blend
886 * (recomposite). We assume that normal
887 * blending has been done inside the group,
888 * so: ra.rc = (1-ha).bc + ha.sc
889 * A bit of rearrangement, and that gives us
890 * that: sc = (ra.rc - bc)/ha + bc
891 * Now, the result of the blend was stored in
892 * src, so: */
893 int invha = ha ? 255 * 256 / ha : 0;
894 int k;
895 unsigned char rr, rg, rb;
896
897 /* ugh, division to get non-premul components */
898 int invsa = sa ? 255 * 256 / sa : 0;
899 int invba = ba ? 255 * 256 / ba : 0;
900
901 int sr = (sp[0] * invsa) >> 8;
902 int sg = (sp[1] * invsa) >> 8;
903 int sb = (sp[2] * invsa) >> 8;
904
905 int br = (bp[0] * invba) >> 8;
906 int bg = (bp[1] * invba) >> 8;
907 int bb = (bp[2] * invba) >> 8;
908
909 if (complement)
910 {
911 sr = 255 - sr;
912 sg = 255 - sg;
913 sb = 255 - sb;
914 br = 255 - br;
915 bg = 255 - bg;
916 bb = 255 - bb;
917 }
918
919 /* Uncomposite */
920 sr = (((sr - br)*invha) >> 8) + br;
921 sr = fz_clampi(sr, 0, 255);
922 sg = (((sg - bg)*invha) >> 8) + bg;
923 sg = fz_clampi(sg, 0, 255);
924 sb = (((sb - bb)*invha) >> 8) + bb;
925 sb = fz_clampi(sb, 0, 255);
926
927 switch (blendmode)
928 {
929 default:
930 case FZ_BLEND_HUE:
931 fz_hue_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
932 break;
933 case FZ_BLEND_SATURATION:
934 fz_saturation_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
935 break;
936 case FZ_BLEND_COLOR:
937 fz_color_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
938 break;
939 case FZ_BLEND_LUMINOSITY:
940 fz_luminosity_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
941 break;
942 }
943
944 /* From the notes at the top:
945 *
946 * Ar * Cr = Cb * (Ar - alpha * As) + alpha * As * (1 - Ab) * Cs + alpha * As * Ab * B(Cb, Cs) ]
947 *
948 * And:
949 *
950 * Ar = ba + haa - bahaa
951 *
952 * In our 0..255 world, with our current variables:
953 *
954 * ra.rc = bc * (ra - haa) + haa * (255 - ba) * sc + bahaa * B(Cb, Cs)
955 * = bc * ra0 + haa * (255 - ba) * sc + bahaa * B(Cb, Cs)
956 */
957
958 if (bahaa != 255)
959 {
960 rr = fz_mul255(bahaa, rr);
961 rg = fz_mul255(bahaa, rg);
962 rb = fz_mul255(bahaa, rb);
963 }
964 if (ba != 255)
965 {
966 int t = fz_mul255(255 - ba, haa);
967 rr += fz_mul255(t, sr);
968 rg += fz_mul255(t, sg);
969 rb += fz_mul255(t, sb);
970 }
971 if (ra0 != 0)
972 {
973 rr += fz_mul255(ra0, br);
974 rg += fz_mul255(ra0, bg);
975 rb += fz_mul255(ra0, bb);
976 }
977
978 /* CMYK */
979 if (complement)
980 {
981 int sk, bk, rk;
982
983 /* Care must be taking when inverting here, as r = alpha * col.
984 * We want to store alpha * (255 - col) = alpha * 255 - alpha * col
985 */
986 rr = ra - rr;
987 rg = ra - rg;
988 rb = ra - rb;
989
990 sk = sa ? (sp[3] * invsa) >> 8 : 255;
991 bk = ba ? (bp[3] * invba) >> 8 : 255;
992
993 bk = fz_clampi(bk, 0, 255);
994 sk = fz_clampi(sk, 0, 255);
995
996 if (blendmode == FZ_BLEND_LUMINOSITY)
997 rk = sk;
998 else
999 rk = bk;
1000
1001 if (bahaa != 255)
1002 rk = fz_mul255(bahaa, rk);
1003
1004 if (ba != 255)
1005 {
1006 int t = fz_mul255(255 - ba, haa);
1007 rk += fz_mul255(t, sk);
1008 }
1009
1010 if (ra0 != 0)
1011 rk += fz_mul255(ra0, bk);
1012
1013 bp[3] = rk;
1014 }
1015
1016 bp[0] = rr;
1017 bp[1] = rg;
1018 bp[2] = rb;
1019
1020 /* Normal blend for spots */
1021 for (k = first_spot; k < n; k++)
1022 {
1023 int sc = (sp[k] * invsa + 128) >> 8;
1024 int bc = (bp[k] * invba + 128) >> 8;
1025 int rc;
1026
1027 sc = (((sc - bc) * invha + 128) >> 8) + bc;
1028 sc = fz_clampi(sc, 0, 255);
1029 rc = bc + fz_mul255(ha, fz_mul255(255 - ba, sc) + fz_mul255(ba, sc) - bc);
1030 rc = fz_clampi(rc, 0, 255);
1031 bp[k] = fz_mul255(rc, ra);
1032 }
1033 }
1034 }
1035 }
1036 sp += n + sal;
1037 bp += n + bal;
1038 }
1039 while (--w);
1040}
1041
1042#ifdef PARANOID_PREMULTIPLY
1043static void
1044verify_premultiply(fz_context *ctx, const fz_pixmap * FZ_RESTRICT dst)
1045{
1046 unsigned char *dp = dst->samples;
1047 int w = dst->w;
1048 int h = dst->h;
1049 int n = dst->n;
1050 int x, y, i;
1051 int s = dst->stride - n * w;
1052
1053 for (y = h; y > 0; y--)
1054 {
1055 for (x = w; x > 0; x--)
1056 {
1057 int a = dp[n-1];
1058 for (i = n-1; i > 0; i--)
1059 if (*dp++ > a)
1060 abort();
1061 dp++;
1062 }
1063 dp += s;
1064 }
1065}
1066#endif
1067
1068void
1069fz_blend_pixmap(fz_context *ctx, fz_pixmap * FZ_RESTRICT dst, fz_pixmap * FZ_RESTRICT src, int alpha, int blendmode, int isolated, const fz_pixmap * FZ_RESTRICT shape)
1070{
1071 unsigned char *sp;
1072 unsigned char *dp;
1073 fz_irect bbox;
1074 int x, y, w, h, n;
1075 int da, sa;
1076 int complement;
1077
1078 /* TODO: fix this hack! */
1079 if (isolated && alpha < 255)
1080 {
1081 unsigned char *sp2;
1082 int nn;
1083 h = src->h;
1084 sp2 = src->samples;
1085 nn = src->w * src->n;
1086 while (h--)
1087 {
1088 n = nn;
1089 while (n--)
1090 {
1091 *sp2 = fz_mul255(*sp2, alpha);
1092 sp2++;
1093 }
1094 sp2 += src->stride - nn;
1095 }
1096 }
1097
1098 bbox = fz_intersect_irect(fz_pixmap_bbox(ctx, src), fz_pixmap_bbox(ctx, dst));
1099
1100 x = bbox.x0;
1101 y = bbox.y0;
1102 w = bbox.x1 - bbox.x0;
1103 h = bbox.y1 - bbox.y0;
1104
1105 if (w == 0 || h == 0)
1106 return;
1107
1108 complement = fz_colorspace_is_subtractive(ctx, src->colorspace);
1109 n = src->n;
1110 sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
1111 sa = src->alpha;
1112 dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
1113 da = dst->alpha;
1114
1115#ifdef PARANOID_PREMULTIPLY
1116 if (sa)
1117 verify_premultiply(ctx, src);
1118 if (da)
1119 verify_premultiply(ctx, dst);
1120#endif
1121
1122 n -= sa;
1123 assert(n == dst->n - da);
1124
1125 if (!isolated)
1126 {
1127 const unsigned char *hp = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (x - shape->x));
1128
1129 while (h--)
1130 {
1131 if (blendmode >= FZ_BLEND_HUE)
1132 {
1133 if (complement || src->s > 0)
1134 if ((n - src->s) == 1)
1135 fz_blend_nonseparable_nonisolated_gray(dp, da, sp, sa, n, w, blendmode, hp, alpha, 1);
1136 else
1137 fz_blend_nonseparable_nonisolated(dp, da, sp, sa, n, w, blendmode, complement, hp, alpha, n - src->s);
1138 else
1139 if (da)
1140 if (sa)
1141 if (n == 1)
1142 fz_blend_nonseparable_nonisolated_gray(dp, 1, sp, 1, 1, w, blendmode, hp, alpha, 1);
1143 else
1144 fz_blend_nonseparable_nonisolated(dp, 1, sp, 1, n, w, blendmode, complement, hp, alpha, n);
1145 else
1146 if (n == 1)
1147 fz_blend_nonseparable_nonisolated_gray(dp, 1, sp, 0, 1, w, blendmode, hp, alpha, 1);
1148 else
1149 fz_blend_nonseparable_nonisolated(dp, 1, sp, 0, n, w, blendmode, complement, hp, alpha, n);
1150 else
1151 if (sa)
1152 if (n == 1)
1153 fz_blend_nonseparable_nonisolated_gray(dp, 0, sp, 1, 1, w, blendmode, hp, alpha, 1);
1154 else
1155 fz_blend_nonseparable_nonisolated(dp, 0, sp, 1, n, w, blendmode, complement, hp, alpha, n);
1156 else
1157 if (n == 1)
1158 fz_blend_nonseparable_nonisolated_gray(dp, 0, sp, 0, 1, w, blendmode, hp, alpha, 1);
1159 else
1160 fz_blend_nonseparable_nonisolated(dp, 0, sp, 0, n, w, blendmode, complement, hp, alpha, n);
1161 }
1162 else
1163 {
1164 if (complement || src->s > 0)
1165 fz_blend_separable_nonisolated(dp, da, sp, sa, n, w, blendmode, complement, hp, alpha, n - src->s);
1166 else
1167 if (da)
1168 if (sa)
1169 fz_blend_separable_nonisolated(dp, 1, sp, 1, n, w, blendmode, 0, hp, alpha, n);
1170 else
1171 fz_blend_separable_nonisolated(dp, 1, sp, 0, n, w, blendmode, 0, hp, alpha, n);
1172 else
1173 if (sa)
1174 fz_blend_separable_nonisolated(dp, 0, sp, 1, n, w, blendmode, 0, hp, alpha, n);
1175 else
1176 fz_blend_separable_nonisolated(dp, 0, sp, 0, n, w, blendmode, 0, hp, alpha, n);
1177 }
1178 sp += src->stride;
1179 dp += dst->stride;
1180 hp += shape->stride;
1181 }
1182 }
1183 else
1184 {
1185 while (h--)
1186 {
1187 if (blendmode >= FZ_BLEND_HUE)
1188 {
1189 if (complement || src->s > 0)
1190 if ((n - src->s) == 1)
1191 fz_blend_nonseparable_gray(dp, da, sp, sa, n, w, blendmode, 1);
1192 else
1193 fz_blend_nonseparable(dp, da, sp, sa, n, w, blendmode, complement, n - src->s);
1194 else
1195 if (da)
1196 if (sa)
1197 if (n == 1)
1198 fz_blend_nonseparable_gray(dp, 1, sp, 1, 1, w, blendmode, 1);
1199 else
1200 fz_blend_nonseparable(dp, 1, sp, 1, n, w, blendmode, complement, n);
1201 else
1202 if (n == 1)
1203 fz_blend_nonseparable_gray(dp, 1, sp, 0, 1, w, blendmode, 1);
1204 else
1205 fz_blend_nonseparable(dp, 1, sp, 0, n, w, blendmode, complement, n);
1206 else
1207 if (sa)
1208 if (n == 1)
1209 fz_blend_nonseparable_gray(dp, 0, sp, 1, 1, w, blendmode, 1);
1210 else
1211 fz_blend_nonseparable(dp, 0, sp, 1, n, w, blendmode, complement, n);
1212 else
1213 if (n == 1)
1214 fz_blend_nonseparable_gray(dp, 0, sp, 0, 1, w, blendmode, 1);
1215 else
1216 fz_blend_nonseparable(dp, 0, sp, 0, n, w, blendmode, complement, n);
1217 }
1218 else
1219 {
1220 if (complement || src->s > 0)
1221 fz_blend_separable(dp, da, sp, sa, n, w, blendmode, complement, n - src->s);
1222 else
1223 if (da)
1224 if (sa)
1225 fz_blend_separable(dp, 1, sp, 1, n, w, blendmode, 0, n);
1226 else
1227 fz_blend_separable(dp, 1, sp, 0, n, w, blendmode, 0, n);
1228 else
1229 if (sa)
1230 fz_blend_separable(dp, 0, sp, 1, n, w, blendmode, 0, n);
1231 else
1232 fz_blend_separable(dp, 0, sp, 0, n, w, blendmode, 0, n);
1233 }
1234 sp += src->stride;
1235 dp += dst->stride;
1236 }
1237 }
1238
1239#ifdef PARANOID_PREMULTIPLY
1240 if (da)
1241 verify_premultiply(ctx, dst);
1242#endif
1243}
1244
1245static inline void
1246fz_blend_knockout(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n1, int w, const byte * FZ_RESTRICT hp)
1247{
1248 int k;
1249 do
1250 {
1251 int ha = *hp++;
1252
1253 if (ha != 0)
1254 {
1255 int sa = (sal ? sp[n1] : 255);
1256 int ba = (bal ? bp[n1] : 255);
1257 if (ba == 0 && ha == 0xFF)
1258 {
1259 memcpy(bp, sp, n1);
1260 if (bal)
1261 bp[n1] = sa;
1262 }
1263 else
1264 {
1265 int hasa = fz_mul255(ha, sa);
1266 /* ugh, division to get non-premul components */
1267 int invsa = sa ? 255 * 256 / sa : 0;
1268 int invba = ba ? 255 * 256 / ba : 0;
1269 int ra = hasa + fz_mul255(255-ha, ba);
1270
1271 /* Process colorants + spots */
1272 for (k = 0; k < n1; k++)
1273 {
1274 int sc = (sp[k] * invsa) >> 8;
1275 int bc = (bp[k] * invba) >> 8;
1276 int rc = fz_mul255(255 - ha, bc) + fz_mul255(ha, sc);
1277
1278 bp[k] = fz_mul255(ra, rc);
1279 }
1280
1281 if (bal)
1282 bp[k] = ra;
1283 }
1284 }
1285 sp += n1 + sal;
1286 bp += n1 + bal;
1287 }
1288 while (--w);
1289}
1290
1291void
1292fz_blend_pixmap_knockout(fz_context *ctx, fz_pixmap * FZ_RESTRICT dst, fz_pixmap * FZ_RESTRICT src, const fz_pixmap * FZ_RESTRICT shape)
1293{
1294 unsigned char *sp;
1295 unsigned char *dp;
1296 fz_irect sbox, dbox, bbox;
1297 int x, y, w, h, n;
1298 int da, sa;
1299 const unsigned char *hp;
1300
1301 dbox = fz_pixmap_bbox_no_ctx(dst);
1302 sbox = fz_pixmap_bbox_no_ctx(src);
1303 bbox = fz_intersect_irect(dbox, sbox);
1304
1305 x = bbox.x0;
1306 y = bbox.y0;
1307 w = bbox.x1 - bbox.x0;
1308 h = bbox.y1 - bbox.y0;
1309
1310 if (w == 0 || h == 0)
1311 return;
1312
1313 n = src->n;
1314 sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
1315 sa = src->alpha;
1316 dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
1317 da = dst->alpha;
1318 hp = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (x - shape->x));
1319
1320#ifdef PARANOID_PREMULTIPLY
1321 if (sa)
1322 verify_premultiply(ctx, src);
1323 if (da)
1324 verify_premultiply(ctx, dst);
1325#endif
1326
1327 n -= sa;
1328 assert(n == dst->n - da);
1329
1330 while (h--)
1331 {
1332 fz_blend_knockout(dp, da, sp, sa, n, w, hp);
1333 sp += src->stride;
1334 dp += dst->stride;
1335 hp += shape->stride;
1336 }
1337
1338#ifdef PARANOID_PREMULTIPLY
1339 if (da)
1340 verify_premultiply(ctx, dst);
1341#endif
1342}
1343