Coverage Report

Created: 2025-12-03 07:00

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