1#include "mupdf/fitz.h"
2#include "draw-imp.h"
3
4#include <string.h>
5#include <assert.h>
6
7/*
8
9The functions in this file implement various flavours of Porter-Duff blending.
10
11We take the following as definitions:
12
13 Cx = Color (from plane x)
14 ax = Alpha (from plane x)
15 cx = Cx.ax = Premultiplied color (from plane x)
16
17The general PorterDuff blending equation is:
18
19 Blend Z = X op Y cz = Fx.cx + Fy.cy where Fx and Fy depend on op
20
21The two operations we use in this file are: '(X in Y) over Z' and
22'S over Z'. The definitions of the 'over' and 'in' operations are as
23follows:
24
25 For S over Z, Fs = 1, Fz = 1-as
26 For X in Y, Fx = ay, Fy = 0
27
28We have 2 choices; we can either work with premultiplied data, or non
29premultiplied data. Our
30
31First the premultiplied case:
32
33 Let S = (X in Y)
34 Let R = (X in Y) over Z = S over Z
35
36 cs = cx.Fx + cy.Fy (where Fx = ay, Fy = 0)
37 = cx.ay
38 as = ax.Fx + ay.Fy
39 = ax.ay
40
41 cr = cs.Fs + cz.Fz (where Fs = 1, Fz = 1-as)
42 = cs + cz.(1-as)
43 = cx.ay + cz.(1-ax.ay)
44 ar = as.Fs + az.Fz
45 = as + az.(1-as)
46 = ax.ay + az.(1-ax.ay)
47
48This has various nice properties, like not needing any divisions, and
49being symmetric in color and alpha, so this is what we use. Because we
50went through the pain of deriving the non premultiplied forms, we list
51them here too, though they are not used.
52
53Non Pre-multiplied case:
54
55 Cs.as = Fx.Cx.ax + Fy.Cy.ay (where Fx = ay, Fy = 0)
56 = Cx.ay.ax
57 Cs = (Cx.ay.ax)/(ay.ax)
58 = Cx
59 Cr.ar = Fs.Cs.as + Fz.Cz.az (where Fs = 1, Fz = 1-as)
60 = Cs.as + (1-as).Cz.az
61 = Cx.ax.ay + Cz.az.(1-ax.ay)
62 Cr = (Cx.ax.ay + Cz.az.(1-ax.ay))/(ax.ay + az.(1-ax.ay))
63
64Much more complex, it seems. However, if we could restrict ourselves to
65the case where we were always plotting onto an opaque background (i.e.
66az = 1), then:
67
68 Cr = Cx.(ax.ay) + Cz.(1-ax.ay)
69 = (Cx-Cz)*(1-ax.ay) + Cz (a single MLA operation)
70 ar = 1
71
72Sadly, this is not true in the general case, so we abandon this effort
73and stick to using the premultiplied form.
74
75*/
76
77typedef unsigned char byte;
78
79/* These are used by the non-aa scan converter */
80
81static inline void
82template_solid_color_1_da(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da)
83{
84 int sa = FZ_EXPAND(color[1]);
85 TRACK_FN();
86 if (sa == 0)
87 return;
88 if (sa == 256)
89 {
90 do
91 {
92 dp[0] = color[0];
93 dp[1] = 255;
94 dp += 2;
95 }
96 while (--w);
97 }
98 else
99 {
100 do
101 {
102 dp[0] = FZ_BLEND(color[0], dp[0], sa);
103 dp[1] = FZ_BLEND(255, dp[1], sa);
104 dp += 2;
105 }
106 while (--w);
107 }
108}
109
110static inline int isbigendian(void)
111{
112 union { int i; char c[sizeof(int)]; } u = {1};
113 return u.c[0] != 1;
114}
115
116static inline void
117template_solid_color_3_da(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da)
118{
119 unsigned int rgba = *(int *)color;
120 int sa = FZ_EXPAND(color[3]);
121 TRACK_FN();
122 if (sa == 0)
123 return;
124 if (isbigendian())
125 rgba |= 0x000000FF;
126 else
127 rgba |= 0xFF000000;
128 if (sa == 256)
129 {
130 do
131 {
132 *(unsigned int *)dp = rgba;
133 dp += 4;
134 }
135 while (--w);
136 }
137 else
138 {
139 unsigned int mask = 0xFF00FF00;
140 unsigned int rb = rgba & (mask>>8);
141 unsigned int ga = (rgba & mask)>>8;
142 do
143 {
144 unsigned int RGBA = *(unsigned int *)dp;
145 unsigned int RB = (RGBA<<8) & mask;
146 unsigned int GA = RGBA & mask;
147 RB += (rb-(RB>>8))*sa;
148 GA += (ga-(GA>>8))*sa;
149 RB &= mask;
150 GA &= mask;
151 *(unsigned int *)dp = (RB>>8) | GA;
152 dp += 4;
153 }
154 while (--w);
155 }
156}
157
158static inline void
159template_solid_color_4_da(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da)
160{
161 int sa = FZ_EXPAND(color[4]);
162 TRACK_FN();
163 if (sa == 0)
164 return;
165 if (sa == 256)
166 {
167#ifdef ARCH_UNALIGNED_OK
168 if (w > 4)
169 {
170 if (isbigendian())
171 {
172 const uint32_t a = *(uint32_t*)color;
173 const uint32_t b = 0xFF000000|(a>>8);
174 const uint32_t c = 0x00FF0000|(a>>16)|(a<<24);
175 const uint32_t d = 0x0000FF00|(a>>24)|(a<<16);
176 const uint32_t e = 0x000000FF|(a<<8);
177 w -= 3;
178 do
179 {
180 ((uint32_t *)(void *)dp)[0] = a;
181 ((uint32_t *)(void *)dp)[1] = b;
182 ((uint32_t *)(void *)dp)[2] = c;
183 ((uint32_t *)(void *)dp)[3] = d;
184 ((uint32_t *)(void *)dp)[4] = e;
185 dp += 20;
186 w -= 4;
187 }
188 while (w > 0);
189 }
190 else
191 {
192 const uint32_t a = *(uint32_t*)color;
193 const uint32_t b = 0x000000FF|(a<<8);
194 const uint32_t c = 0x0000FF00|(a<<16)|(a>>24);
195 const uint32_t d = 0x00FF0000|(a<<24)|(a>>16);
196 const uint32_t e = 0xFF000000|(a>>8);
197 w -= 3;
198 do
199 {
200 ((uint32_t *)(void *)dp)[0] = a;
201 ((uint32_t *)(void *)dp)[1] = b;
202 ((uint32_t *)(void *)dp)[2] = c;
203 ((uint32_t *)(void *)dp)[3] = d;
204 ((uint32_t *)(void *)dp)[4] = e;
205 dp += 20;
206 w -= 4;
207 }
208 while (w > 0);
209 }
210 w += 3;
211 if (w == 0)
212 return;
213 }
214#endif
215 do
216 {
217 dp[0] = color[0];
218 dp[1] = color[1];
219 dp[2] = color[2];
220 dp[3] = color[3];
221 dp[4] = 255;
222 dp += 5;
223 }
224 while (--w);
225 }
226 else
227 {
228 do
229 {
230 dp[0] = FZ_BLEND(color[0], dp[0], sa);
231 dp[1] = FZ_BLEND(color[1], dp[1], sa);
232 dp[2] = FZ_BLEND(color[2], dp[2], sa);
233 dp[3] = FZ_BLEND(color[3], dp[3], sa);
234 dp[4] = FZ_BLEND(255, dp[5], sa);
235 dp += 5;
236 }
237 while (--w);
238 }
239}
240
241static inline void
242template_solid_color_N_256(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da)
243{
244 int k;
245 int n1 = n - da;
246 if (n == 3 && da == 0 && w >= 8)
247 {
248 union {uint32_t w[3]; byte b[12];} u;
249
250 u.b[0] = u.b[3] = u.b[6] = u.b[9] = color[0];
251 u.b[1] = u.b[4] = u.b[7] = u.b[10] = color[1];
252 u.b[2] = u.b[5] = u.b[8] = u.b[11] = color[2];
253
254 switch (((intptr_t)dp) & 3)
255 {
256 case 3:
257 *dp++ = color[0];
258 *(uint32_t *)dp = u.w[1];
259 dp += 4;
260 *(uint32_t *)dp = u.w[2];
261 dp += 4;
262 w -= 3;
263 break;
264 case 2:
265 *dp++ = color[0];
266 *dp++ = color[1];
267 *(uint32_t *)dp = u.w[2];
268 dp += 4;
269 w -= 2;
270 break;
271 case 1:
272 *dp++ = color[0];
273 *dp++ = color[1];
274 *dp++ = color[2];
275 w -= 1;
276 break;
277 }
278 w -= 4;
279 do
280 {
281 *(uint32_t *)dp = u.w[0];
282 dp += 4;
283 *(uint32_t *)dp = u.w[1];
284 dp += 4;
285 *(uint32_t *)dp = u.w[2];
286 dp += 4;
287 w -= 4;
288 }
289 while (w > 0);
290 w += 4;
291 if (w == 0)
292 return;
293 }
294 do
295 {
296 dp[0] = color[0];
297 if (n1 > 1)
298 dp[1] = color[1];
299 if (n1 > 2)
300 dp[2] = color[2];
301 for (k = 3; k < n1; k++)
302 dp[k] = color[k];
303 if (da)
304 dp[n1] = 255;
305 dp += n;
306 }
307 while (--w);
308}
309
310static inline void
311template_solid_color_N_256_op(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
312{
313 int k;
314 int n1 = n - da;
315 do
316 {
317 if (fz_overprint_component(eop, 0))
318 dp[0] = color[0];
319 if (n1 > 1)
320 if (fz_overprint_component(eop, 1))
321 dp[1] = color[1];
322 if (n1 > 2)
323 if (fz_overprint_component(eop, 2))
324 dp[2] = color[2];
325 for (k = 3; k < n1; k++)
326 if (fz_overprint_component(eop, k))
327 dp[k] = color[k];
328 if (da)
329 dp[n1] = 255;
330 dp += n;
331 }
332 while (--w);
333}
334
335static inline void
336template_solid_color_N_sa(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, int sa)
337{
338 int k;
339 int n1 = n - da;
340 do
341 {
342 for (k = 0; k < n1; k++)
343 dp[k] = FZ_BLEND(color[k], dp[k], sa);
344 if (da)
345 dp[k] = FZ_BLEND(255, dp[k], sa);
346 dp += n;
347 }
348 while (--w);
349}
350
351static inline void
352template_solid_color_N_sa_op(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, int sa, const fz_overprint * FZ_RESTRICT eop)
353{
354 int k;
355 int n1 = n - da;
356 do
357 {
358 for (k = 0; k < n1; k++)
359 if (fz_overprint_component(eop, k))
360 dp[k] = FZ_BLEND(color[k], dp[k], sa);
361 if (da)
362 dp[k] = FZ_BLEND(255, dp[k], sa);
363 dp += n;
364 }
365 while (--w);
366}
367
368#if FZ_PLOTTERS_N
369static inline void
370template_solid_color_N_general(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, int sa)
371{
372 int k;
373 int n1 = n - da;
374 if (sa == 256)
375 {
376 do
377 {
378 dp[0] = color[0];
379 if (n1 > 1)
380 dp[1] = color[1];
381 if (n1 > 2)
382 dp[2] = color[2];
383 for (k = 3; k < n1; k++)
384 dp[k] = color[k];
385 if (da)
386 dp[n1] = 255;
387 dp += n;
388 }
389 while (--w);
390 }
391 else
392 {
393 do
394 {
395 for (k = 0; k < n1; k++)
396 dp[k] = FZ_BLEND(color[k], dp[k], sa);
397 if (da)
398 dp[k] = FZ_BLEND(255, dp[k], sa);
399 dp += n;
400 }
401 while (--w);
402 }
403}
404
405static inline void
406template_solid_color_N_general_op(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, int sa, const fz_overprint * FZ_RESTRICT eop)
407{
408 int k;
409 int n1 = n - da;
410 if (sa == 256)
411 {
412 do
413 {
414 if (fz_overprint_component(eop, 0))
415 dp[0] = color[0];
416 if (n1 > 1)
417 if (fz_overprint_component(eop, 1))
418 dp[1] = color[1];
419 if (n1 > 2)
420 if (fz_overprint_component(eop, 2))
421 dp[2] = color[2];
422 for (k = 3; k < n1; k++)
423 if (fz_overprint_component(eop, k))
424 dp[k] = color[k];
425 if (da)
426 dp[n1] = 255;
427 dp += n;
428 }
429 while (--w);
430 }
431 else
432 {
433 do
434 {
435 for (k = 0; k < n1; k++)
436 if (fz_overprint_component(eop, k))
437 dp[k] = FZ_BLEND(color[k], dp[k], sa);
438 if (da)
439 dp[k] = FZ_BLEND(255, dp[k], sa);
440 dp += n;
441 }
442 while (--w);
443 }
444}
445#endif
446
447static inline void
448template_solid_color_0_da(byte * FZ_RESTRICT dp, int w, int sa)
449{
450 if (sa == 256)
451 {
452 memset(dp, 255, w);
453 }
454 else
455 {
456 do
457 {
458 *dp = FZ_BLEND(255, *dp, sa);
459 dp++;
460 }
461 while (--w);
462 }
463}
464
465#if FZ_PLOTTERS_G
466static void paint_solid_color_1_alpha(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
467{
468 TRACK_FN();
469 template_solid_color_N_sa(dp, 1, w, color, 0, FZ_EXPAND(color[1]));
470}
471
472static void paint_solid_color_1(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
473{
474 TRACK_FN();
475 template_solid_color_N_256(dp, 1, w, color, 0);
476}
477
478static void paint_solid_color_1_da(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
479{
480 TRACK_FN();
481 template_solid_color_1_da(dp, 2, w, color, 1);
482}
483#endif /* FZ_PLOTTERS_G */
484
485static void paint_solid_color_0_da(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
486{
487 TRACK_FN();
488 template_solid_color_0_da(dp, w, 256);
489}
490
491#if FZ_PLOTTERS_RGB
492static void paint_solid_color_3_alpha(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
493{
494 TRACK_FN();
495 template_solid_color_N_sa(dp, 3, w, color, 0, FZ_EXPAND(color[3]));
496}
497
498static void paint_solid_color_3(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
499{
500 TRACK_FN();
501 template_solid_color_N_256(dp, 3, w, color, 0);
502}
503
504static void paint_solid_color_3_da(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
505{
506 TRACK_FN();
507 template_solid_color_3_da(dp, 4, w, color, 1);
508}
509#endif /* FZ_PLOTTERS_RGB */
510
511#if FZ_PLOTTERS_CMYK
512static void paint_solid_color_4_alpha(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
513{
514 TRACK_FN();
515 template_solid_color_N_sa(dp, 4, w, color, 0, FZ_EXPAND(color[4]));
516}
517
518static void paint_solid_color_4(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
519{
520 TRACK_FN();
521 template_solid_color_N_256(dp, 4, w, color, 0);
522}
523
524static void paint_solid_color_4_da(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
525{
526 TRACK_FN();
527 template_solid_color_4_da(dp, 5, w, color, 1);
528}
529#endif /* FZ_PLOTTERS_CMYK */
530
531#if FZ_PLOTTERS_N
532static void paint_solid_color_N_alpha(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
533{
534 TRACK_FN();
535 template_solid_color_N_sa(dp, n, w, color, 0, FZ_EXPAND(color[n]));
536}
537
538static void paint_solid_color_N(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
539{
540 TRACK_FN();
541 template_solid_color_N_256(dp, n, w, color, 0);
542}
543
544static void paint_solid_color_N_da(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
545{
546 TRACK_FN();
547 template_solid_color_N_general(dp, n, w, color, 1, FZ_EXPAND(color[n-1]));
548}
549#endif /* FZ_PLOTTERS_N */
550
551#ifdef FZ_ENABLE_SPOT_RENDERING
552static void paint_solid_color_N_alpha_op(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
553{
554 TRACK_FN();
555 template_solid_color_N_sa_op(dp, n, w, color, 0, FZ_EXPAND(color[n]), eop);
556}
557
558static void paint_solid_color_N_op(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
559{
560 TRACK_FN();
561 template_solid_color_N_256_op(dp, n, w, color, 0, eop);
562}
563
564static void paint_solid_color_N_da_op(byte * FZ_RESTRICT dp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
565{
566 TRACK_FN();
567 template_solid_color_N_general_op(dp, n, w, color, 1, FZ_EXPAND(color[n-1]), eop);
568}
569#endif /* FZ_ENABLE_SPOT_RENDERING */
570
571fz_solid_color_painter_t *
572fz_get_solid_color_painter(int n, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
573{
574#if FZ_ENABLE_SPOT_RENDERING
575 if (fz_overprint_required(eop))
576 {
577 if (da)
578 return paint_solid_color_N_da_op;
579 else if (color[n] == 255)
580 return paint_solid_color_N_op;
581 else
582 return paint_solid_color_N_alpha_op;
583 }
584#endif /* FZ_ENABLE_SPOT_RENDERING */
585 switch (n-da)
586 {
587 case 0:
588 return paint_solid_color_0_da;
589#if FZ_PLOTTERS_G
590 case 1:
591 if (da)
592 return paint_solid_color_1_da;
593 else if (color[1] == 255)
594 return paint_solid_color_1;
595 else
596 return paint_solid_color_1_alpha;
597#endif /* FZ_PLOTTERS_G */
598#if FZ_PLOTTERS_RGB
599 case 3:
600 if (da)
601 return paint_solid_color_3_da;
602 else if (color[3] == 255)
603 return paint_solid_color_3;
604 else
605 return paint_solid_color_3_alpha;
606#endif /* FZ_PLOTTERS_RGB */
607#if FZ_PLOTTERS_CMYK
608 case 4:
609 if (da)
610 return paint_solid_color_4_da;
611 else if (color[4] == 255)
612 return paint_solid_color_4;
613 else
614 return paint_solid_color_4_alpha;
615#endif /* FZ_PLOTTERS_CMYK */
616 default:
617#if FZ_PLOTTERS_N
618 if (da)
619 return paint_solid_color_N_da;
620 else if (color[n] == 255)
621 return paint_solid_color_N;
622 else
623 return paint_solid_color_N_alpha;
624#else
625 return NULL;
626#endif /* FZ_PLOTTERS_N */
627 }
628}
629
630/* Blend a non-premultiplied color in mask over destination */
631
632static inline void
633template_span_with_color_1_da(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da)
634{
635 int sa = FZ_EXPAND(color[1]);
636 int g = color[0];
637 if (sa == 256)
638 {
639 do
640 {
641 int ma = *mp++;
642 ma = FZ_EXPAND(ma);
643 if (ma == 0)
644 {
645 }
646 else if (ma == 256)
647 {
648 dp[0] = g;
649 dp[1] = 255;
650 }
651 else
652 {
653 dp[0] = FZ_BLEND(g, dp[0], ma);
654 dp[1] = FZ_BLEND(255, dp[1], ma);
655 }
656 dp += 2;
657 }
658 while (--w);
659 }
660 else
661 {
662 do
663 {
664 int ma = *mp++;
665 ma = FZ_EXPAND(ma);
666 if (ma == 0)
667 {
668 }
669 else
670 {
671 ma = FZ_COMBINE(ma, sa);
672 dp[0] = FZ_BLEND(g, dp[0], ma);
673 dp[1] = FZ_BLEND(255, dp[1], ma);
674 }
675 dp += 2;
676 }
677 while (--w);
678 }
679}
680
681static inline void
682template_span_with_color_3_da(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da)
683{
684 unsigned int rgba = *((const unsigned int *)color);
685 unsigned int mask, rb, ga;
686 int sa = FZ_EXPAND(color[3]);
687 if (sa == 0)
688 return;
689 if (isbigendian())
690 rgba |= 0x000000FF;
691 else
692 rgba |= 0xFF000000;
693 mask = 0xFF00FF00;
694 rb = rgba & (mask>>8);
695 ga = (rgba & mask)>>8;
696 if (sa == 256)
697 {
698 do
699 {
700 unsigned int ma = *mp++;
701 dp += 4;
702 ma = FZ_EXPAND(ma);
703 if (ma == 0)
704 {
705 }
706 else if (ma == 256)
707 {
708 ((unsigned int *)dp)[-1] = rgba;
709 }
710 else
711 {
712 unsigned int RGBA = ((unsigned int *)dp)[-1];
713 unsigned int RB = (RGBA<<8) & mask;
714 unsigned int GA = RGBA & mask;
715 RB += (rb-(RB>>8))*ma;
716 GA += (ga-(GA>>8))*ma;
717 RB &= mask;
718 GA &= mask;
719 ((unsigned int *)dp)[-1] = (RB>>8) | GA;
720 }
721 }
722 while (--w);
723 }
724 else
725 {
726 do
727 {
728 unsigned int ma = *mp++;
729 ma = FZ_COMBINE(FZ_EXPAND(ma), sa);
730 dp += 4;
731 if (ma != 0)
732 {
733 unsigned int RGBA = ((unsigned int*)dp)[-1];
734 unsigned int RB = (RGBA<<8) & mask;
735 unsigned int GA = RGBA & mask;
736 RB += (rb-(RB>>8))*ma;
737 GA += (ga-(GA>>8))*ma;
738 RB &= mask;
739 GA &= mask;
740 ((unsigned int *)dp)[-1] = (RB>>8) | GA;
741 }
742 }
743 while (--w);
744 }
745}
746
747static inline void
748template_span_with_color_4_da(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da)
749{
750 int sa = FZ_EXPAND(color[4]);
751 int c = color[0];
752 int m = color[1];
753 int y = color[2];
754 int k = color[3];
755 TRACK_FN();
756 if (sa == 256)
757 {
758 do
759 {
760 int ma = *mp++;
761 ma = FZ_EXPAND(ma);
762 if (ma == 0)
763 {
764 }
765 else if (ma == 256)
766 {
767 dp[0] = c;
768 dp[1] = m;
769 dp[2] = y;
770 dp[3] = k;
771 dp[4] = 255;
772 }
773 else
774 {
775 dp[0] = FZ_BLEND(c, dp[0], ma);
776 dp[1] = FZ_BLEND(m, dp[1], ma);
777 dp[2] = FZ_BLEND(y, dp[2], ma);
778 dp[3] = FZ_BLEND(k, dp[3], ma);
779 dp[4] = FZ_BLEND(255, dp[4], ma);
780 }
781 dp += 5;
782 }
783 while (--w);
784 }
785 else
786 {
787 do
788 {
789 int ma = *mp++;
790 ma = FZ_EXPAND(ma);
791 if (ma == 0)
792 {
793 }
794 else
795 {
796 ma = FZ_COMBINE(ma, sa);
797 dp[0] = FZ_BLEND(c, dp[0], ma);
798 dp[1] = FZ_BLEND(m, dp[1], ma);
799 dp[2] = FZ_BLEND(y, dp[2], ma);
800 dp[3] = FZ_BLEND(k, dp[3], ma);
801 dp[4] = FZ_BLEND(255, dp[4], ma);
802 }
803 dp += 5;
804 }
805 while (--w);
806 }
807}
808
809static inline void
810template_span_with_color_N_general(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da)
811{
812 int k;
813 int n1 = n - da;
814 int sa = FZ_EXPAND(color[n1]);
815 if (sa == 0)
816 return;
817 if (sa == 256)
818 {
819 do
820 {
821 int ma = *mp++;
822 ma = FZ_EXPAND(ma);
823 if (ma == 0)
824 {
825 }
826 else if (ma == 256)
827 {
828 if (n1 > 0)
829 dp[0] = color[0];
830 if (n1 > 1)
831 dp[1] = color[1];
832 if (n1 > 2)
833 dp[2] = color[2];
834 for (k = 3; k < n1; k++)
835 dp[k] = color[k];
836 if (da)
837 dp[n1] = 255;
838 }
839 else
840 {
841 for (k = 0; k < n1; k++)
842 dp[k] = FZ_BLEND(color[k], dp[k], ma);
843 if (da)
844 dp[n1] = FZ_BLEND(255, dp[k], ma);
845 }
846 dp += n;
847 }
848 while (--w);
849 }
850 else
851 {
852 do
853 {
854 int ma = *mp++;
855 ma = FZ_COMBINE(FZ_EXPAND(ma), sa);
856 for (k = 0; k < n1; k++)
857 dp[k] = FZ_BLEND(color[k], dp[k], ma);
858 if (da)
859 dp[k] = FZ_BLEND(255, dp[k], ma);
860 dp += n;
861 }
862 while (--w);
863 }
864}
865
866static inline void
867template_span_with_color_N_general_op(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
868{
869 int k;
870 int n1 = n - da;
871 int sa = FZ_EXPAND(color[n1]);
872 if (sa == 0)
873 return;
874 if (sa == 256)
875 {
876 do
877 {
878 int ma = *mp++;
879 ma = FZ_EXPAND(ma);
880 if (ma == 0)
881 {
882 }
883 else if (ma == 256)
884 {
885 if (n1 > 0)
886 if (fz_overprint_component(eop, 0))
887 dp[0] = color[0];
888 if (n1 > 1)
889 if (fz_overprint_component(eop, 1))
890 dp[1] = color[1];
891 if (n1 > 2)
892 if (fz_overprint_component(eop, 2))
893 dp[2] = color[2];
894 for (k = 3; k < n1; k++)
895 if (fz_overprint_component(eop, k))
896 dp[k] = color[k];
897 if (da)
898 dp[n1] = 255;
899 }
900 else
901 {
902 for (k = 0; k < n1; k++)
903 if (fz_overprint_component(eop, k))
904 dp[k] = FZ_BLEND(color[k], dp[k], ma);
905 if (da)
906 dp[n1] = FZ_BLEND(255, dp[k], ma);
907 }
908 dp += n;
909 }
910 while (--w);
911 }
912 else
913 {
914 do
915 {
916 int ma = *mp++;
917 ma = FZ_COMBINE(FZ_EXPAND(ma), sa);
918 for (k = 0; k < n1; k++)
919 if (fz_overprint_component(eop, k))
920 dp[k] = FZ_BLEND(color[k], dp[k], ma);
921 if (da)
922 dp[k] = FZ_BLEND(255, dp[k], ma);
923 dp += n;
924 }
925 while (--w);
926 }
927}
928
929static void
930paint_span_with_color_0_da(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
931{
932 TRACK_FN();
933 template_span_with_color_N_general(dp, mp, 1, w, color, 1);
934}
935
936static void
937paint_span_with_color_1(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
938{
939 TRACK_FN();
940 template_span_with_color_N_general(dp, mp, 1, w, color, 0);
941}
942
943static void
944paint_span_with_color_1_da(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
945{
946 TRACK_FN();
947 template_span_with_color_1_da(dp, mp, 2, w, color, 1);
948}
949
950#if FZ_PLOTTERS_RGB
951static void
952paint_span_with_color_3(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
953{
954 TRACK_FN();
955 template_span_with_color_N_general(dp, mp, 3, w, color, 0);
956}
957
958static void
959paint_span_with_color_3_da(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
960{
961 TRACK_FN();
962 template_span_with_color_3_da(dp, mp, 4, w, color, 1);
963}
964#endif /* FZ_PLOTTERS_RGB */
965
966#if FZ_PLOTTERS_CMYK
967static void
968paint_span_with_color_4(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
969{
970 TRACK_FN();
971 template_span_with_color_N_general(dp, mp, 4, w, color, 0);
972}
973
974static void
975paint_span_with_color_4_da(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
976{
977 TRACK_FN();
978 template_span_with_color_4_da(dp, mp, 5, w, color, 1);
979}
980#endif /* FZ_PLOTTERS_CMYK */
981
982#if FZ_PLOTTERS_N
983static void
984paint_span_with_color_N(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
985{
986 TRACK_FN();
987 template_span_with_color_N_general(dp, mp, n, w, color, 0);
988}
989
990static void
991paint_span_with_color_N_da(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
992{
993 TRACK_FN();
994 template_span_with_color_N_general(dp, mp, n, w, color, 1);
995}
996#endif /* FZ_PLOTTERS_N */
997
998#ifdef FZ_ENABLE_SPOT_RENDERING
999static void
1000paint_span_with_color_N_op(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
1001{
1002 TRACK_FN();
1003 template_span_with_color_N_general_op(dp, mp, n, w, color, 0, eop);
1004}
1005
1006static void
1007paint_span_with_color_N_da_op(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT mp, int n, int w, const byte * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop)
1008{
1009 TRACK_FN();
1010 template_span_with_color_N_general_op(dp, mp, n, w, color, 1, eop);
1011}
1012#endif /* FZ_ENABLE_SPOT_RENDERING */
1013
1014fz_span_color_painter_t *
1015fz_get_span_color_painter(int n, int da, const byte * FZ_RESTRICT color, const fz_overprint * FZ_RESTRICT eop)
1016{
1017#if FZ_ENABLE_SPOT_RENDERING
1018 if (fz_overprint_required(eop))
1019 {
1020 return da ? paint_span_with_color_N_da_op : paint_span_with_color_N_op;
1021 }
1022#endif /* FZ_ENABLE_SPOT_RENDERING */
1023 switch(n-da)
1024 {
1025 case 0: return da ? paint_span_with_color_0_da : NULL;
1026 case 1: return da ? paint_span_with_color_1_da : paint_span_with_color_1;
1027#if FZ_PLOTTERS_RGB
1028 case 3: return da ? paint_span_with_color_3_da : paint_span_with_color_3;
1029#endif/* FZ_PLOTTERS_RGB */
1030#if FZ_PLOTTERS_CMYK
1031 case 4: return da ? paint_span_with_color_4_da : paint_span_with_color_4;
1032#endif/* FZ_PLOTTERS_CMYK */
1033#if FZ_PLOTTERS_N
1034 default: return da ? paint_span_with_color_N_da : paint_span_with_color_N;
1035#else
1036 default: return NULL;
1037#endif /* FZ_PLOTTERS_N */
1038 }
1039}
1040
1041/* Blend source in mask over destination */
1042
1043/* FIXME: There is potential for SWAR optimisation here */
1044static inline void
1045template_span_with_mask_1_general(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, int a, const byte * FZ_RESTRICT mp, int w)
1046{
1047 do
1048 {
1049 int ma = *mp++;
1050 ma = FZ_EXPAND(ma);
1051 if (ma == 0 || (a && sp[1] == 0))
1052 {
1053 dp += 1 + a;
1054 sp += 1 + a;
1055 }
1056 else if (ma == 256)
1057 {
1058 *dp++ = *sp++;
1059 if (a)
1060 *dp++ = *sp++;
1061 }
1062 else
1063 {
1064 *dp = FZ_BLEND(*sp, *dp, ma);
1065 sp++; dp++;
1066 if (a)
1067 {
1068 *dp = FZ_BLEND(*sp, *dp, ma);
1069 sp++; dp++;
1070 }
1071 }
1072 }
1073 while (--w);
1074}
1075
1076static inline void
1077template_span_with_mask_3_general(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, int a, const byte * FZ_RESTRICT mp, int w)
1078{
1079 do
1080 {
1081 int ma = *mp++;
1082 ma = FZ_EXPAND(ma);
1083 if (ma == 0 || (a && sp[3] == 0))
1084 {
1085 dp += 3 + a;
1086 sp += 3 + a;
1087 }
1088 else if (ma == 256)
1089 {
1090 if (a)
1091 {
1092 *(int32_t *)dp = *(int32_t *)sp;
1093 sp += 4; dp += 4;
1094 }
1095 else
1096 {
1097 *dp++ = *sp++;
1098 *dp++ = *sp++;
1099 *dp++ = *sp++;
1100 }
1101 }
1102 else if (a)
1103 {
1104 const uint32_t mask = 0x00ff00ff;
1105 uint32_t d0 = *(uint32_t *)dp;
1106 uint32_t d1 = d0>>8;
1107 uint32_t s0 = *(uint32_t *)sp;
1108 uint32_t s1 = s0>>8;
1109 d0 &= mask;
1110 d1 &= mask;
1111 s0 &= mask;
1112 s1 &= mask;
1113 d0 = (((d0<<8) + (s0-d0)*ma)>>8) & mask;
1114 d1 = ((d1<<8) + (s1-d1)*ma) & ~mask;
1115 d0 |= d1;
1116 assert((d0>>24) >= (d0 & 0xff));
1117 assert((d0>>24) >= ((d0>>8) & 0xff));
1118 assert((d0>>24) >= ((d0>>16) & 0xff));
1119 *(uint32_t *)dp = d0;
1120 sp += 4;
1121 dp += 4;
1122 }
1123 else
1124 {
1125 *dp = FZ_BLEND(*sp, *dp, ma);
1126 sp++; dp++;
1127 *dp = FZ_BLEND(*sp, *dp, ma);
1128 sp++; dp++;
1129 *dp = FZ_BLEND(*sp, *dp, ma);
1130 sp++; dp++;
1131 }
1132 }
1133 while (--w);
1134}
1135
1136static inline void
1137template_span_with_mask_4_general(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, int a, const byte * FZ_RESTRICT mp, int w)
1138{
1139 do
1140 {
1141 int ma = *mp++;
1142 ma = FZ_EXPAND(ma);
1143 if (ma == 0 || (a && sp[4] == 0))
1144 {
1145 dp += 4 + a;
1146 sp += 4 + a;
1147 }
1148 else if (ma == 256)
1149 {
1150 if (!a)
1151 {
1152 *(uint32_t *)dp = *(uint32_t *)sp;
1153 dp += 4;
1154 sp += 4;
1155 }
1156 else
1157 {
1158 *dp++ = *sp++;
1159 *dp++ = *sp++;
1160 *dp++ = *sp++;
1161 *dp++ = *sp++;
1162 *dp++ = *sp++;
1163 }
1164 }
1165 else if (a)
1166 {
1167 *dp = FZ_BLEND(*sp, *dp, ma);
1168 sp++; dp++;
1169 *dp = FZ_BLEND(*sp, *dp, ma);
1170 sp++; dp++;
1171 *dp = FZ_BLEND(*sp, *dp, ma);
1172 sp++; dp++;
1173 *dp = FZ_BLEND(*sp, *dp, ma);
1174 sp++; dp++;
1175 *dp = FZ_BLEND(*sp, *dp, ma);
1176 sp++; dp++;
1177 }
1178 else
1179 {
1180 const uint32_t mask = 0x00ff00ff;
1181 uint32_t d0 = *(uint32_t *)dp;
1182 uint32_t d1 = d0>>8;
1183 uint32_t s0 = *(uint32_t *)sp;
1184 uint32_t s1 = s0>>8;
1185 sp += 4;
1186 d0 &= mask;
1187 d1 &= mask;
1188 s0 &= mask;
1189 s1 &= mask;
1190 d0 = (((d0<<8) + (s0-d0)*ma)>>8) & mask;
1191 d1 = ((d1<<8) + (s1-d1)*ma) & ~mask;
1192 d0 |= d1;
1193 *(uint32_t *)dp = d0;
1194 dp += 4;
1195 }
1196 }
1197 while (--w);
1198}
1199
1200static inline void
1201template_span_with_mask_N_general(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, int a, const byte * FZ_RESTRICT mp, int n, int w)
1202{
1203 do
1204 {
1205 int ma = *mp++;
1206 ma = FZ_EXPAND(ma);
1207 if (ma == 0 || (a && sp[n] == 0))
1208 {
1209 dp += n + a;
1210 sp += n + a;
1211 }
1212 else if (ma == 256)
1213 {
1214 int k;
1215 for (k = 0; k < n; k++)
1216 *dp++ = *sp++;
1217 if (a)
1218 *dp++ = *sp++;
1219 }
1220 else
1221 {
1222 int k;
1223 for (k = 0; k < n; k++)
1224 {
1225 *dp = FZ_BLEND(*sp, *dp, ma);
1226 sp++; dp++;
1227 }
1228 if (a)
1229 {
1230 *dp = FZ_BLEND(*sp, *dp, ma);
1231 sp++; dp++;
1232 }
1233 }
1234 }
1235 while (--w);
1236}
1237
1238static void
1239paint_span_with_mask_0_a(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop)
1240{
1241 TRACK_FN();
1242 template_span_with_mask_N_general(dp, sp, 1, mp, 0, w);
1243}
1244
1245static void
1246paint_span_with_mask_1_a(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop)
1247{
1248 TRACK_FN();
1249 template_span_with_mask_1_general(dp, sp, 1, mp, w);
1250}
1251
1252static void
1253paint_span_with_mask_1(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop)
1254{
1255 TRACK_FN();
1256 template_span_with_mask_1_general(dp, sp, 0, mp, w);
1257}
1258
1259#if FZ_PLOTTERS_RGB
1260static void
1261paint_span_with_mask_3_a(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop)
1262{
1263 TRACK_FN();
1264 template_span_with_mask_3_general(dp, sp, 1, mp, w);
1265}
1266
1267static void
1268paint_span_with_mask_3(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop)
1269{
1270 TRACK_FN();
1271 template_span_with_mask_3_general(dp, sp, 0, mp, w);
1272}
1273#endif /* FZ_PLOTTERS_RGB */
1274
1275#if FZ_PLOTTERS_CMYK
1276static void
1277paint_span_with_mask_4_a(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop)
1278{
1279 TRACK_FN();
1280 template_span_with_mask_4_general(dp, sp, 1, mp, w);
1281}
1282
1283static void
1284paint_span_with_mask_4(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop)
1285{
1286 TRACK_FN();
1287 template_span_with_mask_4_general(dp, sp, 0, mp, w);
1288}
1289#endif /* FZ_PLOTTERS_CMYK */
1290
1291#if FZ_PLOTTERS_N
1292static void
1293paint_span_with_mask_N_a(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop)
1294{
1295 TRACK_FN();
1296 template_span_with_mask_N_general(dp, sp, 1, mp, n, w);
1297}
1298
1299static void
1300paint_span_with_mask_N(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop)
1301{
1302 TRACK_FN();
1303 template_span_with_mask_N_general(dp, sp, 0, mp, n, w);
1304}
1305#endif /* FZ_PLOTTERS_N */
1306
1307typedef void (fz_span_mask_painter_t)(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, const byte * FZ_RESTRICT mp, int w, int n, int a, const fz_overprint * FZ_RESTRICT eop);
1308
1309static fz_span_mask_painter_t *
1310fz_get_span_mask_painter(int a, int n)
1311{
1312 switch(n)
1313 {
1314 case 0:
1315 /* assert(a); */
1316 return paint_span_with_mask_0_a;
1317 case 1:
1318 if (a)
1319 return paint_span_with_mask_1_a;
1320 else
1321 return paint_span_with_mask_1;
1322#if FZ_PLOTTERS_RGB
1323 case 3:
1324 if (a)
1325 return paint_span_with_mask_3_a;
1326 else
1327 return paint_span_with_mask_3;
1328#endif /* FZ_PLOTTERS_RGB */
1329#if FZ_PLOTTERS_CMYK
1330 case 4:
1331 if (a)
1332 return paint_span_with_mask_4_a;
1333 else
1334 return paint_span_with_mask_4;
1335#endif /* FZ_PLOTTERS_CMYK */
1336 default:
1337 {
1338#if FZ_PLOTTERS_N
1339 if (a)
1340 return paint_span_with_mask_N_a;
1341 else
1342 return paint_span_with_mask_N;
1343#else
1344 return NULL;
1345#endif /* FZ_PLOTTERS_N */
1346 }
1347 }
1348}
1349
1350/* Blend source in constant alpha over destination */
1351
1352static inline void
1353template_span_1_with_alpha_general(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int w, int alpha)
1354{
1355 if (sa)
1356 alpha = FZ_EXPAND(alpha);
1357 do
1358 {
1359 int masa = (sa ? FZ_COMBINE(sp[1], alpha) : alpha);
1360 int t = FZ_EXPAND(255-masa);
1361 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1362 dp++; sp++;
1363 if (da)
1364 {
1365 *dp = masa + FZ_COMBINE(*dp, t);
1366 dp++;
1367 }
1368 if (sa)
1369 sp++;
1370 }
1371 while (--w);
1372}
1373
1374static inline void
1375template_span_3_with_alpha_general(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int w, int alpha)
1376{
1377 if (sa)
1378 alpha = FZ_EXPAND(alpha);
1379 do
1380 {
1381 int masa = (sa ? FZ_COMBINE(sp[3], alpha) : alpha);
1382 int t = FZ_EXPAND(255-masa);
1383 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1384 sp++; dp++;
1385 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1386 sp++; dp++;
1387 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1388 sp++; dp++;
1389 if (da)
1390 {
1391 *dp = masa + FZ_COMBINE(*dp, t);
1392 dp++;
1393 }
1394 if (sa)
1395 sp++;
1396 }
1397 while (--w);
1398}
1399
1400static inline void
1401template_span_4_with_alpha_general(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int w, int alpha)
1402{
1403 if (sa)
1404 alpha = FZ_EXPAND(alpha);
1405 do
1406 {
1407 int masa = (sa ? FZ_COMBINE(sp[4], alpha) : alpha);
1408 int t = FZ_EXPAND(255-masa);
1409 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1410 sp++; dp++;
1411 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1412 sp++; dp++;
1413 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1414 sp++; dp++;
1415 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1416 sp++; dp++;
1417 if (da)
1418 {
1419 *dp = masa + FZ_COMBINE(*dp, t);
1420 dp++;
1421 }
1422 if (sa)
1423 sp++;
1424 }
1425 while (--w);
1426}
1427
1428#if FZ_PLOTTERS_N
1429static inline void
1430template_span_N_with_alpha_general(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n1, int w, int alpha)
1431{
1432 if (sa)
1433 alpha = FZ_EXPAND(alpha);
1434 do
1435 {
1436 int masa = (sa ? FZ_COMBINE(sp[n1], alpha) : alpha);
1437 int t = FZ_EXPAND(255-masa);
1438 int k;
1439 for (k = 0; k < n1; k++)
1440 {
1441 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1442 sp++; dp++;
1443 }
1444 if (da)
1445 {
1446 *dp = masa + FZ_COMBINE(*dp, t);
1447 dp++;
1448 }
1449 if (sa)
1450 sp++;
1451 }
1452 while (--w);
1453}
1454
1455static inline void
1456template_span_N_with_alpha_general_op(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n1, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1457{
1458 if (sa)
1459 alpha = FZ_EXPAND(alpha);
1460 do
1461 {
1462 int masa = (sa ? FZ_COMBINE(sp[n1], alpha) : alpha);
1463 int t = FZ_EXPAND(255-masa);
1464 int k;
1465 for (k = 0; k < n1; k++)
1466 {
1467 if (fz_overprint_component(eop, k))
1468 *dp = FZ_COMBINE(*sp, alpha) + FZ_COMBINE(*dp, t);
1469 sp++;
1470 dp++;
1471 }
1472 if (da)
1473 {
1474 *dp = masa + FZ_COMBINE(*dp, t);
1475 dp++;
1476 }
1477 if (sa)
1478 sp++;
1479 }
1480 while (--w);
1481}
1482#endif
1483
1484/* Blend source over destination */
1485
1486static inline void
1487template_span_1_general(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int w)
1488{
1489 do
1490 {
1491 int t = (sa ? FZ_EXPAND(sp[1]): 256);
1492 if (t == 0)
1493 {
1494 dp += 1 + da; sp += 1 + sa;
1495 }
1496 else
1497 {
1498 t = 256 - t;
1499 if (t == 0)
1500 {
1501 *dp++ = *sp++;
1502 if (da)
1503 *dp++ = (sa ? *sp : 255);
1504 if (sa)
1505 sp++;
1506 }
1507 else
1508 {
1509 *dp = *sp + FZ_COMBINE(*dp, t);
1510 sp++;
1511 dp++;
1512 if (da)
1513 {
1514 *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
1515 dp++;
1516 }
1517 if (sa)
1518 sp++;
1519 }
1520 }
1521 }
1522 while (--w);
1523}
1524
1525static inline void
1526template_span_3_general(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int w)
1527{
1528 do
1529 {
1530 int t = (sa ? FZ_EXPAND(sp[3]) : 256);
1531 if (t == 0)
1532 {
1533 dp += 3 + da; sp += 3 + sa;
1534 }
1535 else
1536 {
1537 t = 256 - t;
1538 if (t == 0)
1539 {
1540 if (da && sa)
1541 *(int32_t *)dp = *(const int32_t *)sp;
1542 else
1543 {
1544 dp[0] = sp[0];
1545 dp[1] = sp[1];
1546 dp[2] = sp[2];
1547 if (da)
1548 dp[3] = 255;
1549 }
1550 dp += 3+da; sp += 3+sa;
1551 }
1552 else
1553 {
1554 *dp = *sp++ + FZ_COMBINE(*dp, t);
1555 dp++;
1556 *dp = *sp++ + FZ_COMBINE(*dp, t);
1557 dp++;
1558 *dp = *sp++ + FZ_COMBINE(*dp, t);
1559 dp++;
1560 if (da)
1561 {
1562 *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
1563 dp++;
1564 }
1565 if (sa)
1566 sp++;
1567 }
1568 }
1569 }
1570 while (--w);
1571}
1572
1573static inline void
1574template_span_4_general(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int w)
1575{
1576 do
1577 {
1578 int t = (sa ? FZ_EXPAND(sp[4]) : 256);
1579 if (t == 0)
1580 {
1581 dp += 4+da; sp += 4+sa;
1582 }
1583 else
1584 {
1585 t = 256 - t;
1586 if (t == 0)
1587 {
1588 dp[0] = sp[0];
1589 dp[1] = sp[1];
1590 dp[2] = sp[2];
1591 dp[3] = sp[3];
1592 if (da)
1593 dp[4] = (sa ? sp[4] : 255);
1594 dp += 4+da; sp += 4 + sa;
1595 }
1596 else
1597 {
1598 *dp = *sp++ + FZ_COMBINE(*dp, t);
1599 dp++;
1600 *dp = *sp++ + FZ_COMBINE(*dp, t);
1601 dp++;
1602 *dp = *sp++ + FZ_COMBINE(*dp, t);
1603 dp++;
1604 *dp = *sp++ + FZ_COMBINE(*dp, t);
1605 dp++;
1606 if (da)
1607 {
1608 *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
1609 dp++;
1610 }
1611 if (sa)
1612 sp++;
1613 }
1614 }
1615 }
1616 while (--w);
1617}
1618
1619#if FZ_PLOTTERS_N
1620static inline void
1621template_span_N_general(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n1, int w)
1622{
1623 do
1624 {
1625 int t = (sa ? FZ_EXPAND(sp[n1]) : 256);
1626 if (t == 0)
1627 {
1628 dp += n1 + da; sp += n1 + sa;
1629 }
1630 else
1631 {
1632 t = 256 - t;
1633 if (t == 0)
1634 {
1635 int k;
1636 for (k = 0; k < n1; k++)
1637 *dp++ = *sp++;
1638 if (da)
1639 *dp++ = (sa ? *sp : 255);
1640 if (sa)
1641 sp++;
1642 }
1643 else
1644 {
1645 int k;
1646 for (k = 0; k < n1; k++)
1647 {
1648 *dp = *sp + FZ_COMBINE(*dp, t);
1649 sp++;
1650 dp++;
1651 }
1652 if (da)
1653 {
1654 *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
1655 dp++;
1656 }
1657 if (sa)
1658 sp++;
1659 }
1660 }
1661 }
1662 while (--w);
1663}
1664
1665static inline void
1666template_span_N_general_op(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n1, int w, const fz_overprint * FZ_RESTRICT eop)
1667{
1668 do
1669 {
1670 int t = (sa ? FZ_EXPAND(sp[n1]) : 256);
1671 if (t == 0)
1672 {
1673 dp += n1 + da; sp += n1 + sa;
1674 }
1675 else
1676 {
1677 t = 256 - t;
1678 if (t == 0)
1679 {
1680 int k;
1681 for (k = 0; k < n1; k++)
1682 {
1683 if (fz_overprint_component(eop, k))
1684 *dp = *sp;
1685 dp++;
1686 sp++;
1687 }
1688 if (da)
1689 *dp++ = (sa ? *sp : 255);
1690 if (sa)
1691 sp++;
1692 }
1693 else
1694 {
1695 int k;
1696 for (k = 0; k < n1; k++)
1697 {
1698 if (fz_overprint_component(eop, k))
1699 *dp = *sp + FZ_COMBINE(*dp, t);
1700 sp++;
1701 dp++;
1702 }
1703 if (da)
1704 {
1705 *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
1706 dp++;
1707 }
1708 if (sa)
1709 sp++;
1710 }
1711 }
1712 }
1713 while (--w);
1714}
1715#endif
1716
1717static void
1718paint_span_0_da_sa(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1719{
1720 TRACK_FN();
1721 do
1722 {
1723 int s = *sp++;
1724 int t = FZ_EXPAND(255 - s);
1725 *dp = s + FZ_COMBINE(*dp, t);
1726 dp ++;
1727 }
1728 while (--w);
1729}
1730
1731static void
1732paint_span_0_da_sa_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1733{
1734 TRACK_FN();
1735 alpha = FZ_EXPAND(alpha);
1736 do
1737 {
1738 int masa = FZ_COMBINE(sp[0], alpha);
1739 int t = FZ_EXPAND(255-masa);
1740 *dp = masa + FZ_COMBINE(*dp, t);
1741 dp++;
1742 sp++;
1743 }
1744 while (--w);
1745}
1746
1747static void
1748paint_span_1_sa(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1749{
1750 TRACK_FN();
1751 template_span_1_general(dp, 0, sp, 1, w);
1752}
1753
1754static void
1755paint_span_1_sa_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1756{
1757 TRACK_FN();
1758 template_span_1_with_alpha_general(dp, 0, sp, 1, w, alpha);
1759}
1760
1761static void
1762paint_span_1_da_sa(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1763{
1764 TRACK_FN();
1765 template_span_1_general(dp, 1, sp, 1, w);
1766}
1767
1768static void
1769paint_span_1_da_sa_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1770{
1771 TRACK_FN();
1772 template_span_1_with_alpha_general(dp, 1, sp, 1, w, alpha);
1773}
1774
1775#if FZ_PLOTTERS_G
1776static void
1777paint_span_1_da(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1778{
1779 TRACK_FN();
1780 template_span_1_general(dp, 1, sp, 0, w);
1781}
1782
1783static void
1784paint_span_1_da_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1785{
1786 TRACK_FN();
1787 template_span_1_with_alpha_general(dp, 1, sp, 0, w, alpha);
1788}
1789
1790static void
1791paint_span_1(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1792{
1793 TRACK_FN();
1794 template_span_1_general(dp, 0, sp, 0, w);
1795}
1796
1797static void
1798paint_span_1_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1799{
1800 TRACK_FN();
1801 template_span_1_with_alpha_general(dp, 0, sp, 0, w, alpha);
1802}
1803#endif /* FZ_PLOTTERS_G */
1804
1805#if FZ_PLOTTERS_RGB
1806static void
1807paint_span_3_da_sa(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1808{
1809 TRACK_FN();
1810 template_span_3_general(dp, 1, sp, 1, w);
1811}
1812
1813static void
1814paint_span_3_da_sa_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1815{
1816 TRACK_FN();
1817 template_span_3_with_alpha_general(dp, 1, sp, 1, w, alpha);
1818}
1819
1820static void
1821paint_span_3_da(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1822{
1823 TRACK_FN();
1824 template_span_3_general(dp, 1, sp, 0, w);
1825}
1826
1827static void
1828paint_span_3_da_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1829{
1830 TRACK_FN();
1831 template_span_3_with_alpha_general(dp, 1, sp, 0, w, alpha);
1832}
1833
1834static void
1835paint_span_3_sa(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1836{
1837 TRACK_FN();
1838 template_span_3_general(dp, 0, sp, 1, w);
1839}
1840
1841static void
1842paint_span_3_sa_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1843{
1844 TRACK_FN();
1845 template_span_3_with_alpha_general(dp, 0, sp, 1, w, alpha);
1846}
1847
1848static void
1849paint_span_3(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1850{
1851 TRACK_FN();
1852 template_span_3_general(dp, 0, sp, 0, w);
1853}
1854
1855static void
1856paint_span_3_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1857{
1858 TRACK_FN();
1859 template_span_3_with_alpha_general(dp, 0, sp, 0, w, alpha);
1860}
1861#endif /* FZ_PLOTTERS_RGB */
1862
1863#if FZ_PLOTTERS_CMYK
1864static void
1865paint_span_4_da_sa(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1866{
1867 TRACK_FN();
1868 template_span_4_general(dp, 1, sp, 1, w);
1869}
1870
1871static void
1872paint_span_4_da_sa_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1873{
1874 TRACK_FN();
1875 template_span_4_with_alpha_general(dp, 1, sp, 1, w, alpha);
1876}
1877
1878static void
1879paint_span_4_da(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1880{
1881 TRACK_FN();
1882 template_span_4_general(dp, 1, sp, 0, w);
1883}
1884
1885static void
1886paint_span_4_da_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1887{
1888 TRACK_FN();
1889 template_span_4_with_alpha_general(dp, 1, sp, 0, w, alpha);
1890}
1891
1892static void
1893paint_span_4_sa(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1894{
1895 TRACK_FN();
1896 template_span_4_general(dp, 0, sp, 1, w);
1897}
1898
1899static void
1900paint_span_4_sa_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1901{
1902 TRACK_FN();
1903 template_span_4_with_alpha_general(dp, 0, sp, 1, w, alpha);
1904}
1905
1906static void
1907paint_span_4(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1908{
1909 TRACK_FN();
1910 template_span_4_general(dp, 0, sp, 0, w);
1911}
1912
1913static void
1914paint_span_4_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1915{
1916 TRACK_FN();
1917 template_span_4_with_alpha_general(dp, 0, sp, 0, w, alpha);
1918}
1919#endif /* FZ_PLOTTERS_CMYK */
1920
1921#if FZ_PLOTTERS_N
1922static void
1923paint_span_N_da_sa(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1924{
1925 TRACK_FN();
1926 template_span_N_general(dp, 1, sp, 1, n, w);
1927}
1928
1929static void
1930paint_span_N_da_sa_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1931{
1932 TRACK_FN();
1933 template_span_N_with_alpha_general(dp, 1, sp, 1, n, w, alpha);
1934}
1935
1936static void
1937paint_span_N_da(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1938{
1939 TRACK_FN();
1940 template_span_N_general(dp, 1, sp, 0, n, w);
1941}
1942
1943static void
1944paint_span_N_da_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1945{
1946 TRACK_FN();
1947 template_span_N_with_alpha_general(dp, 1, sp, 0, n, w, alpha);
1948}
1949
1950static void
1951paint_span_N_sa(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1952{
1953 TRACK_FN();
1954 template_span_N_general(dp, 0, sp, 1, n, w);
1955}
1956
1957static void
1958paint_span_N_sa_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1959{
1960 TRACK_FN();
1961 template_span_N_with_alpha_general(dp, 0, sp, 1, n, w, alpha);
1962}
1963
1964static void
1965paint_span_N(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1966{
1967 TRACK_FN();
1968 template_span_N_general(dp, 0, sp, 0, n, w);
1969}
1970
1971static void
1972paint_span_N_alpha(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1973{
1974 TRACK_FN();
1975 template_span_N_with_alpha_general(dp, 0, sp, 0, n, w, alpha);
1976}
1977#endif /* FZ_PLOTTERS_N */
1978
1979#if FZ_ENABLE_SPOT_RENDERING
1980static void
1981paint_span_N_general_op(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1982{
1983 TRACK_FN();
1984 template_span_N_general_op(dp, da, sp, sa, n, w, eop);
1985}
1986
1987static void
1988paint_span_N_general_alpha_op(byte * FZ_RESTRICT dp, int da, const byte * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop)
1989{
1990 TRACK_FN();
1991 template_span_N_with_alpha_general_op(dp, da, sp, sa, n, w, alpha, eop);
1992}
1993#endif /* FZ_ENABLE_SPOT_RENDERING */
1994
1995fz_span_painter_t *
1996fz_get_span_painter(int da, int sa, int n, int alpha, const fz_overprint * FZ_RESTRICT eop)
1997{
1998#if FZ_ENABLE_SPOT_RENDERING
1999 if (fz_overprint_required(eop))
2000 {
2001 if (alpha == 255)
2002 return paint_span_N_general_op;
2003 else if (alpha > 0)
2004 return paint_span_N_general_alpha_op;
2005 else
2006 return NULL;
2007 }
2008#endif /* FZ_ENABLE_SPOT_RENDERING */
2009 switch (n)
2010 {
2011 case 0:
2012 if (alpha == 255)
2013 return paint_span_0_da_sa;
2014 else if (alpha > 0)
2015 return paint_span_0_da_sa_alpha;
2016 break;
2017 case 1:
2018 if (sa)
2019 if (da)
2020 {
2021 if (alpha == 255)
2022 return paint_span_1_da_sa;
2023 else if (alpha > 0)
2024 return paint_span_1_da_sa_alpha;
2025 }
2026 else
2027 {
2028 if (alpha == 255)
2029 return paint_span_1_sa;
2030 else if (alpha > 0)
2031 return paint_span_1_sa_alpha;
2032 }
2033 else
2034#if FZ_PLOTTERS_G
2035 if (da)
2036 {
2037 if (alpha == 255)
2038 return paint_span_1_da;
2039 else if (alpha > 0)
2040 return paint_span_1_da_alpha;
2041 }
2042 else
2043 {
2044 if (alpha == 255)
2045 return paint_span_1;
2046 else if (alpha > 0)
2047 return paint_span_1_alpha;
2048 }
2049#else
2050 goto fallback;
2051#endif /* FZ_PLOTTERS_G */
2052 break;
2053#if FZ_PLOTTERS_RGB
2054 case 3:
2055 if (da)
2056 if (sa)
2057 {
2058 if (alpha == 255)
2059 return paint_span_3_da_sa;
2060 else if (alpha > 0)
2061 return paint_span_3_da_sa_alpha;
2062 }
2063 else
2064 {
2065 if (alpha == 255)
2066 return paint_span_3_da;
2067 else if (alpha > 0)
2068 return paint_span_3_da_alpha;
2069 }
2070 else
2071 if (sa)
2072 {
2073 if (alpha == 255)
2074 return paint_span_3_sa;
2075 else if (alpha > 0)
2076 return paint_span_3_sa_alpha;
2077 }
2078 else
2079 {
2080 if (alpha == 255)
2081 return paint_span_3;
2082 else if (alpha > 0)
2083 return paint_span_3_alpha;
2084 }
2085 break;
2086#endif /* FZ_PLOTTERS_RGB */
2087#if FZ_PLOTTERS_CMYK
2088 case 4:
2089 if (da)
2090 if (sa)
2091 {
2092 if (alpha == 255)
2093 return paint_span_4_da_sa;
2094 else if (alpha > 0)
2095 return paint_span_4_da_sa_alpha;
2096 }
2097 else
2098 {
2099 if (alpha == 255)
2100 return paint_span_4_da;
2101 else if (alpha > 0)
2102 return paint_span_4_da_alpha;
2103 }
2104 else
2105 if (sa)
2106 {
2107 if (alpha == 255)
2108 return paint_span_4_sa;
2109 else if (alpha > 0)
2110 return paint_span_4_sa_alpha;
2111 }
2112 else
2113 {
2114 if (alpha == 255)
2115 return paint_span_4;
2116 else if (alpha > 0)
2117 return paint_span_4_alpha;
2118 }
2119 break;
2120#endif /* FZ_PLOTTERS_CMYK */
2121 default:
2122 {
2123#if !FZ_PLOTTERS_G
2124fallback:{}
2125#endif /* FZ_PLOTTERS_G */
2126#if FZ_PLOTTERS_N
2127 if (da)
2128 if (sa)
2129 {
2130 if (alpha == 255)
2131 return paint_span_N_da_sa;
2132 else if (alpha > 0)
2133 return paint_span_N_da_sa_alpha;
2134 }
2135 else
2136 {
2137 if (alpha == 255)
2138 return paint_span_N_da;
2139 else if (alpha > 0)
2140 return paint_span_N_da_alpha;
2141 }
2142 else
2143 if (sa)
2144 {
2145 if (alpha == 255)
2146 return paint_span_N_sa;
2147 else if (alpha > 0)
2148 return paint_span_N_sa_alpha;
2149 }
2150 else
2151 {
2152 if (alpha == 255)
2153 return paint_span_N;
2154 else if (alpha > 0)
2155 return paint_span_N_alpha;
2156 }
2157#endif /* FZ_PLOTTERS_N */
2158 break;
2159 }
2160 }
2161 return NULL;
2162}
2163
2164/*
2165 * Pixmap blending functions
2166 */
2167
2168void
2169fz_paint_pixmap_with_bbox(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, int alpha, fz_irect bbox)
2170{
2171 const unsigned char *sp;
2172 unsigned char *dp;
2173 int x, y, w, h, n, da, sa;
2174 fz_span_painter_t *fn;
2175
2176 assert(dst->n - dst->alpha == src->n - src->alpha);
2177
2178 if (alpha == 0)
2179 return;
2180
2181 bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(dst));
2182 bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(src));
2183
2184 x = bbox.x0;
2185 y = bbox.y0;
2186 w = bbox.x1 - bbox.x0;
2187 h = bbox.y1 - bbox.y0;
2188 if (w == 0 || h == 0)
2189 return;
2190
2191 n = src->n;
2192 sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
2193 sa = src->alpha;
2194 dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
2195 da = dst->alpha;
2196
2197 n -= sa;
2198 fn = fz_get_span_painter(da, sa, n, alpha, 0);
2199 assert(fn);
2200 if (fn == NULL)
2201 return;
2202
2203 while (h--)
2204 {
2205 (*fn)(dp, da, sp, sa, n, w, alpha, 0);
2206 sp += src->stride;
2207 dp += dst->stride;
2208 }
2209}
2210
2211void
2212fz_paint_pixmap(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, int alpha)
2213{
2214 const unsigned char *sp;
2215 unsigned char *dp;
2216 fz_irect bbox;
2217 int x, y, w, h, n, da, sa;
2218 fz_span_painter_t *fn;
2219
2220 if (alpha == 0)
2221 return;
2222
2223 if (dst->n - dst->alpha != src->n - src->alpha)
2224 {
2225 // fprintf(stderr, "fz_paint_pixmap - FIXME\n");
2226 return;
2227 }
2228 assert(dst->n - dst->alpha == src->n - src->alpha);
2229
2230 bbox = fz_intersect_irect(fz_pixmap_bbox_no_ctx(src), fz_pixmap_bbox_no_ctx(dst));
2231 x = bbox.x0;
2232 y = bbox.y0;
2233 w = bbox.x1 - bbox.x0;
2234 h = bbox.y1 - bbox.y0;
2235 if (w == 0 || h == 0)
2236 return;
2237
2238 n = src->n;
2239 sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
2240 sa = src->alpha;
2241 dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
2242 da = dst->alpha;
2243
2244 n -= sa;
2245 fn = fz_get_span_painter(da, sa, n, alpha, 0);
2246 assert(fn);
2247 if (fn == NULL)
2248 return;
2249
2250 while (h--)
2251 {
2252 (*fn)(dp, da, sp, sa, n, w, alpha, 0);
2253 sp += src->stride;
2254 dp += dst->stride;
2255 }
2256}
2257
2258static inline void
2259paint_span_alpha_solid(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, int n, int w)
2260{
2261 TRACK_FN();
2262 sp += n-1;
2263 do
2264 {
2265 int s = *sp;
2266 int t = FZ_EXPAND(255 - s);
2267 sp += n;
2268 *dp = s + FZ_COMBINE(*dp, t);
2269 dp ++;
2270 }
2271 while (--w);
2272}
2273
2274static inline void
2275paint_span_alpha_not_solid(byte * FZ_RESTRICT dp, const byte * FZ_RESTRICT sp, int n, int w, int alpha)
2276{
2277 TRACK_FN();
2278 sp += n-1;
2279 alpha = FZ_EXPAND(alpha);
2280 do
2281 {
2282 int masa = FZ_COMBINE(sp[0], alpha);
2283 sp += n;
2284 *dp = FZ_BLEND(*sp, *dp, masa);
2285 dp++;
2286 }
2287 while (--w);
2288}
2289
2290void
2291fz_paint_pixmap_alpha(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, int alpha)
2292{
2293 const unsigned char *sp;
2294 unsigned char *dp;
2295 fz_irect bbox;
2296 int x, y, w, h, n;
2297
2298 if (alpha == 0)
2299 return;
2300
2301 assert(dst->n == 1 && dst->alpha == 1 && src->n >= 1 && src->alpha == 1);
2302
2303 bbox = fz_intersect_irect(fz_pixmap_bbox_no_ctx(src), fz_pixmap_bbox_no_ctx(dst));
2304 x = bbox.x0;
2305 y = bbox.y0;
2306 w = bbox.x1 - bbox.x0;
2307 h = bbox.y1 - bbox.y0;
2308 if (w == 0 || h == 0)
2309 return;
2310
2311 n = src->n;
2312 sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
2313 dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
2314
2315 if (alpha == 255)
2316 {
2317 while (h--)
2318 {
2319 paint_span_alpha_solid(dp, sp, n, w);
2320 sp += src->stride;
2321 dp += dst->stride;
2322 }
2323 }
2324 else
2325 {
2326 while (h--)
2327 {
2328 paint_span_alpha_not_solid(dp, sp, n, w, alpha);
2329 sp += src->stride;
2330 dp += dst->stride;
2331 }
2332 }
2333}
2334
2335void
2336fz_paint_pixmap_with_overprint(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, const fz_overprint *eop)
2337{
2338 const unsigned char *sp;
2339 unsigned char *dp;
2340 fz_irect bbox;
2341 int x, y, w, h, n, da, sa;
2342 fz_span_painter_t *fn;
2343
2344 if (dst->n - dst->alpha != src->n - src->alpha)
2345 {
2346 // fprintf(stderr, "fz_paint_pixmap_with_overprint - FIXME\n");
2347 return;
2348 }
2349 assert(dst->n - dst->alpha == src->n - src->alpha);
2350
2351 bbox = fz_intersect_irect(fz_pixmap_bbox_no_ctx(src), fz_pixmap_bbox_no_ctx(dst));
2352 x = bbox.x0;
2353 y = bbox.y0;
2354 w = bbox.x1 - bbox.x0;
2355 h = bbox.y1 - bbox.y0;
2356 if (w == 0 || h == 0)
2357 return;
2358
2359 n = src->n;
2360 sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
2361 sa = src->alpha;
2362 dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
2363 da = dst->alpha;
2364
2365 n -= sa;
2366 fn = fz_get_span_painter(da, sa, n, 255, eop);
2367 assert(fn);
2368 if (fn == NULL)
2369 return;
2370
2371 while (h--)
2372 {
2373 (*fn)(dp, da, sp, sa, n, w, 255, eop);
2374 sp += src->stride;
2375 dp += dst->stride;
2376 }
2377}
2378
2379void
2380fz_paint_pixmap_with_mask(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, const fz_pixmap * FZ_RESTRICT msk)
2381{
2382 const unsigned char *sp, *mp;
2383 unsigned char *dp;
2384 fz_irect bbox;
2385 int x, y, w, h, n, sa, da;
2386 fz_span_mask_painter_t *fn;
2387
2388 assert(dst->n == src->n);
2389 assert(msk->n == 1);
2390
2391 bbox = fz_pixmap_bbox_no_ctx(dst);
2392 bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(src));
2393 bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(msk));
2394
2395 x = bbox.x0;
2396 y = bbox.y0;
2397 w = bbox.x1 - bbox.x0;
2398 h = bbox.y1 - bbox.y0;
2399 if (w == 0 || h == 0)
2400 return;
2401
2402 n = src->n;
2403 sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
2404 sa = src->alpha;
2405 mp = msk->samples + (unsigned int)((y - msk->y) * msk->stride + (x - msk->x) * msk->n);
2406 dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
2407 da = dst->alpha;
2408
2409 /* sa == da, or something has gone very wrong! */
2410 assert(sa == da);
2411
2412 n -= sa;
2413 fn = fz_get_span_mask_painter(da, n);
2414 if (fn == NULL)
2415 return;
2416
2417 while (h--)
2418 {
2419 (*fn)(dp, sp, mp, w, n, sa, NULL);
2420 sp += src->stride;
2421 dp += dst->stride;
2422 mp += msk->stride;
2423 }
2424}
2425
2426static inline void
2427fz_paint_glyph_mask(int span, unsigned char *dp, int da, const fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
2428{
2429 while (h--)
2430 {
2431 int skip_xx, ww, len, extend;
2432 const unsigned char *runp;
2433 unsigned char *ddp = dp;
2434 int offset = ((const int *)(glyph->data))[skip_y++];
2435 if (offset >= 0)
2436 {
2437 int eol = 0;
2438 runp = &glyph->data[offset];
2439 extend = 0;
2440 ww = w;
2441 skip_xx = skip_x;
2442 while (skip_xx)
2443 {
2444 int v = *runp++;
2445 switch (v & 3)
2446 {
2447 case 0: /* Extend */
2448 extend = v>>2;
2449 len = 0;
2450 break;
2451 case 1: /* Transparent */
2452 len = (v>>2) + 1 + (extend<<6);
2453 extend = 0;
2454 if (len > skip_xx)
2455 {
2456 len -= skip_xx;
2457 goto transparent_run;
2458 }
2459 break;
2460 case 2: /* Solid */
2461 eol = v & 4;
2462 len = (v>>3) + 1 + (extend<<5);
2463 extend = 0;
2464 if (len > skip_xx)
2465 {
2466 len -= skip_xx;
2467 goto solid_run;
2468 }
2469 break;
2470 default: /* Intermediate */
2471 eol = v & 4;
2472 len = (v>>3) + 1 + (extend<<5);
2473 extend = 0;
2474 if (len > skip_xx)
2475 {
2476 runp += skip_xx;
2477 len -= skip_xx;
2478 goto intermediate_run;
2479 }
2480 runp += len;
2481 break;
2482 }
2483 if (eol)
2484 {
2485 ww = 0;
2486 break;
2487 }
2488 skip_xx -= len;
2489 }
2490 while (ww > 0)
2491 {
2492 int v = *runp++;
2493 switch(v & 3)
2494 {
2495 case 0: /* Extend */
2496 extend = v>>2;
2497 break;
2498 case 1: /* Transparent */
2499 len = (v>>2) + 1 + (extend<<6);
2500 extend = 0;
2501transparent_run:
2502 if (len > ww)
2503 len = ww;
2504 ww -= len;
2505 ddp += len;
2506 break;
2507 case 2: /* Solid */
2508 eol = v & 4;
2509 len = (v>>3) + 1 + (extend<<5);
2510 extend = 0;
2511solid_run:
2512 if (len > ww)
2513 len = ww;
2514 ww -= len;
2515 do
2516 {
2517 *ddp++ = 0xFF;
2518 }
2519 while (--len);
2520 break;
2521 default: /* Intermediate */
2522 eol = v & 4;
2523 len = (v>>3) + 1 + (extend<<5);
2524 extend = 0;
2525intermediate_run:
2526 if (len > ww)
2527 len = ww;
2528 ww -= len;
2529 do
2530 {
2531 int v = *ddp;
2532 int a = *runp++;
2533 if (v == 0)
2534 {
2535 *ddp++ = a;
2536 }
2537 else
2538 {
2539 a = FZ_EXPAND(a);
2540 *ddp = FZ_BLEND(0xFF, v, a);
2541 ddp++;
2542 }
2543 }
2544 while (--len);
2545 break;
2546 }
2547 if (eol)
2548 break;
2549 }
2550 }
2551 dp += span;
2552 }
2553}
2554
2555#define N 1
2556#include "paint-glyph.h"
2557
2558#define ALPHA
2559#define N 1
2560#include "paint-glyph.h"
2561
2562#if FZ_PLOTTERS_G
2563#define DA
2564#define N 1
2565#include "paint-glyph.h"
2566
2567#define DA
2568#define ALPHA
2569#define N 1
2570#include "paint-glyph.h"
2571#endif /* FZ_PLOTTERS_G */
2572
2573#if FZ_PLOTTERS_RGB
2574#define DA
2575#define N 3
2576#include "paint-glyph.h"
2577
2578#define DA
2579#define ALPHA
2580#define N 3
2581#include "paint-glyph.h"
2582
2583#define N 3
2584#include "paint-glyph.h"
2585
2586#define ALPHA
2587#define N 3
2588#include "paint-glyph.h"
2589#endif /* FZ_PLOTTERS_RGB */
2590
2591#if FZ_PLOTTERS_CMYK
2592#define DA
2593#define N 4
2594#include "paint-glyph.h"
2595
2596#define DA
2597#define ALPHA
2598#define N 4
2599#include "paint-glyph.h"
2600
2601#define ALPHA
2602#define N 4
2603#include "paint-glyph.h"
2604
2605#define N 4
2606#include "paint-glyph.h"
2607#endif /* FZ_PLOTTERS_CMYK */
2608
2609#if FZ_PLOTTERS_N
2610#define ALPHA
2611#include "paint-glyph.h"
2612
2613#define DA
2614#include "paint-glyph.h"
2615
2616#define DA
2617#define ALPHA
2618#include "paint-glyph.h"
2619
2620#include "paint-glyph.h"
2621#endif /* FZ_PLOTTERS_N */
2622
2623#if FZ_ENABLE_SPOT_RENDERING
2624#define ALPHA
2625#define EOP
2626#include "paint-glyph.h"
2627
2628#define DA
2629#define EOP
2630#include "paint-glyph.h"
2631
2632#define DA
2633#define ALPHA
2634#define EOP
2635#include "paint-glyph.h"
2636
2637#define EOP
2638#include "paint-glyph.h"
2639#endif /* FZ_ENABLE_SPOT_RENDERING */
2640
2641static inline void
2642fz_paint_glyph_alpha(const unsigned char * FZ_RESTRICT colorbv, int n, int span, unsigned char * FZ_RESTRICT dp, int da, const fz_glyph *glyph, int w, int h, int skip_x, int skip_y, const fz_overprint * FZ_RESTRICT eop)
2643{
2644#if FZ_ENABLE_SPOT_RENDERING
2645 if (fz_overprint_required(eop))
2646 {
2647 if (da)
2648 fz_paint_glyph_alpha_N_da_op(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y, eop);
2649 else
2650 fz_paint_glyph_alpha_N_op(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y, eop);
2651 return;
2652 }
2653#endif /* FZ_ENABLE_SPOT_RENDERING */
2654 switch (n)
2655 {
2656 case 1:
2657 if (da)
2658#if FZ_PLOTTERS_G
2659 fz_paint_glyph_alpha_1_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2660#else
2661 goto fallback;
2662#endif /* FZ_PLOTTERS_G */
2663 else
2664 fz_paint_glyph_alpha_1(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2665 break;
2666#if FZ_PLOTTERS_RGB
2667 case 3:
2668 if (da)
2669 fz_paint_glyph_alpha_3_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2670 else
2671 fz_paint_glyph_alpha_3(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2672 break;
2673#endif /* FZ_PLOTTERS_RGB */
2674#if FZ_PLOTTERS_CMYK
2675 case 4:
2676 if (da)
2677 fz_paint_glyph_alpha_4_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2678 else
2679 fz_paint_glyph_alpha_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2680 break;
2681#endif /* FZ_PLOTTERS_CMYK */
2682 default:
2683 {
2684#if !FZ_PLOTTERS_G
2685fallback:{}
2686#endif /* !FZ_PLOTTERS_G */
2687#if FZ_PLOTTERS_N
2688 if (da)
2689 fz_paint_glyph_alpha_N_da(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
2690 else
2691 fz_paint_glyph_alpha_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
2692#endif /* FZ_PLOTTERS_N */
2693 break;
2694 }
2695 }
2696}
2697
2698static inline void
2699fz_paint_glyph_solid(const unsigned char * FZ_RESTRICT colorbv, int n, int span, unsigned char * FZ_RESTRICT dp, int da, const fz_glyph * FZ_RESTRICT glyph, int w, int h, int skip_x, int skip_y, const fz_overprint * FZ_RESTRICT eop)
2700{
2701#if FZ_ENABLE_SPOT_RENDERING
2702 if (fz_overprint_required(eop))
2703 {
2704 if (da)
2705 fz_paint_glyph_solid_N_da_op(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y, eop);
2706 else
2707 fz_paint_glyph_solid_N_op(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y, eop);
2708 return;
2709 }
2710#endif /* FZ_ENABLE_SPOT_RENDERING */
2711 switch (n)
2712 {
2713 case 1:
2714 if (da)
2715#if FZ_PLOTTERS_G
2716 fz_paint_glyph_solid_1_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2717#else
2718 goto fallback;
2719#endif /* FZ_PLOTTERS_G */
2720 else
2721 fz_paint_glyph_solid_1(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2722 break;
2723#if FZ_PLOTTERS_RGB
2724 case 3:
2725 if (da)
2726 fz_paint_glyph_solid_3_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2727 else
2728 fz_paint_glyph_solid_3(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2729 break;
2730#endif /* FZ_PLOTTERS_RGB */
2731#if FZ_PLOTTERS_CMYK
2732 case 4:
2733 if (da)
2734 fz_paint_glyph_solid_4_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2735 else
2736 fz_paint_glyph_solid_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
2737 break;
2738#endif /* FZ_PLOTTERS_CMYK */
2739 default:
2740 {
2741#if !FZ_PLOTTERS_G
2742fallback:{}
2743#endif /* FZ_PLOTTERS_G */
2744#if FZ_PLOTTERS_N
2745 if (da)
2746 fz_paint_glyph_solid_N_da(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
2747 else
2748 fz_paint_glyph_solid_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
2749 break;
2750#endif /* FZ_PLOTTERS_N */
2751 }
2752 }
2753}
2754
2755void
2756fz_paint_glyph(const unsigned char * FZ_RESTRICT colorbv, fz_pixmap * FZ_RESTRICT dst, unsigned char * FZ_RESTRICT dp, const fz_glyph * FZ_RESTRICT glyph, int w, int h, int skip_x, int skip_y, const fz_overprint * FZ_RESTRICT eop)
2757{
2758 int n = dst->n - dst->alpha;
2759 if (dst->colorspace)
2760 {
2761 assert(n > 0);
2762 if (colorbv[n] == 255)
2763 fz_paint_glyph_solid(colorbv, n, dst->stride, dp, dst->alpha, glyph, w, h, skip_x, skip_y, eop);
2764 else if (colorbv[n] != 0)
2765 fz_paint_glyph_alpha(colorbv, n, dst->stride, dp, dst->alpha, glyph, w, h, skip_x, skip_y, eop);
2766 }
2767 else
2768 {
2769 assert(dst->alpha && dst->n == 1 && dst->colorspace == NULL && !fz_overprint_required(eop));
2770 fz_paint_glyph_mask(dst->stride, dp, dst->alpha, glyph, w, h, skip_x, skip_y);
2771 }
2772}
2773