Coverage Report

Created: 2026-08-14 07:34

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