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