Coverage Report

Created: 2026-08-13 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xpdf-4.06/xpdf/GfxState.cc
Line
Count
Source
1
//========================================================================
2
//
3
// GfxState.cc
4
//
5
// Copyright 1996-2016 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
#include <aconf.h>
10
11
#include <stddef.h>
12
#include <math.h>
13
#include <string.h>
14
#include "gmem.h"
15
#include "gmempp.h"
16
#include "Error.h"
17
#include "GlobalParams.h"
18
#include "LocalParams.h"
19
#include "Object.h"
20
#include "Array.h"
21
#include "Page.h"
22
#include "XRef.h"
23
#include "GfxState.h"
24
25
//------------------------------------------------------------------------
26
27
// Max depth of nested color spaces.  This is used to catch infinite
28
// loops in the color space object structure.
29
112k
#define colorSpaceRecursionLimit 8
30
31
32
//------------------------------------------------------------------------
33
34
16.8M
static inline GfxColorComp clip01(GfxColorComp x) {
35
16.8M
  return (x < 0) ? 0 : (x > gfxColorComp1) ? gfxColorComp1 : x;
36
16.8M
}
37
38
75.2k
static inline double clip01(double x) {
39
75.2k
  return (x < 0) ? 0 : (x > 1) ? 1 : x;
40
75.2k
}
41
42
//------------------------------------------------------------------------
43
44
struct GfxBlendModeInfo {
45
  const char *name;
46
  GfxBlendMode mode;
47
};
48
49
static GfxBlendModeInfo gfxBlendModeNames[] = {
50
  { "Normal",     gfxBlendNormal },
51
  { "Compatible", gfxBlendNormal },
52
  { "Multiply",   gfxBlendMultiply },
53
  { "Screen",     gfxBlendScreen },
54
  { "Overlay",    gfxBlendOverlay },
55
  { "Darken",     gfxBlendDarken },
56
  { "Lighten",    gfxBlendLighten },
57
  { "ColorDodge", gfxBlendColorDodge },
58
  { "ColorBurn",  gfxBlendColorBurn },
59
  { "HardLight",  gfxBlendHardLight },
60
  { "SoftLight",  gfxBlendSoftLight },
61
  { "Difference", gfxBlendDifference },
62
  { "Exclusion",  gfxBlendExclusion },
63
  { "Hue",        gfxBlendHue },
64
  { "Saturation", gfxBlendSaturation },
65
  { "Color",      gfxBlendColor },
66
  { "Luminosity", gfxBlendLuminosity }
67
};
68
69
#define nGfxBlendModeNames \
70
46.9k
          ((int)((sizeof(gfxBlendModeNames) / sizeof(GfxBlendModeInfo))))
71
72
//------------------------------------------------------------------------
73
74
// NB: This must match the GfxColorSpaceMode enum defined in
75
// GfxState.h
76
static const char *gfxColorSpaceModeNames[] = {
77
  "DeviceGray",
78
  "CalGray",
79
  "DeviceRGB",
80
  "CalRGB",
81
  "DeviceCMYK",
82
  "Lab",
83
  "ICCBased",
84
  "Indexed",
85
  "Separation",
86
  "DeviceN",
87
  "Pattern"
88
};
89
90
0
#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *)))
91
92
93
94
95
//------------------------------------------------------------------------
96
// GfxColorSpace
97
//------------------------------------------------------------------------
98
99
6.07M
GfxColorSpace::GfxColorSpace() {
100
6.07M
  overprintMask = 0x0f;
101
6.07M
  defaultColorSpace = gFalse;
102
6.07M
}
103
104
6.06M
GfxColorSpace::~GfxColorSpace() {
105
6.06M
}
106
107
GfxColorSpace *GfxColorSpace::parse(Object *csObj,
108
112k
            int recursion) {
109
112k
  GfxColorSpace *cs;
110
112k
  Object obj1;
111
112
112k
  if (recursion > colorSpaceRecursionLimit) {
113
38
    error(errSyntaxError, -1, "Loop detected in color space objects");
114
38
    return NULL;
115
38
  }
116
112k
  cs = NULL;
117
112k
  if (csObj->isName()) {
118
90.2k
    if (csObj->isName("DeviceGray") || csObj->isName("G")) {
119
18.0k
      cs = GfxColorSpace::create(csDeviceGray);
120
72.1k
    } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
121
14.3k
      cs = GfxColorSpace::create(csDeviceRGB);
122
57.8k
    } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
123
1.46k
      cs = GfxColorSpace::create(csDeviceCMYK);
124
56.3k
    } else if (csObj->isName("Pattern")) {
125
49.9k
      cs = new GfxPatternColorSpace(NULL);
126
49.9k
    } else {
127
6.42k
      error(errSyntaxError, -1, "Bad color space '{0:s}'", csObj->getName());
128
6.42k
    }
129
90.2k
  } else if (csObj->isArray() && csObj->arrayGetLength() > 0) {
130
20.7k
    csObj->arrayGet(0, &obj1);
131
20.7k
    if (obj1.isName("DeviceGray") || obj1.isName("G")) {
132
23
      cs = GfxColorSpace::create(csDeviceGray);
133
20.7k
    } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
134
21
      cs = GfxColorSpace::create(csDeviceRGB);
135
20.7k
    } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
136
0
      cs = GfxColorSpace::create(csDeviceCMYK);
137
20.7k
    } else if (obj1.isName("CalGray")) {
138
661
      cs = GfxCalGrayColorSpace::parse(csObj->getArray(), recursion);
139
20.0k
    } else if (obj1.isName("CalRGB")) {
140
121
      cs = GfxCalRGBColorSpace::parse(csObj->getArray(), recursion);
141
19.9k
    } else if (obj1.isName("Lab")) {
142
1.01k
      cs = GfxLabColorSpace::parse(csObj->getArray(), recursion);
143
18.9k
    } else if (obj1.isName("ICCBased")) {
144
8.15k
      cs = GfxICCBasedColorSpace::parse(csObj->getArray(),
145
8.15k
          recursion);
146
10.7k
    } else if (obj1.isName("Indexed") || obj1.isName("I")) {
147
1.91k
      cs = GfxIndexedColorSpace::parse(csObj->getArray(),
148
1.91k
               recursion);
149
8.86k
    } else if (obj1.isName("Separation")) {
150
2.94k
      cs = GfxSeparationColorSpace::parse(csObj->getArray(),
151
2.94k
            recursion);
152
5.91k
    } else if (obj1.isName("DeviceN")) {
153
1.64k
      cs = GfxDeviceNColorSpace::parse(csObj->getArray(),
154
1.64k
               recursion);
155
4.27k
    } else if (obj1.isName("Pattern")) {
156
3.55k
      cs = GfxPatternColorSpace::parse(csObj->getArray(),
157
3.55k
               recursion);
158
3.55k
    } else {
159
717
      error(errSyntaxError, -1, "Bad color space");
160
717
    }
161
20.7k
    obj1.free();
162
20.7k
  } else {
163
1.27k
    error(errSyntaxError, -1, "Bad color space - expected name or array");
164
1.27k
  }
165
112k
  return cs;
166
112k
}
167
168
1.10M
GfxColorSpace *GfxColorSpace::create(GfxColorSpaceMode mode) {
169
1.10M
  GfxColorSpace *cs;
170
171
1.10M
  cs = NULL;
172
1.10M
  if (mode == csDeviceGray) {
173
959k
    cs = new GfxDeviceGrayColorSpace();
174
959k
  } else if (mode == csDeviceRGB) {
175
134k
    cs = new GfxDeviceRGBColorSpace();
176
134k
  } else if (mode == csDeviceCMYK) {
177
12.8k
    cs = new GfxDeviceCMYKColorSpace();
178
12.8k
  }
179
1.10M
  return cs;
180
1.10M
}
181
182
void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
183
26.8k
             int maxImgPixel) {
184
26.8k
  int i;
185
186
69.7k
  for (i = 0; i < getNComps(); ++i) {
187
42.9k
    decodeLow[i] = 0;
188
42.9k
    decodeRange[i] = 1;
189
42.9k
  }
190
26.8k
}
191
192
0
int GfxColorSpace::getNumColorSpaceModes() {
193
0
  return nGfxColorSpaceModes;
194
0
}
195
196
0
const char *GfxColorSpace::getColorSpaceModeName(int idx) {
197
0
  return gfxColorSpaceModeNames[idx];
198
0
}
199
200
//------------------------------------------------------------------------
201
// GfxDeviceGrayColorSpace
202
//------------------------------------------------------------------------
203
204
4.14M
GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() {
205
4.14M
}
206
207
GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() {
208
}
209
210
3.18M
GfxColorSpace *GfxDeviceGrayColorSpace::copy() {
211
3.18M
  GfxDeviceGrayColorSpace *cs;
212
213
3.18M
  cs = new GfxDeviceGrayColorSpace();
214
3.18M
  return cs;
215
3.18M
}
216
217
218
void GfxDeviceGrayColorSpace::getGray(GfxColor *color, GfxGray *gray,
219
480k
              GfxRenderingIntent ri) {
220
480k
  *gray = clip01(color->c[0]);
221
480k
}
222
223
void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
224
2.36M
             GfxRenderingIntent ri) {
225
2.36M
  rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
226
2.36M
}
227
228
void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
229
45.6k
              GfxRenderingIntent ri) {
230
45.6k
  cmyk->c = cmyk->m = cmyk->y = 0;
231
45.6k
  cmyk->k = clip01(gfxColorComp1 - color->c[0]);
232
45.6k
}
233
234
235
236
64.9k
void GfxDeviceGrayColorSpace::getDefaultColor(GfxColor *color) {
237
64.9k
  color->c[0] = 0;
238
64.9k
}
239
240
//------------------------------------------------------------------------
241
// GfxCalGrayColorSpace
242
//------------------------------------------------------------------------
243
244
579
GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
245
579
  whiteX = whiteY = whiteZ = 1;
246
579
  blackX = blackY = blackZ = 0;
247
579
  gamma = 1;
248
579
}
249
250
GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
251
}
252
253
30
GfxColorSpace *GfxCalGrayColorSpace::copy() {
254
30
  GfxCalGrayColorSpace *cs;
255
256
30
  cs = new GfxCalGrayColorSpace();
257
30
  cs->whiteX = whiteX;
258
30
  cs->whiteY = whiteY;
259
30
  cs->whiteZ = whiteZ;
260
30
  cs->blackX = blackX;
261
30
  cs->blackY = blackY;
262
30
  cs->blackZ = blackZ;
263
30
  cs->gamma = gamma;
264
30
  return cs;
265
30
}
266
267
268
661
GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr, int recursion) {
269
661
  GfxCalGrayColorSpace *cs;
270
661
  Object obj1, obj2, obj3;
271
272
661
  if (arr->getLength() < 2) {
273
19
    error(errSyntaxError, -1, "Bad CalGray color space");
274
19
    return NULL;
275
19
  }
276
642
  arr->get(1, &obj1);
277
642
  if (!obj1.isDict()) {
278
93
    error(errSyntaxError, -1, "Bad CalGray color space");
279
93
    obj1.free();
280
93
    return NULL;
281
93
  }
282
549
  cs = new GfxCalGrayColorSpace();
283
549
  if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
284
470
      obj2.arrayGetLength() == 3) {
285
312
    obj2.arrayGet(0, &obj3);
286
312
    cs->whiteX = obj3.getNum();
287
312
    obj3.free();
288
312
    obj2.arrayGet(1, &obj3);
289
312
    cs->whiteY = obj3.getNum();
290
312
    obj3.free();
291
312
    obj2.arrayGet(2, &obj3);
292
312
    cs->whiteZ = obj3.getNum();
293
312
    obj3.free();
294
312
  }
295
549
  obj2.free();
296
549
  if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
297
457
      obj2.arrayGetLength() == 3) {
298
381
    obj2.arrayGet(0, &obj3);
299
381
    cs->blackX = obj3.getNum();
300
381
    obj3.free();
301
381
    obj2.arrayGet(1, &obj3);
302
381
    cs->blackY = obj3.getNum();
303
381
    obj3.free();
304
381
    obj2.arrayGet(2, &obj3);
305
381
    cs->blackZ = obj3.getNum();
306
381
    obj3.free();
307
381
  }
308
549
  obj2.free();
309
549
  if (obj1.dictLookup("Gamma", &obj2)->isNum()) {
310
413
    cs->gamma = obj2.getNum();
311
413
  }
312
549
  obj2.free();
313
549
  obj1.free();
314
549
  return cs;
315
642
}
316
317
void GfxCalGrayColorSpace::getGray(GfxColor *color, GfxGray *gray,
318
0
           GfxRenderingIntent ri) {
319
0
  *gray = clip01(color->c[0]);
320
0
}
321
322
void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
323
1.15k
          GfxRenderingIntent ri) {
324
1.15k
  rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
325
1.15k
}
326
327
void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
328
0
           GfxRenderingIntent ri) {
329
0
  cmyk->c = cmyk->m = cmyk->y = 0;
330
0
  cmyk->k = clip01(gfxColorComp1 - color->c[0]);
331
0
}
332
333
334
335
549
void GfxCalGrayColorSpace::getDefaultColor(GfxColor *color) {
336
549
  color->c[0] = 0;
337
549
}
338
339
//------------------------------------------------------------------------
340
// GfxDeviceRGBColorSpace
341
//------------------------------------------------------------------------
342
343
1.69M
GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() {
344
1.69M
}
345
346
GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() {
347
}
348
349
1.56M
GfxColorSpace *GfxDeviceRGBColorSpace::copy() {
350
1.56M
  GfxDeviceRGBColorSpace *cs;
351
352
1.56M
  cs = new GfxDeviceRGBColorSpace();
353
1.56M
  return cs;
354
1.56M
}
355
356
357
void GfxDeviceRGBColorSpace::getGray(GfxColor *color, GfxGray *gray,
358
60
             GfxRenderingIntent ri) {
359
60
  *gray = clip01((GfxColorComp)(0.3  * color->c[0] +
360
60
        0.59 * color->c[1] +
361
60
        0.11 * color->c[2] + 0.5));
362
60
}
363
364
void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
365
2.12M
            GfxRenderingIntent ri) {
366
2.12M
  rgb->r = clip01(color->c[0]);
367
2.12M
  rgb->g = clip01(color->c[1]);
368
2.12M
  rgb->b = clip01(color->c[2]);
369
2.12M
}
370
371
void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
372
105
             GfxRenderingIntent ri) {
373
105
  GfxColorComp c, m, y, k;
374
375
105
  c = clip01(gfxColorComp1 - color->c[0]);
376
105
  m = clip01(gfxColorComp1 - color->c[1]);
377
105
  y = clip01(gfxColorComp1 - color->c[2]);
378
105
  k = c;
379
105
  if (m < k) {
380
46
    k = m;
381
46
  }
382
105
  if (y < k) {
383
46
    k = y;
384
46
  }
385
105
  cmyk->c = c - k;
386
105
  cmyk->m = m - k;
387
105
  cmyk->y = y - k;
388
105
  cmyk->k = k;
389
105
}
390
391
392
393
11
void GfxDeviceRGBColorSpace::getDefaultColor(GfxColor *color) {
394
11
  color->c[0] = 0;
395
11
  color->c[1] = 0;
396
11
  color->c[2] = 0;
397
11
}
398
399
//------------------------------------------------------------------------
400
// GfxCalRGBColorSpace
401
//------------------------------------------------------------------------
402
403
85
GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
404
85
  whiteX = whiteY = whiteZ = 1;
405
85
  blackX = blackY = blackZ = 0;
406
85
  gammaR = gammaG = gammaB = 1;
407
85
  mat[0] = 1; mat[1] = 0; mat[2] = 0;
408
85
  mat[3] = 0; mat[4] = 1; mat[5] = 0;
409
85
  mat[6] = 0; mat[7] = 0; mat[8] = 1;
410
85
}
411
412
GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
413
}
414
415
6
GfxColorSpace *GfxCalRGBColorSpace::copy() {
416
6
  GfxCalRGBColorSpace *cs;
417
6
  int i;
418
419
6
  cs = new GfxCalRGBColorSpace();
420
6
  cs->whiteX = whiteX;
421
6
  cs->whiteY = whiteY;
422
6
  cs->whiteZ = whiteZ;
423
6
  cs->blackX = blackX;
424
6
  cs->blackY = blackY;
425
6
  cs->blackZ = blackZ;
426
6
  cs->gammaR = gammaR;
427
6
  cs->gammaG = gammaG;
428
6
  cs->gammaB = gammaB;
429
60
  for (i = 0; i < 9; ++i) {
430
54
    cs->mat[i] = mat[i];
431
54
  }
432
6
  return cs;
433
6
}
434
435
121
GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr, int recursion) {
436
121
  GfxCalRGBColorSpace *cs;
437
121
  Object obj1, obj2, obj3;
438
121
  int i;
439
440
121
  if (arr->getLength() < 2) {
441
13
    error(errSyntaxError, -1, "Bad CalRGB color space");
442
13
    return NULL;
443
13
  }
444
108
  arr->get(1, &obj1);
445
108
  if (!obj1.isDict()) {
446
29
    error(errSyntaxError, -1, "Bad CalRGB color space");
447
29
    obj1.free();
448
29
    return NULL;
449
29
  }
450
79
  cs = new GfxCalRGBColorSpace();
451
79
  if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
452
17
      obj2.arrayGetLength() == 3) {
453
16
    obj2.arrayGet(0, &obj3);
454
16
    cs->whiteX = obj3.getNum();
455
16
    obj3.free();
456
16
    obj2.arrayGet(1, &obj3);
457
16
    cs->whiteY = obj3.getNum();
458
16
    obj3.free();
459
16
    obj2.arrayGet(2, &obj3);
460
16
    cs->whiteZ = obj3.getNum();
461
16
    obj3.free();
462
16
  }
463
79
  obj2.free();
464
79
  if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
465
0
      obj2.arrayGetLength() == 3) {
466
0
    obj2.arrayGet(0, &obj3);
467
0
    cs->blackX = obj3.getNum();
468
0
    obj3.free();
469
0
    obj2.arrayGet(1, &obj3);
470
0
    cs->blackY = obj3.getNum();
471
0
    obj3.free();
472
0
    obj2.arrayGet(2, &obj3);
473
0
    cs->blackZ = obj3.getNum();
474
0
    obj3.free();
475
0
  }
476
79
  obj2.free();
477
79
  if (obj1.dictLookup("Gamma", &obj2)->isArray() &&
478
28
      obj2.arrayGetLength() == 3) {
479
7
    obj2.arrayGet(0, &obj3);
480
7
    cs->gammaR = obj3.getNum();
481
7
    obj3.free();
482
7
    obj2.arrayGet(1, &obj3);
483
7
    cs->gammaG = obj3.getNum();
484
7
    obj3.free();
485
7
    obj2.arrayGet(2, &obj3);
486
7
    cs->gammaB = obj3.getNum();
487
7
    obj3.free();
488
7
  }
489
79
  obj2.free();
490
79
  if (obj1.dictLookup("Matrix", &obj2)->isArray() &&
491
7
      obj2.arrayGetLength() == 9) {
492
60
    for (i = 0; i < 9; ++i) {
493
54
      obj2.arrayGet(i, &obj3);
494
54
      cs->mat[i] = obj3.getNum();
495
54
      obj3.free();
496
54
    }
497
6
  }
498
79
  obj2.free();
499
79
  obj1.free();
500
79
  return cs;
501
108
}
502
503
504
void GfxCalRGBColorSpace::getGray(GfxColor *color, GfxGray *gray,
505
0
          GfxRenderingIntent ri) {
506
0
  *gray = clip01((GfxColorComp)(0.299 * color->c[0] +
507
0
        0.587 * color->c[1] +
508
0
        0.114 * color->c[2] + 0.5));
509
0
}
510
511
void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
512
142
         GfxRenderingIntent ri) {
513
142
  rgb->r = clip01(color->c[0]);
514
142
  rgb->g = clip01(color->c[1]);
515
142
  rgb->b = clip01(color->c[2]);
516
142
}
517
518
void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
519
0
          GfxRenderingIntent ri) {
520
0
  GfxColorComp c, m, y, k;
521
522
0
  c = clip01(gfxColorComp1 - color->c[0]);
523
0
  m = clip01(gfxColorComp1 - color->c[1]);
524
0
  y = clip01(gfxColorComp1 - color->c[2]);
525
0
  k = c;
526
0
  if (m < k) {
527
0
    k = m;
528
0
  }
529
0
  if (y < k) {
530
0
    k = y;
531
0
  }
532
0
  cmyk->c = c - k;
533
0
  cmyk->m = m - k;
534
0
  cmyk->y = y - k;
535
0
  cmyk->k = k;
536
0
}
537
538
539
540
73
void GfxCalRGBColorSpace::getDefaultColor(GfxColor *color) {
541
73
  color->c[0] = 0;
542
73
  color->c[1] = 0;
543
73
  color->c[2] = 0;
544
73
}
545
546
//------------------------------------------------------------------------
547
// GfxDeviceCMYKColorSpace
548
//------------------------------------------------------------------------
549
550
38.9k
GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
551
38.9k
}
552
553
GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
554
}
555
556
26.0k
GfxColorSpace *GfxDeviceCMYKColorSpace::copy() {
557
26.0k
  GfxDeviceCMYKColorSpace *cs;
558
559
26.0k
  cs = new GfxDeviceCMYKColorSpace();
560
26.0k
  return cs;
561
26.0k
}
562
563
564
void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, GfxGray *gray,
565
10
              GfxRenderingIntent ri) {
566
10
  *gray = clip01((GfxColorComp)(gfxColorComp1 - color->c[3]
567
10
        - 0.3  * color->c[0]
568
10
        - 0.59 * color->c[1]
569
10
        - 0.11 * color->c[2] + 0.5));
570
10
}
571
572
void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
573
2.53M
             GfxRenderingIntent ri) {
574
2.53M
  double c, m, y, k, c1, m1, y1, k1, r, g, b, x;
575
576
2.53M
  c = colToDbl(color->c[0]);
577
2.53M
  m = colToDbl(color->c[1]);
578
2.53M
  y = colToDbl(color->c[2]);
579
2.53M
  k = colToDbl(color->c[3]);
580
2.53M
  c1 = 1 - c;
581
2.53M
  m1 = 1 - m;
582
2.53M
  y1 = 1 - y;
583
2.53M
  k1 = 1 - k;
584
  // this is a matrix multiplication, unrolled for performance
585
  //                        C M Y K
586
2.53M
  x = c1 * m1 * y1 * k1; // 0 0 0 0
587
2.53M
  r = g = b = x;
588
2.53M
  x = c1 * m1 * y1 * k;  // 0 0 0 1
589
2.53M
  r += 0.1373 * x;
590
2.53M
  g += 0.1216 * x;
591
2.53M
  b += 0.1255 * x;
592
2.53M
  x = c1 * m1 * y  * k1; // 0 0 1 0
593
2.53M
  r += x;
594
2.53M
  g += 0.9490 * x;
595
2.53M
  x = c1 * m1 * y  * k;  // 0 0 1 1
596
2.53M
  r += 0.1098 * x;
597
2.53M
  g += 0.1020 * x;
598
2.53M
  x = c1 * m  * y1 * k1; // 0 1 0 0
599
2.53M
  r += 0.9255 * x;
600
2.53M
  b += 0.5490 * x;
601
2.53M
  x = c1 * m  * y1 * k;  // 0 1 0 1
602
2.53M
  r += 0.1412 * x;
603
2.53M
  x = c1 * m  * y  * k1; // 0 1 1 0
604
2.53M
  r += 0.9294 * x;
605
2.53M
  g += 0.1098 * x;
606
2.53M
  b += 0.1412 * x;
607
2.53M
  x = c1 * m  * y  * k;  // 0 1 1 1
608
2.53M
  r += 0.1333 * x;
609
2.53M
  x = c  * m1 * y1 * k1; // 1 0 0 0
610
2.53M
  g += 0.6784 * x;
611
2.53M
  b += 0.9373 * x;
612
2.53M
  x = c  * m1 * y1 * k;  // 1 0 0 1
613
2.53M
  g += 0.0588 * x;
614
2.53M
  b += 0.1412 * x;
615
2.53M
  x = c  * m1 * y  * k1; // 1 0 1 0
616
2.53M
  g += 0.6510 * x;
617
2.53M
  b += 0.3137 * x;
618
2.53M
  x = c  * m1 * y  * k;  // 1 0 1 1
619
2.53M
  g += 0.0745 * x;
620
2.53M
  x = c  * m  * y1 * k1; // 1 1 0 0
621
2.53M
  r += 0.1804 * x;
622
2.53M
  g += 0.1922 * x;
623
2.53M
  b += 0.5725 * x;
624
2.53M
  x = c  * m  * y1 * k;  // 1 1 0 1
625
2.53M
  b += 0.0078 * x;
626
2.53M
  x = c  * m  * y  * k1; // 1 1 1 0
627
2.53M
  r += 0.2118 * x;
628
2.53M
  g += 0.2119 * x;
629
2.53M
  b += 0.2235 * x;
630
2.53M
  rgb->r = clip01(dblToCol(r));
631
2.53M
  rgb->g = clip01(dblToCol(g));
632
2.53M
  rgb->b = clip01(dblToCol(b));
633
2.53M
}
634
635
void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
636
233
              GfxRenderingIntent ri) {
637
233
  cmyk->c = clip01(color->c[0]);
638
233
  cmyk->m = clip01(color->c[1]);
639
233
  cmyk->y = clip01(color->c[2]);
640
233
  cmyk->k = clip01(color->c[3]);
641
233
}
642
643
644
645
7
void GfxDeviceCMYKColorSpace::getDefaultColor(GfxColor *color) {
646
7
  color->c[0] = 0;
647
7
  color->c[1] = 0;
648
7
  color->c[2] = 0;
649
7
  color->c[3] = gfxColorComp1;
650
7
}
651
652
653
//------------------------------------------------------------------------
654
// GfxLabColorSpace
655
//------------------------------------------------------------------------
656
657
// This is the inverse of MatrixLMN in Example 4.10 from the PostScript
658
// Language Reference, Third Edition.
659
static double xyzrgb[3][3] = {
660
  {  3.240449, -1.537136, -0.498531 },
661
  { -0.969265,  1.876011,  0.041556 },
662
  {  0.055643, -0.204026,  1.057229 }
663
};
664
665
1.62k
GfxLabColorSpace::GfxLabColorSpace() {
666
1.62k
  whiteX = whiteY = whiteZ = 1;
667
1.62k
  blackX = blackY = blackZ = 0;
668
1.62k
  aMin = bMin = -100;
669
1.62k
  aMax = bMax = 100;
670
1.62k
}
671
672
GfxLabColorSpace::~GfxLabColorSpace() {
673
}
674
675
651
GfxColorSpace *GfxLabColorSpace::copy() {
676
651
  GfxLabColorSpace *cs;
677
678
651
  cs = new GfxLabColorSpace();
679
651
  cs->whiteX = whiteX;
680
651
  cs->whiteY = whiteY;
681
651
  cs->whiteZ = whiteZ;
682
651
  cs->blackX = blackX;
683
651
  cs->blackY = blackY;
684
651
  cs->blackZ = blackZ;
685
651
  cs->aMin = aMin;
686
651
  cs->aMax = aMax;
687
651
  cs->bMin = bMin;
688
651
  cs->bMax = bMax;
689
651
  cs->kr = kr;
690
651
  cs->kg = kg;
691
651
  cs->kb = kb;
692
651
  return cs;
693
651
}
694
695
1.01k
GfxColorSpace *GfxLabColorSpace::parse(Array *arr, int recursion) {
696
1.01k
  GfxLabColorSpace *cs;
697
1.01k
  Object obj1, obj2, obj3;
698
699
1.01k
  if (arr->getLength() < 2) {
700
23
    error(errSyntaxError, -1, "Bad Lab color space");
701
23
    return NULL;
702
23
  }
703
993
  arr->get(1, &obj1);
704
993
  if (!obj1.isDict()) {
705
18
    error(errSyntaxError, -1, "Bad Lab color space");
706
18
    obj1.free();
707
18
    return NULL;
708
18
  }
709
975
  cs = new GfxLabColorSpace();
710
975
  if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
711
501
      obj2.arrayGetLength() == 3) {
712
438
    obj2.arrayGet(0, &obj3);
713
438
    cs->whiteX = obj3.getNum();
714
438
    obj3.free();
715
438
    obj2.arrayGet(1, &obj3);
716
438
    cs->whiteY = obj3.getNum();
717
438
    obj3.free();
718
438
    obj2.arrayGet(2, &obj3);
719
438
    cs->whiteZ = obj3.getNum();
720
438
    obj3.free();
721
438
  }
722
975
  obj2.free();
723
975
  if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
724
546
      obj2.arrayGetLength() == 3) {
725
485
    obj2.arrayGet(0, &obj3);
726
485
    cs->blackX = obj3.getNum();
727
485
    obj3.free();
728
485
    obj2.arrayGet(1, &obj3);
729
485
    cs->blackY = obj3.getNum();
730
485
    obj3.free();
731
485
    obj2.arrayGet(2, &obj3);
732
485
    cs->blackZ = obj3.getNum();
733
485
    obj3.free();
734
485
  }
735
975
  obj2.free();
736
975
  if (obj1.dictLookup("Range", &obj2)->isArray() &&
737
384
      obj2.arrayGetLength() == 4) {
738
321
    obj2.arrayGet(0, &obj3);
739
321
    cs->aMin = obj3.getNum();
740
321
    obj3.free();
741
321
    obj2.arrayGet(1, &obj3);
742
321
    cs->aMax = obj3.getNum();
743
321
    obj3.free();
744
321
    obj2.arrayGet(2, &obj3);
745
321
    cs->bMin = obj3.getNum();
746
321
    obj3.free();
747
321
    obj2.arrayGet(3, &obj3);
748
321
    cs->bMax = obj3.getNum();
749
321
    obj3.free();
750
321
  }
751
975
  obj2.free();
752
975
  obj1.free();
753
754
975
  cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
755
975
    xyzrgb[0][1] * cs->whiteY +
756
975
    xyzrgb[0][2] * cs->whiteZ);
757
975
  cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
758
975
    xyzrgb[1][1] * cs->whiteY +
759
975
    xyzrgb[1][2] * cs->whiteZ);
760
975
  cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
761
975
    xyzrgb[2][1] * cs->whiteY +
762
975
    xyzrgb[2][2] * cs->whiteZ);
763
764
975
  return cs;
765
993
}
766
767
768
void GfxLabColorSpace::getGray(GfxColor *color, GfxGray *gray,
769
0
             GfxRenderingIntent ri) {
770
0
  GfxRGB rgb;
771
772
0
  getRGB(color, &rgb, ri);
773
0
  *gray = clip01((GfxColorComp)(0.299 * rgb.r +
774
0
        0.587 * rgb.g +
775
0
        0.114 * rgb.b + 0.5));
776
0
}
777
778
void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
779
25.0k
            GfxRenderingIntent ri) {
780
25.0k
  double X, Y, Z;
781
25.0k
  double t1, t2;
782
25.0k
  double r, g, b;
783
784
785
  // convert L*a*b* to CIE 1931 XYZ color space
786
25.0k
  t1 = (colToDbl(color->c[0]) + 16) / 116;
787
25.0k
  t2 = t1 + colToDbl(color->c[1]) / 500;
788
25.0k
  if (t2 >= (6.0 / 29.0)) {
789
18.0k
    X = t2 * t2 * t2;
790
18.0k
  } else {
791
7.03k
    X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
792
7.03k
  }
793
25.0k
  X *= whiteX;
794
25.0k
  if (t1 >= (6.0 / 29.0)) {
795
18.0k
    Y = t1 * t1 * t1;
796
18.0k
  } else {
797
7.00k
    Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
798
7.00k
  }
799
25.0k
  Y *= whiteY;
800
25.0k
  t2 = t1 - colToDbl(color->c[2]) / 200;
801
25.0k
  if (t2 >= (6.0 / 29.0)) {
802
24.0k
    Z = t2 * t2 * t2;
803
24.0k
  } else {
804
990
    Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
805
990
  }
806
25.0k
  Z *= whiteZ;
807
808
  // convert XYZ to RGB, including gamut mapping and gamma correction
809
25.0k
  r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
810
25.0k
  g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
811
25.0k
  b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
812
25.0k
  rgb->r = dblToCol(pow(clip01(r * kr), 0.5));
813
25.0k
  rgb->g = dblToCol(pow(clip01(g * kg), 0.5));
814
25.0k
  rgb->b = dblToCol(pow(clip01(b * kb), 0.5));
815
25.0k
}
816
817
void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
818
0
             GfxRenderingIntent ri) {
819
0
  GfxRGB rgb;
820
0
  GfxColorComp c, m, y, k;
821
822
823
0
  getRGB(color, &rgb, ri);
824
0
  c = clip01(gfxColorComp1 - rgb.r);
825
0
  m = clip01(gfxColorComp1 - rgb.g);
826
0
  y = clip01(gfxColorComp1 - rgb.b);
827
0
  k = c;
828
0
  if (m < k) {
829
0
    k = m;
830
0
  }
831
0
  if (y < k) {
832
0
    k = y;
833
0
  }
834
0
  cmyk->c = c - k;
835
0
  cmyk->m = m - k;
836
0
  cmyk->y = y - k;
837
0
  cmyk->k = k;
838
0
}
839
840
841
842
170
void GfxLabColorSpace::getDefaultColor(GfxColor *color) {
843
170
  color->c[0] = 0;
844
170
  if (aMin > 0) {
845
14
    color->c[1] = dblToCol(aMin);
846
156
  } else if (aMax < 0) {
847
0
    color->c[1] = dblToCol(aMax);
848
156
  } else {
849
156
    color->c[1] = 0;
850
156
  }
851
170
  if (bMin > 0) {
852
28
    color->c[2] = dblToCol(bMin);
853
142
  } else if (bMax < 0) {
854
0
    color->c[2] = dblToCol(bMax);
855
142
  } else {
856
142
    color->c[2] = 0;
857
142
  }
858
170
}
859
860
void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
861
904
          int maxImgPixel) {
862
904
  decodeLow[0] = 0;
863
904
  decodeRange[0] = 100;
864
904
  decodeLow[1] = aMin;
865
904
  decodeRange[1] = aMax - aMin;
866
904
  decodeLow[2] = bMin;
867
904
  decodeRange[2] = bMax - bMin;
868
904
}
869
870
//------------------------------------------------------------------------
871
// GfxICCBasedColorSpace
872
//------------------------------------------------------------------------
873
874
GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
875
3.58k
               Ref *iccProfileStreamA) {
876
3.58k
  nComps = nCompsA;
877
3.58k
  alt = altA;
878
3.58k
  iccProfileStream = *iccProfileStreamA;
879
3.58k
  rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
880
3.58k
  rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
881
3.58k
}
882
883
3.58k
GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
884
3.58k
  delete alt;
885
3.58k
}
886
887
1.96k
GfxColorSpace *GfxICCBasedColorSpace::copy() {
888
1.96k
  GfxICCBasedColorSpace *cs;
889
1.96k
  int i;
890
891
1.96k
  cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
892
9.80k
  for (i = 0; i < 4; ++i) {
893
7.84k
    cs->rangeMin[i] = rangeMin[i];
894
7.84k
    cs->rangeMax[i] = rangeMax[i];
895
7.84k
  }
896
1.96k
  return cs;
897
1.96k
}
898
899
GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr,
900
8.15k
              int recursion) {
901
8.15k
  GfxICCBasedColorSpace *cs;
902
8.15k
  Ref iccProfileStreamA;
903
8.15k
  int nCompsA;
904
8.15k
  GfxColorSpace *altA;
905
8.15k
  Dict *dict;
906
8.15k
  Object obj1, obj2, obj3;
907
8.15k
  int i;
908
909
8.15k
  if (arr->getLength() < 2) {
910
23
    error(errSyntaxError, -1, "Bad ICCBased color space");
911
23
    return NULL;
912
23
  }
913
8.13k
  arr->getNF(1, &obj1);
914
8.13k
  if (obj1.isRef()) {
915
7.82k
    iccProfileStreamA = obj1.getRef();
916
7.82k
  } else {
917
311
    iccProfileStreamA.num = 0;
918
311
    iccProfileStreamA.gen = 0;
919
311
  }
920
8.13k
  obj1.free();
921
8.13k
  arr->get(1, &obj1);
922
8.13k
  if (!obj1.isStream()) {
923
6.19k
    error(errSyntaxError, -1, "Bad ICCBased color space (stream)");
924
6.19k
    obj1.free();
925
6.19k
    return NULL;
926
6.19k
  }
927
1.93k
  dict = obj1.streamGetDict();
928
1.93k
  if (!dict->lookup("N", &obj2)->isInt()) {
929
240
    error(errSyntaxError, -1, "Bad ICCBased color space (N)");
930
240
    obj2.free();
931
240
    obj1.free();
932
240
    return NULL;
933
240
  }
934
1.69k
  nCompsA = obj2.getInt();
935
1.69k
  obj2.free();
936
1.69k
  if (!dict->lookup("Alternate", &obj2)->isNull() &&
937
1.43k
      (altA = GfxColorSpace::parse(&obj2,
938
1.43k
           recursion + 1))) {
939
1.28k
    if (altA->getNComps() != nCompsA) {
940
62
      error(errSyntaxError, -1,
941
62
      "Number of components in ICCBased color space doesn't match alternate color space");
942
62
      nCompsA = altA->getNComps();
943
62
    }
944
1.28k
  } else {
945
410
    switch (nCompsA) {
946
59
    case 1:
947
59
      altA = GfxColorSpace::create(csDeviceGray);
948
59
      break;
949
260
    case 3:
950
260
      altA = GfxColorSpace::create(csDeviceRGB);
951
260
      break;
952
27
    case 4:
953
27
      altA = GfxColorSpace::create(csDeviceCMYK);
954
27
      break;
955
64
    default:
956
64
      error(errSyntaxError, -1, "Bad ICCBased color space - invalid N");
957
64
      obj2.free();
958
64
      obj1.free();
959
64
      return NULL;
960
410
    }
961
410
  }
962
1.62k
  obj2.free();
963
1.62k
  cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA);
964
1.62k
  if (dict->lookup("Range", &obj2)->isArray() &&
965
20
      obj2.arrayGetLength() == 2 * nCompsA) {
966
56
    for (i = 0; i < nCompsA; ++i) {
967
42
      obj2.arrayGet(2*i, &obj3);
968
42
      cs->rangeMin[i] = obj3.getNum();
969
42
      obj3.free();
970
42
      obj2.arrayGet(2*i+1, &obj3);
971
42
      cs->rangeMax[i] = obj3.getNum();
972
42
      obj3.free();
973
42
    }
974
14
  }
975
1.62k
  obj2.free();
976
1.62k
  obj1.free();
977
1.62k
  return cs;
978
1.69k
}
979
980
981
void GfxICCBasedColorSpace::getGray(GfxColor *color, GfxGray *gray,
982
0
            GfxRenderingIntent ri) {
983
0
  alt->getGray(color, gray, ri);
984
0
}
985
986
void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
987
1.75M
           GfxRenderingIntent ri) {
988
1.75M
  alt->getRGB(color, rgb, ri);
989
1.75M
}
990
991
void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
992
0
            GfxRenderingIntent ri) {
993
0
  alt->getCMYK(color, cmyk, ri);
994
0
}
995
996
997
998
741
void GfxICCBasedColorSpace::getDefaultColor(GfxColor *color) {
999
741
  int i;
1000
1001
2.74k
  for (i = 0; i < nComps; ++i) {
1002
2.00k
    if (rangeMin[i] > 0) {
1003
0
      color->c[i] = dblToCol(rangeMin[i]);
1004
2.00k
    } else if (rangeMax[i] < 0) {
1005
0
      color->c[i] = dblToCol(rangeMax[i]);
1006
2.00k
    } else {
1007
2.00k
      color->c[i] = 0;
1008
2.00k
    }
1009
2.00k
  }
1010
741
}
1011
1012
void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
1013
               double *decodeRange,
1014
69
               int maxImgPixel) {
1015
69
  alt->getDefaultRanges(decodeLow, decodeRange, maxImgPixel);
1016
1017
#if 0
1018
  // this is nominally correct, but some PDF files don't set the
1019
  // correct ranges in the ICCBased dict
1020
  int i;
1021
1022
  for (i = 0; i < nComps; ++i) {
1023
    decodeLow[i] = rangeMin[i];
1024
    decodeRange[i] = rangeMax[i] - rangeMin[i];
1025
  }
1026
#endif
1027
69
}
1028
1029
1030
//------------------------------------------------------------------------
1031
// GfxIndexedColorSpace
1032
//------------------------------------------------------------------------
1033
1034
GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA,
1035
1.45k
             int indexHighA) {
1036
1.45k
  base = baseA;
1037
1.45k
  indexHigh = indexHighA;
1038
1.45k
  lookup = (Guchar *)gmallocn((indexHigh + 1) * base->getNComps(),
1039
1.45k
            sizeof(Guchar));
1040
1.45k
  overprintMask = base->getOverprintMask();
1041
1.45k
}
1042
1043
1.44k
GfxIndexedColorSpace::~GfxIndexedColorSpace() {
1044
1.44k
  delete base;
1045
1.44k
  gfree(lookup);
1046
1.44k
}
1047
1048
168
GfxColorSpace *GfxIndexedColorSpace::copy() {
1049
168
  GfxIndexedColorSpace *cs;
1050
1051
168
  cs = new GfxIndexedColorSpace(base->copy(), indexHigh);
1052
168
  memcpy(cs->lookup, lookup,
1053
168
   (indexHigh + 1) * base->getNComps() * sizeof(Guchar));
1054
168
  return cs;
1055
168
}
1056
1057
GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr,
1058
1.91k
             int recursion) {
1059
1.91k
  GfxIndexedColorSpace *cs;
1060
1.91k
  GfxColorSpace *baseA;
1061
1.91k
  int indexHighA;
1062
1.91k
  Object obj1;
1063
1.91k
  int x;
1064
1.91k
  char *s;
1065
1.91k
  int n, i, j;
1066
1067
1.91k
  if (arr->getLength() != 4) {
1068
107
    error(errSyntaxError, -1, "Bad Indexed color space");
1069
107
    goto err1;
1070
107
  }
1071
1.80k
  arr->get(1, &obj1);
1072
1.80k
  if (!(baseA = GfxColorSpace::parse(&obj1,
1073
1.80k
             recursion + 1))) {
1074
394
    error(errSyntaxError, -1, "Bad Indexed color space (base color space)");
1075
394
    goto err2;
1076
394
  }
1077
1.41k
  obj1.free();
1078
1.41k
  if (!arr->get(2, &obj1)->isInt()) {
1079
89
    error(errSyntaxError, -1, "Bad Indexed color space (hival)");
1080
89
    delete baseA;
1081
89
    goto err2;
1082
89
  }
1083
1.32k
  indexHighA = obj1.getInt();
1084
1.32k
  if (indexHighA < 0 || indexHighA > 255) {
1085
    // the PDF spec requires indexHigh to be in [0,255] -- allowing
1086
    // values larger than 255 creates a security hole: if nComps *
1087
    // indexHigh is greater than 2^31, the loop below may overwrite
1088
    // past the end of the array
1089
42
    error(errSyntaxError, -1,
1090
42
    "Bad Indexed color space (invalid indexHigh value)");
1091
42
    delete baseA;
1092
42
    goto err2;
1093
42
  }
1094
1.28k
  obj1.free();
1095
1.28k
  cs = new GfxIndexedColorSpace(baseA, indexHighA);
1096
1.28k
  arr->get(3, &obj1);
1097
1.28k
  n = baseA->getNComps();
1098
1.28k
  if (obj1.isStream()) {
1099
395
    obj1.streamReset();
1100
71.9k
    for (i = 0; i <= indexHighA; ++i) {
1101
283k
      for (j = 0; j < n; ++j) {
1102
211k
  if ((x = obj1.streamGetChar()) == EOF) {
1103
220
    error(errSyntaxError, -1,
1104
220
    "Bad Indexed color space (lookup table stream too short)");
1105
220
    cs->indexHigh = indexHighA = i - 1;
1106
220
    if (cs->indexHigh < 0) {
1107
24
      goto err3;
1108
24
    }
1109
220
  }
1110
211k
  cs->lookup[i*n + j] = (Guchar)x;
1111
211k
      }
1112
71.5k
    }
1113
371
    obj1.streamClose();
1114
887
  } else if (obj1.isString()) {
1115
752
    if (obj1.getString()->getLength() < (indexHighA + 1) * n) {
1116
70
      error(errSyntaxError, -1,
1117
70
      "Bad Indexed color space (lookup table string too short)");
1118
70
      cs->indexHigh = indexHighA = obj1.getString()->getLength() / n - 1;
1119
70
      if (cs->indexHigh < 0) {
1120
40
  goto err3;
1121
40
      }
1122
70
    }
1123
712
    s = obj1.getString()->getCString();
1124
5.09k
    for (i = 0; i <= indexHighA; ++i) {
1125
17.4k
      for (j = 0; j < n; ++j) {
1126
13.0k
  cs->lookup[i*n + j] = (Guchar)*s++;
1127
13.0k
      }
1128
4.37k
    }
1129
712
  } else {
1130
135
    error(errSyntaxError, -1, "Bad Indexed color space (lookup table)");
1131
135
    goto err3;
1132
135
  }
1133
1.08k
  obj1.free();
1134
1.08k
  return cs;
1135
1136
199
 err3:
1137
199
  delete cs;
1138
724
 err2:
1139
724
  obj1.free();
1140
831
 err1:
1141
831
  return NULL;
1142
724
}
1143
1144
1145
GfxColor *GfxIndexedColorSpace::mapColorToBase(GfxColor *color,
1146
469
                 GfxColor *baseColor) {
1147
469
  Guchar *p;
1148
469
  double low[gfxColorMaxComps], range[gfxColorMaxComps];
1149
469
  int n, i, k;
1150
1151
469
  n = base->getNComps();
1152
469
  base->getDefaultRanges(low, range, indexHigh);
1153
469
  k = (int)(colToDbl(color->c[0]) + 0.5);
1154
469
  if (k < 0) {
1155
104
    k = 0;
1156
365
  } else if (k > indexHigh) {
1157
13
    k = indexHigh;
1158
13
  }
1159
469
  p = &lookup[k * n];
1160
1.75k
  for (i = 0; i < n; ++i) {
1161
1.28k
    baseColor->c[i] = dblToCol(low[i] + (p[i] / 255.0) * range[i]);
1162
1.28k
  }
1163
469
  return baseColor;
1164
469
}
1165
1166
void GfxIndexedColorSpace::getGray(GfxColor *color, GfxGray *gray,
1167
0
           GfxRenderingIntent ri) {
1168
0
  GfxColor color2;
1169
1170
0
  base->getGray(mapColorToBase(color, &color2), gray, ri);
1171
0
}
1172
1173
void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
1174
469
          GfxRenderingIntent ri) {
1175
469
  GfxColor color2;
1176
1177
469
  base->getRGB(mapColorToBase(color, &color2), rgb, ri);
1178
469
}
1179
1180
void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
1181
0
           GfxRenderingIntent ri) {
1182
0
  GfxColor color2;
1183
1184
0
  base->getCMYK(mapColorToBase(color, &color2), cmyk, ri);
1185
0
}
1186
1187
1188
1189
67
void GfxIndexedColorSpace::getDefaultColor(GfxColor *color) {
1190
67
  color->c[0] = 0;
1191
67
}
1192
1193
void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
1194
              double *decodeRange,
1195
1.01k
              int maxImgPixel) {
1196
1.01k
  decodeLow[0] = 0;
1197
1.01k
  decodeRange[0] = maxImgPixel;
1198
1.01k
}
1199
1200
//------------------------------------------------------------------------
1201
// GfxSeparationColorSpace
1202
//------------------------------------------------------------------------
1203
1204
GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
1205
             GfxColorSpace *altA,
1206
892
             Function *funcA) {
1207
892
  name = nameA;
1208
892
  alt = altA;
1209
892
  func = funcA;
1210
892
  nonMarking = !name->cmp("None");
1211
892
  if (!name->cmp("Cyan")) {
1212
0
    overprintMask = 0x01;
1213
892
  } else if (!name->cmp("Magenta")) {
1214
0
    overprintMask = 0x02;
1215
892
  } else if (!name->cmp("Yellow")) {
1216
0
    overprintMask = 0x04;
1217
892
  } else if (!name->cmp("Black")) {
1218
367
    overprintMask = 0x08;
1219
367
  }
1220
892
}
1221
1222
GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
1223
             GfxColorSpace *altA,
1224
             Function *funcA,
1225
             GBool nonMarkingA,
1226
1.95k
             Guint overprintMaskA) {
1227
1.95k
  name = nameA;
1228
1.95k
  alt = altA;
1229
1.95k
  func = funcA;
1230
1.95k
  nonMarking = nonMarkingA;
1231
1.95k
  overprintMask = overprintMaskA;
1232
1.95k
}
1233
1234
2.84k
GfxSeparationColorSpace::~GfxSeparationColorSpace() {
1235
2.84k
  delete name;
1236
2.84k
  delete alt;
1237
2.84k
  delete func;
1238
2.84k
}
1239
1240
1.95k
GfxColorSpace *GfxSeparationColorSpace::copy() {
1241
1.95k
  GfxSeparationColorSpace *cs;
1242
1243
1.95k
  cs = new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy(),
1244
1.95k
           nonMarking, overprintMask);
1245
1.95k
  return cs;
1246
1.95k
}
1247
1248
GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr,
1249
2.94k
                int recursion) {
1250
2.94k
  GfxSeparationColorSpace *cs;
1251
2.94k
  GString *nameA;
1252
2.94k
  GfxColorSpace *altA;
1253
2.94k
  Function *funcA;
1254
2.94k
  Object obj1, obj2;
1255
1256
2.94k
  if (arr->getLength() != 4) {
1257
69
    error(errSyntaxError, -1, "Bad Separation color space");
1258
69
    goto err1;
1259
69
  }
1260
2.87k
  if (!arr->get(1, &obj1)->isName()) {
1261
38
    error(errSyntaxError, -1, "Bad Separation color space (name)");
1262
38
    goto err2;
1263
38
  }
1264
2.83k
  nameA = new GString(obj1.getName());
1265
2.83k
  obj1.free();
1266
2.83k
  arr->get(2, &obj1);
1267
  // some PDF generators use an ICC profile stream here; Adobe
1268
  // apparently looks at the /Alternate entry in the stream dictionary
1269
2.83k
  if (obj1.isStream() &&
1270
21
      !obj1.streamGetDict()->lookup("Alternate", &obj2)->isNull()) {
1271
0
    obj1.free();
1272
0
    obj1 = obj2;
1273
0
  }
1274
2.83k
  if (!(altA = GfxColorSpace::parse(&obj1,
1275
2.83k
            recursion + 1))) {
1276
107
    error(errSyntaxError, -1,
1277
107
    "Bad Separation color space (alternate color space)");
1278
107
    goto err3;
1279
107
  }
1280
2.73k
  obj1.free();
1281
2.73k
  arr->get(3, &obj1);
1282
2.73k
  if (!(funcA = Function::parse(&obj1, 1, altA->getNComps()))) {
1283
1.83k
    goto err4;
1284
1.83k
  }
1285
892
  obj1.free();
1286
892
  cs = new GfxSeparationColorSpace(nameA, altA, funcA);
1287
892
  return cs;
1288
1289
1.83k
 err4:
1290
1.83k
  delete altA;
1291
1.94k
 err3:
1292
1.94k
  delete nameA;
1293
1.98k
 err2:
1294
1.98k
  obj1.free();
1295
2.05k
 err1:
1296
2.05k
  return NULL;
1297
1.98k
}
1298
1299
1300
void GfxSeparationColorSpace::getGray(GfxColor *color, GfxGray *gray,
1301
0
              GfxRenderingIntent ri) {
1302
0
  double x;
1303
0
  double c[gfxColorMaxComps];
1304
0
  GfxColor color2;
1305
0
  int i;
1306
1307
0
  x = colToDbl(color->c[0]);
1308
0
  func->transform(&x, c);
1309
0
  for (i = 0; i < alt->getNComps(); ++i) {
1310
0
    color2.c[i] = dblToCol(c[i]);
1311
0
  }
1312
0
  alt->getGray(&color2, gray, ri);
1313
0
}
1314
1315
void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
1316
1.38k
             GfxRenderingIntent ri) {
1317
1.38k
  double x;
1318
1.38k
  double c[gfxColorMaxComps];
1319
1.38k
  GfxColor color2;
1320
1.38k
  int i;
1321
1322
1.38k
  x = colToDbl(color->c[0]);
1323
1.38k
  func->transform(&x, c);
1324
5.59k
  for (i = 0; i < alt->getNComps(); ++i) {
1325
4.20k
    color2.c[i] = dblToCol(c[i]);
1326
4.20k
  }
1327
1.38k
  alt->getRGB(&color2, rgb, ri);
1328
1.38k
}
1329
1330
void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
1331
46
              GfxRenderingIntent ri) {
1332
46
  double x;
1333
46
  double c[gfxColorMaxComps];
1334
46
  GfxColor color2;
1335
46
  int i;
1336
1337
46
  x = colToDbl(color->c[0]);
1338
46
  func->transform(&x, c);
1339
184
  for (i = 0; i < alt->getNComps(); ++i) {
1340
138
    color2.c[i] = dblToCol(c[i]);
1341
138
  }
1342
46
  alt->getCMYK(&color2, cmyk, ri);
1343
46
}
1344
1345
1346
1347
712
void GfxSeparationColorSpace::getDefaultColor(GfxColor *color) {
1348
712
  color->c[0] = gfxColorComp1;
1349
712
}
1350
1351
//------------------------------------------------------------------------
1352
// GfxDeviceNColorSpace
1353
//------------------------------------------------------------------------
1354
1355
GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
1356
             GString **namesA,
1357
             GfxColorSpace *altA,
1358
             Function *funcA,
1359
109
             Object *attrsA) {
1360
109
  int i;
1361
1362
109
  nComps = nCompsA;
1363
109
  alt = altA;
1364
109
  func = funcA;
1365
109
  attrsA->copy(&attrs);
1366
109
  nonMarking = gTrue;
1367
109
  overprintMask = 0;
1368
320
  for (i = 0; i < nComps; ++i) {
1369
211
    names[i] = namesA[i];
1370
211
    if (names[i]->cmp("None")) {
1371
211
      nonMarking = gFalse;
1372
211
    }
1373
211
    if (!names[i]->cmp("Cyan")) {
1374
1
      overprintMask |= 0x01;
1375
210
    } else if (!names[i]->cmp("Magenta")) {
1376
1
      overprintMask |= 0x02;
1377
209
    } else if (!names[i]->cmp("Yellow")) {
1378
0
      overprintMask |= 0x04;
1379
209
    } else if (!names[i]->cmp("Black")) {
1380
59
      overprintMask |= 0x08;
1381
150
    } else {
1382
150
      overprintMask = 0x0f;
1383
150
    }
1384
211
  }
1385
109
}
1386
1387
GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
1388
             GString **namesA,
1389
             GfxColorSpace *altA,
1390
             Function *funcA,
1391
             Object *attrsA,
1392
             GBool nonMarkingA,
1393
63
             Guint overprintMaskA) {
1394
63
  int i;
1395
1396
63
  nComps = nCompsA;
1397
63
  alt = altA;
1398
63
  func = funcA;
1399
63
  attrsA->copy(&attrs);
1400
63
  nonMarking = nonMarkingA;
1401
63
  overprintMask = overprintMaskA;
1402
136
  for (i = 0; i < nComps; ++i) {
1403
73
    names[i] = namesA[i]->copy();
1404
73
  }
1405
63
}
1406
1407
166
GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
1408
166
  int i;
1409
1410
432
  for (i = 0; i < nComps; ++i) {
1411
266
    delete names[i];
1412
266
  }
1413
166
  delete alt;
1414
166
  delete func;
1415
166
  attrs.free();
1416
166
}
1417
1418
63
GfxColorSpace *GfxDeviceNColorSpace::copy() {
1419
63
  GfxDeviceNColorSpace *cs;
1420
1421
63
  cs = new GfxDeviceNColorSpace(nComps, names, alt->copy(), func->copy(),
1422
63
        &attrs, nonMarking, overprintMask);
1423
63
  return cs;
1424
63
}
1425
1426
GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr,
1427
1.64k
             int recursion) {
1428
1.64k
  GfxDeviceNColorSpace *cs;
1429
1.64k
  int nCompsA;
1430
1.64k
  GString *namesA[gfxColorMaxComps];
1431
1.64k
  GfxColorSpace *altA;
1432
1.64k
  Function *funcA;
1433
1.64k
  Object attrsA, obj1, obj2;
1434
1.64k
  int i;
1435
1436
1.64k
  if (arr->getLength() != 4 && arr->getLength() != 5) {
1437
88
    error(errSyntaxError, -1, "Bad DeviceN color space");
1438
88
    goto err1;
1439
88
  }
1440
1.55k
  if (!arr->get(1, &obj1)->isArray()) {
1441
53
    error(errSyntaxError, -1, "Bad DeviceN color space (names)");
1442
53
    goto err2;
1443
53
  }
1444
1.50k
  nCompsA = obj1.arrayGetLength();
1445
1.50k
  if (nCompsA > gfxColorMaxComps) {
1446
20
    error(errSyntaxError, -1,
1447
20
    "DeviceN color space with too many ({0:d} > {1:d}) components",
1448
20
    nCompsA, gfxColorMaxComps);
1449
20
    nCompsA = gfxColorMaxComps;
1450
20
  }
1451
6.46k
  for (i = 0; i < nCompsA; ++i) {
1452
5.03k
    if (!obj1.arrayGet(i, &obj2)->isName()) {
1453
74
      error(errSyntaxError, -1, "Bad DeviceN color space (names)");
1454
74
      obj2.free();
1455
74
      goto err2;
1456
74
    }
1457
4.96k
    namesA[i] = new GString(obj2.getName());
1458
4.96k
    obj2.free();
1459
4.96k
  }
1460
1.43k
  obj1.free();
1461
1.43k
  arr->get(2, &obj1);
1462
  // some PDF generators use an ICC profile stream here; Adobe
1463
  // apparently looks at the /Alternate entry in the stream dictionary
1464
1.43k
  if (obj1.isStream() &&
1465
241
      !obj1.streamGetDict()->lookup("Alternate", &obj2)->isNull()) {
1466
138
    obj1.free();
1467
138
    obj1 = obj2;
1468
138
  }
1469
1.43k
  if (!(altA = GfxColorSpace::parse(&obj1,
1470
1.43k
            recursion + 1))) {
1471
795
    error(errSyntaxError, -1,
1472
795
    "Bad DeviceN color space (alternate color space)");
1473
795
    goto err3;
1474
795
  }
1475
635
  obj1.free();
1476
635
  arr->get(3, &obj1);
1477
635
  if (!(funcA = Function::parse(&obj1, nCompsA, altA->getNComps()))) {
1478
526
    goto err4;
1479
526
  }
1480
109
  obj1.free();
1481
109
  if (arr->getLength() == 5) {
1482
99
    arr->get(4, &attrsA);
1483
99
  } else {
1484
10
    attrsA.initNull();
1485
10
  }
1486
109
  cs = new GfxDeviceNColorSpace(nCompsA, namesA, altA, funcA, &attrsA);
1487
109
  attrsA.free();
1488
109
  return cs;
1489
1490
526
 err4:
1491
526
  delete altA;
1492
1.32k
 err3:
1493
5.98k
  for (i = 0; i < nCompsA; ++i) {
1494
4.66k
    delete namesA[i];
1495
4.66k
  }
1496
1.44k
 err2:
1497
1.44k
  obj1.free();
1498
1.53k
 err1:
1499
1.53k
  return NULL;
1500
1.44k
}
1501
1502
1503
void GfxDeviceNColorSpace::getGray(GfxColor *color, GfxGray *gray,
1504
0
           GfxRenderingIntent ri) {
1505
0
  double x[gfxColorMaxComps], c[gfxColorMaxComps];
1506
0
  GfxColor color2;
1507
0
  int i;
1508
1509
0
  for (i = 0; i < nComps; ++i) {
1510
0
    x[i] = colToDbl(color->c[i]);
1511
0
  }
1512
0
  func->transform(x, c);
1513
0
  for (i = 0; i < alt->getNComps(); ++i) {
1514
0
    color2.c[i] = dblToCol(c[i]);
1515
0
  }
1516
0
  alt->getGray(&color2, gray, ri);
1517
0
}
1518
1519
void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
1520
912
          GfxRenderingIntent ri) {
1521
912
  double x[gfxColorMaxComps], c[gfxColorMaxComps];
1522
912
  GfxColor color2;
1523
912
  int i;
1524
1525
1.95k
  for (i = 0; i < nComps; ++i) {
1526
1.04k
    x[i] = colToDbl(color->c[i]);
1527
1.04k
  }
1528
912
  func->transform(x, c);
1529
4.49k
  for (i = 0; i < alt->getNComps(); ++i) {
1530
3.58k
    color2.c[i] = dblToCol(c[i]);
1531
3.58k
  }
1532
912
  alt->getRGB(&color2, rgb, ri);
1533
912
}
1534
1535
void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
1536
0
           GfxRenderingIntent ri) {
1537
0
  double x[gfxColorMaxComps], c[gfxColorMaxComps];
1538
0
  GfxColor color2;
1539
0
  int i;
1540
1541
0
  for (i = 0; i < nComps; ++i) {
1542
0
    x[i] = colToDbl(color->c[i]);
1543
0
  }
1544
0
  func->transform(x, c);
1545
0
  for (i = 0; i < alt->getNComps(); ++i) {
1546
0
    color2.c[i] = dblToCol(c[i]);
1547
0
  }
1548
0
  alt->getCMYK(&color2, cmyk, ri);
1549
0
}
1550
1551
1552
1553
50
void GfxDeviceNColorSpace::getDefaultColor(GfxColor *color) {
1554
50
  int i;
1555
1556
200
  for (i = 0; i < nComps; ++i) {
1557
150
    color->c[i] = gfxColorComp1;
1558
150
  }
1559
50
}
1560
1561
//------------------------------------------------------------------------
1562
// GfxPatternColorSpace
1563
//------------------------------------------------------------------------
1564
1565
181k
GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) {
1566
181k
  under = underA;
1567
181k
}
1568
1569
181k
GfxPatternColorSpace::~GfxPatternColorSpace() {
1570
181k
  if (under) {
1571
264
    delete under;
1572
264
  }
1573
181k
}
1574
1575
127k
GfxColorSpace *GfxPatternColorSpace::copy() {
1576
127k
  GfxPatternColorSpace *cs;
1577
1578
127k
  cs = new GfxPatternColorSpace(under ? under->copy() :
1579
127k
                (GfxColorSpace *)NULL);
1580
127k
  return cs;
1581
127k
}
1582
1583
GfxColorSpace *GfxPatternColorSpace::parse(Array *arr,
1584
3.55k
             int recursion) {
1585
3.55k
  GfxPatternColorSpace *cs;
1586
3.55k
  GfxColorSpace *underA;
1587
3.55k
  Object obj1;
1588
1589
3.55k
  if (arr->getLength() != 1 && arr->getLength() != 2) {
1590
74
    error(errSyntaxError, -1, "Bad Pattern color space");
1591
74
    return NULL;
1592
74
  }
1593
3.48k
  underA = NULL;
1594
3.48k
  if (arr->getLength() == 2) {
1595
145
    arr->get(1, &obj1);
1596
145
    if (!(underA = GfxColorSpace::parse(&obj1,
1597
145
          recursion + 1))) {
1598
29
      error(errSyntaxError, -1,
1599
29
      "Bad Pattern color space (underlying color space)");
1600
29
      obj1.free();
1601
29
      return NULL;
1602
29
    }
1603
116
    obj1.free();
1604
116
  }
1605
3.45k
  cs = new GfxPatternColorSpace(underA);
1606
3.45k
  return cs;
1607
3.48k
}
1608
1609
1610
void GfxPatternColorSpace::getGray(GfxColor *color, GfxGray *gray,
1611
0
           GfxRenderingIntent ri) {
1612
0
  *gray = 0;
1613
0
}
1614
1615
void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb,
1616
56.3k
          GfxRenderingIntent ri) {
1617
56.3k
  rgb->r = rgb->g = rgb->b = 0;
1618
56.3k
}
1619
1620
void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk,
1621
0
           GfxRenderingIntent ri) {
1622
0
  cmyk->c = cmyk->m = cmyk->y = 0;
1623
0
  cmyk->k = 1;
1624
0
}
1625
1626
1627
1628
53.3k
void GfxPatternColorSpace::getDefaultColor(GfxColor *color) {
1629
  // not used
1630
53.3k
}
1631
1632
//------------------------------------------------------------------------
1633
// Pattern
1634
//------------------------------------------------------------------------
1635
1636
81.5k
GfxPattern::GfxPattern(int typeA) {
1637
81.5k
  type = typeA;
1638
81.5k
}
1639
1640
81.5k
GfxPattern::~GfxPattern() {
1641
81.5k
}
1642
1643
GfxPattern *GfxPattern::parse(Object *objRef, Object *obj
1644
32.9k
            ) {
1645
32.9k
  GfxPattern *pattern;
1646
32.9k
  Object typeObj;
1647
1648
32.9k
  if (obj->isDict()) {
1649
12.2k
    obj->dictLookup("PatternType", &typeObj);
1650
20.6k
  } else if (obj->isStream()) {
1651
20.2k
    obj->streamGetDict()->lookup("PatternType", &typeObj);
1652
20.2k
  } else {
1653
395
    return NULL;
1654
395
  }
1655
32.5k
  pattern = NULL;
1656
32.5k
  if (typeObj.isInt() && typeObj.getInt() == 1) {
1657
22.8k
    pattern = GfxTilingPattern::parse(objRef, obj);
1658
22.8k
  } else if (typeObj.isInt() && typeObj.getInt() == 2) {
1659
9.11k
    pattern = GfxShadingPattern::parse(obj
1660
9.11k
               );
1661
9.11k
  }
1662
32.5k
  typeObj.free();
1663
32.5k
  return pattern;
1664
32.9k
}
1665
1666
//------------------------------------------------------------------------
1667
// GfxTilingPattern
1668
//------------------------------------------------------------------------
1669
1670
22.8k
GfxTilingPattern *GfxTilingPattern::parse(Object *patObjRef, Object *patObj) {
1671
22.8k
  GfxTilingPattern *pat;
1672
22.8k
  Dict *dict;
1673
22.8k
  int paintTypeA, tilingTypeA;
1674
22.8k
  double bboxA[4], matrixA[6];
1675
22.8k
  double xStepA, yStepA;
1676
22.8k
  Object resDictA;
1677
22.8k
  Object obj1, obj2;
1678
22.8k
  int i;
1679
1680
22.8k
  if (!patObj->isStream()) {
1681
2.75k
    return NULL;
1682
2.75k
  }
1683
20.0k
  dict = patObj->streamGetDict();
1684
1685
20.0k
  if (dict->lookup("PaintType", &obj1)->isInt()) {
1686
17.5k
    paintTypeA = obj1.getInt();
1687
17.5k
  } else {
1688
2.54k
    paintTypeA = 1;
1689
2.54k
    error(errSyntaxWarning, -1, "Invalid or missing PaintType in pattern");
1690
2.54k
  }
1691
20.0k
  obj1.free();
1692
20.0k
  if (dict->lookup("TilingType", &obj1)->isInt()) {
1693
18.6k
    tilingTypeA = obj1.getInt();
1694
18.6k
  } else {
1695
1.47k
    tilingTypeA = 1;
1696
1.47k
    error(errSyntaxWarning, -1, "Invalid or missing TilingType in pattern");
1697
1.47k
  }
1698
20.0k
  obj1.free();
1699
20.0k
  bboxA[0] = bboxA[1] = 0;
1700
20.0k
  bboxA[2] = bboxA[3] = 1;
1701
20.0k
  if (dict->lookup("BBox", &obj1)->isArray() &&
1702
4.27k
      obj1.arrayGetLength() == 4) {
1703
20.3k
    for (i = 0; i < 4; ++i) {
1704
16.2k
      if (obj1.arrayGet(i, &obj2)->isNum()) {
1705
12.7k
  bboxA[i] = obj2.getNum();
1706
12.7k
      }
1707
16.2k
      obj2.free();
1708
16.2k
    }
1709
16.0k
  } else {
1710
16.0k
    error(errSyntaxError, -1, "Invalid or missing BBox in pattern");
1711
16.0k
  }
1712
20.0k
  obj1.free();
1713
20.0k
  if (dict->lookup("XStep", &obj1)->isNum()) {
1714
16.5k
    xStepA = obj1.getNum();
1715
16.5k
  } else {
1716
3.53k
    xStepA = 1;
1717
3.53k
    error(errSyntaxError, -1, "Invalid or missing XStep in pattern");
1718
3.53k
  }
1719
20.0k
  obj1.free();
1720
20.0k
  if (dict->lookup("YStep", &obj1)->isNum()) {
1721
16.1k
    yStepA = obj1.getNum();
1722
16.1k
  } else {
1723
3.97k
    yStepA = 1;
1724
3.97k
    error(errSyntaxError, -1, "Invalid or missing YStep in pattern");
1725
3.97k
  }
1726
20.0k
  obj1.free();
1727
20.0k
  if (!dict->lookup("Resources", &resDictA)->isDict()) {
1728
3.75k
    resDictA.free();
1729
3.75k
    resDictA.initNull();
1730
3.75k
    error(errSyntaxError, -1, "Invalid or missing Resources in pattern");
1731
3.75k
  }
1732
20.0k
  matrixA[0] = 1; matrixA[1] = 0;
1733
20.0k
  matrixA[2] = 0; matrixA[3] = 1;
1734
20.0k
  matrixA[4] = 0; matrixA[5] = 0;
1735
20.0k
  if (dict->lookup("Matrix", &obj1)->isArray() &&
1736
18.1k
      obj1.arrayGetLength() == 6) {
1737
123k
    for (i = 0; i < 6; ++i) {
1738
106k
      if (obj1.arrayGet(i, &obj2)->isNum()) {
1739
83.8k
  matrixA[i] = obj2.getNum();
1740
83.8k
      }
1741
106k
      obj2.free();
1742
106k
    }
1743
17.6k
  }
1744
20.0k
  obj1.free();
1745
1746
20.0k
  pat = new GfxTilingPattern(paintTypeA, tilingTypeA, bboxA, xStepA, yStepA,
1747
20.0k
           &resDictA, matrixA, patObjRef);
1748
20.0k
  resDictA.free();
1749
20.0k
  return pat;
1750
22.8k
}
1751
1752
GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA,
1753
           double *bboxA, double xStepA, double yStepA,
1754
           Object *resDictA, double *matrixA,
1755
           Object *contentStreamRefA):
1756
78.8k
  GfxPattern(1)
1757
78.8k
{
1758
78.8k
  int i;
1759
1760
78.8k
  paintType = paintTypeA;
1761
78.8k
  tilingType = tilingTypeA;
1762
394k
  for (i = 0; i < 4; ++i) {
1763
315k
    bbox[i] = bboxA[i];
1764
315k
  }
1765
78.8k
  xStep = xStepA;
1766
78.8k
  yStep = yStepA;
1767
78.8k
  resDictA->copy(&resDict);
1768
552k
  for (i = 0; i < 6; ++i) {
1769
473k
    matrix[i] = matrixA[i];
1770
473k
  }
1771
78.8k
  contentStreamRefA->copy(&contentStreamRef);
1772
78.8k
}
1773
1774
78.8k
GfxTilingPattern::~GfxTilingPattern() {
1775
78.8k
  resDict.free();
1776
78.8k
  contentStreamRef.free();
1777
78.8k
}
1778
1779
58.7k
GfxPattern *GfxTilingPattern::copy() {
1780
58.7k
  return new GfxTilingPattern(paintType, tilingType, bbox, xStep, yStep,
1781
58.7k
            &resDict, matrix, &contentStreamRef);
1782
58.7k
}
1783
1784
2.58k
GBool GfxTilingPattern::usesBlendMode(XRef *xref) {
1785
2.58k
  char *scannedObjs = (char *)gmalloc(xref->getNumObjects());
1786
2.58k
  memset(scannedObjs, 0, xref->getNumObjects());
1787
2.58k
  GBool ret = scanResourcesForBlendMode(&resDict, scannedObjs, xref);
1788
2.58k
  gfree(scannedObjs);
1789
2.58k
  return ret;
1790
2.58k
}
1791
1792
GBool GfxTilingPattern::scanResourcesForBlendMode(Object *resDict2,
1793
              char *scannedObjs,
1794
2.94k
              XRef *xref) {
1795
2.94k
  Object ref1, obj1, obj2;
1796
1797
2.94k
  if (!resDict2->isDict()) {
1798
825
    return gFalse;
1799
825
  }
1800
1801
  //----- ExtGStates
1802
2.12k
  resDict2->dictLookupNF("ExtGState", &ref1);
1803
2.12k
  if (!ref1.isRef() || (ref1.getRefNum() < xref->getNumObjects() &&
1804
2.12k
      !scannedObjs[ref1.getRefNum()])) {
1805
2.12k
    if (ref1.isRef()) {
1806
0
      scannedObjs[ref1.getRefNum()] = 1;
1807
0
      ref1.fetch(xref, &obj1);
1808
2.12k
    } else {
1809
2.12k
      ref1.copy(&obj1);
1810
2.12k
    }
1811
2.12k
    if (obj1.isDict()) {
1812
2.63k
      for (int i = 0; i < obj1.dictGetLength(); ++i) {
1813
1.91k
  if (scanExtGStateForBlendMode(obj1.dictGetValNF(i, &obj2),
1814
1.91k
              scannedObjs, xref)) {
1815
12
    obj2.free();
1816
12
    obj1.free();
1817
12
    ref1.free();
1818
12
    return gTrue;
1819
12
  }
1820
1.89k
  obj2.free();
1821
1.89k
      }
1822
736
    }
1823
2.11k
    obj1.free();
1824
2.11k
  }
1825
2.11k
  ref1.free();
1826
1827
  //----- patterns
1828
2.11k
  resDict2->dictLookupNF("Pattern", &ref1);
1829
2.11k
  if (!ref1.isRef() || (ref1.getRefNum() < xref->getNumObjects() &&
1830
2.11k
      !scannedObjs[ref1.getRefNum()])) {
1831
2.11k
    if (ref1.isRef()) {
1832
0
      scannedObjs[ref1.getRefNum()] = 1;
1833
0
      ref1.fetch(xref, &obj1);
1834
2.11k
    } else {
1835
2.11k
      ref1.copy(&obj1);
1836
2.11k
    }
1837
2.11k
    if (obj1.isDict()) {
1838
1.65k
      for (int i = 0; i < obj1.dictGetLength(); ++i) {
1839
802
  if (scanPatternForBlendMode(obj1.dictGetValNF(i, &obj2),
1840
802
            scannedObjs, xref)) {
1841
0
    obj2.free();
1842
0
    obj1.free();
1843
0
    ref1.free();
1844
0
    return gTrue;
1845
0
  }
1846
802
  obj2.free();
1847
802
      }
1848
848
    }
1849
2.11k
    obj1.free();
1850
2.11k
  }
1851
2.11k
  ref1.free();
1852
1853
  //----- XObjects
1854
2.11k
  resDict2->dictLookupNF("XObject", &ref1);
1855
2.11k
  if (!ref1.isRef() || (ref1.getRefNum() < xref->getNumObjects() &&
1856
2.11k
      !scannedObjs[ref1.getRefNum()])) {
1857
2.11k
    if (ref1.isRef()) {
1858
0
      scannedObjs[ref1.getRefNum()] = 1;
1859
0
      ref1.fetch(xref, &obj1);
1860
2.11k
    } else {
1861
2.11k
      ref1.copy(&obj1);
1862
2.11k
    }
1863
2.11k
    if (obj1.isDict()) {
1864
867
      for (int i = 0; i < obj1.dictGetLength(); ++i) {
1865
434
  if (scanXObjectForBlendMode(obj1.dictGetValNF(i, &obj2),
1866
434
            scannedObjs, xref)) {
1867
0
    obj2.free();
1868
0
    obj1.free();
1869
0
    ref1.free();
1870
0
    return gTrue;
1871
0
  }
1872
434
  obj2.free();
1873
434
      }
1874
433
    }
1875
2.11k
    obj1.free();
1876
2.11k
  }
1877
2.11k
  ref1.free();
1878
1879
2.11k
  return gFalse;
1880
2.11k
}
1881
1882
GBool GfxTilingPattern::scanExtGStateForBlendMode(Object *gsObj,
1883
              char *scannedObjs,
1884
1.91k
              XRef *xref) {
1885
1.91k
  Object gsDict, obj1;
1886
1887
1.91k
  if (gsObj->isRef()) {
1888
1.16k
    if (gsObj->getRefNum() >= xref->getNumObjects() ||
1889
1.14k
  scannedObjs[gsObj->getRefNum()]) {
1890
508
      return gFalse;
1891
508
    }
1892
656
    scannedObjs[gsObj->getRefNum()] = 1;
1893
656
    gsObj->fetch(xref, &gsDict);
1894
747
  } else {
1895
747
    gsObj->copy(&gsDict);
1896
747
  }
1897
1.40k
  if (!gsDict.isDict()) {
1898
992
    gsDict.free();
1899
992
    return gFalse;
1900
992
  }
1901
1902
411
  gsDict.dictLookup("BM", &obj1);
1903
411
  if (obj1.isName() && !obj1.isName("Normal")) {
1904
12
    obj1.free();
1905
12
    gsDict.free();
1906
12
    return gTrue;
1907
12
  }
1908
399
  obj1.free();
1909
1910
399
  if (!gsDict.dictLookupNF("SMask", &obj1)->isNull()) {
1911
141
    if (scanSoftMaskForBlendMode(&obj1, scannedObjs, xref)) {
1912
0
      obj1.free();
1913
0
      gsDict.free();
1914
0
      return gTrue;
1915
0
    }
1916
141
  }
1917
399
  obj1.free();
1918
1919
399
  gsDict.free();
1920
1921
399
  return gFalse;
1922
399
}
1923
1924
GBool GfxTilingPattern::scanSoftMaskForBlendMode(Object *softMaskObj,
1925
             char *scannedObjs,
1926
141
             XRef *xref) {
1927
141
  Object softMaskDict, obj1;
1928
1929
141
  if (softMaskObj->isRef()) {
1930
0
    if (softMaskObj->getRefNum() >= xref->getNumObjects() ||
1931
0
  scannedObjs[softMaskObj->getRefNum()]) {
1932
0
      return gFalse;
1933
0
    }
1934
0
    scannedObjs[softMaskObj->getRefNum()] = 1;
1935
0
    softMaskObj->fetch(xref, &softMaskDict);
1936
141
  } else {
1937
141
    softMaskObj->copy(&softMaskDict);
1938
141
  }
1939
141
  if (!softMaskDict.isDict()) {
1940
12
    softMaskDict.free();
1941
12
    return gFalse;
1942
12
  }
1943
1944
129
  if (!softMaskDict.dictLookupNF("G", &obj1)->isNull()) {
1945
118
    if (scanXObjectForBlendMode(&obj1, scannedObjs, xref)) {
1946
0
      obj1.free();
1947
0
      softMaskDict.free();
1948
0
      return gTrue;
1949
0
    }
1950
118
  }
1951
129
  obj1.free();
1952
1953
129
  softMaskDict.free();
1954
1955
129
  return gFalse;
1956
129
}
1957
1958
GBool GfxTilingPattern::scanPatternForBlendMode(Object *patternObj,
1959
            char *scannedObjs,
1960
802
            XRef *xref) {
1961
802
  Object patternObj2, obj1;
1962
802
  Dict *patternDict;
1963
1964
802
  if (patternObj->isRef()) {
1965
706
    if (patternObj->getRefNum() >= xref->getNumObjects() ||
1966
700
  scannedObjs[patternObj->getRefNum()]) {
1967
250
      return gFalse;
1968
250
    }
1969
456
    scannedObjs[patternObj->getRefNum()] = 1;
1970
456
    patternObj->fetch(xref, &patternObj2);
1971
456
  } else {
1972
96
    patternObj->copy(&patternObj2);
1973
96
  }
1974
552
  if (patternObj2.isDict()) {
1975
218
    patternDict = patternObj2.getDict();
1976
334
  } else if (patternObj2.isStream()) {
1977
238
    patternDict = patternObj2.streamGetDict();
1978
238
  } else {
1979
96
    patternObj2.free();
1980
96
    return gFalse;
1981
96
  }
1982
1983
456
  if (!patternDict->lookupNF("Resources", &obj1)->isNull()) {
1984
237
    if (scanResourcesForBlendMode(&obj1, scannedObjs, xref)) {
1985
0
      obj1.free();
1986
0
      patternObj2.free();
1987
0
      return gTrue;
1988
0
    }
1989
237
  }
1990
456
  obj1.free();
1991
1992
456
  patternObj2.free();
1993
1994
456
  return gFalse;
1995
456
}
1996
1997
GBool GfxTilingPattern::scanXObjectForBlendMode(Object *xObj,
1998
            char *scannedObjs,
1999
552
            XRef *xref) {
2000
552
  Object xObj2, obj1;
2001
552
  Dict *dict;
2002
2003
552
  if (xObj->isRef()) {
2004
521
    if (xObj->getRefNum() >= xref->getNumObjects() ||
2005
327
  scannedObjs[xObj->getRefNum()]) {
2006
327
      return gFalse;
2007
327
    }
2008
194
    scannedObjs[xObj->getRefNum()] = 1;
2009
194
    xObj->fetch(xref, &xObj2);
2010
194
  } else {
2011
31
    xObj->copy(&xObj2);
2012
31
  }
2013
225
  if (xObj2.isDict()) {
2014
12
    dict = xObj2.getDict();
2015
213
  } else if (xObj2.isStream()) {
2016
147
    dict = xObj2.streamGetDict();
2017
147
  } else {
2018
66
    xObj2.free();
2019
66
    return gFalse;
2020
66
  }
2021
2022
159
  if (!dict->lookupNF("Resources", &obj1)->isNull()) {
2023
130
    if (scanResourcesForBlendMode(&obj1, scannedObjs, xref)) {
2024
0
      obj1.free();
2025
0
      xObj2.free();
2026
0
      return gTrue;
2027
0
    }
2028
130
  }
2029
159
  obj1.free();
2030
2031
159
  xObj2.free();
2032
2033
159
  return gFalse;
2034
159
}
2035
2036
//------------------------------------------------------------------------
2037
// GfxShadingPattern
2038
//------------------------------------------------------------------------
2039
2040
GfxShadingPattern *GfxShadingPattern::parse(Object *patObj
2041
9.11k
              ) {
2042
9.11k
  Dict *dict;
2043
9.11k
  GfxShading *shadingA;
2044
9.11k
  double matrixA[6];
2045
9.11k
  Object obj1, obj2;
2046
9.11k
  int i;
2047
2048
9.11k
  if (!patObj->isDict()) {
2049
96
    return NULL;
2050
96
  }
2051
9.02k
  dict = patObj->getDict();
2052
2053
9.02k
  dict->lookup("Shading", &obj1);
2054
9.02k
  shadingA = GfxShading::parse(&obj1
2055
9.02k
             );
2056
9.02k
  obj1.free();
2057
9.02k
  if (!shadingA) {
2058
8.15k
    return NULL;
2059
8.15k
  }
2060
2061
869
  matrixA[0] = 1; matrixA[1] = 0;
2062
869
  matrixA[2] = 0; matrixA[3] = 1;
2063
869
  matrixA[4] = 0; matrixA[5] = 0;
2064
869
  if (dict->lookup("Matrix", &obj1)->isArray() &&
2065
626
      obj1.arrayGetLength() == 6) {
2066
4.13k
    for (i = 0; i < 6; ++i) {
2067
3.54k
      if (obj1.arrayGet(i, &obj2)->isNum()) {
2068
2.75k
  matrixA[i] = obj2.getNum();
2069
2.75k
      }
2070
3.54k
      obj2.free();
2071
3.54k
    }
2072
590
  }
2073
869
  obj1.free();
2074
2075
869
  return new GfxShadingPattern(shadingA, matrixA);
2076
9.02k
}
2077
2078
GfxShadingPattern::GfxShadingPattern(GfxShading *shadingA, double *matrixA):
2079
2.73k
  GfxPattern(2)
2080
2.73k
{
2081
2.73k
  int i;
2082
2083
2.73k
  shading = shadingA;
2084
19.1k
  for (i = 0; i < 6; ++i) {
2085
16.4k
    matrix[i] = matrixA[i];
2086
16.4k
  }
2087
2.73k
}
2088
2089
2.64k
GfxShadingPattern::~GfxShadingPattern() {
2090
2.64k
  delete shading;
2091
2.64k
}
2092
2093
1.86k
GfxPattern *GfxShadingPattern::copy() {
2094
1.86k
  return new GfxShadingPattern(shading->copy(), matrix);
2095
1.86k
}
2096
2097
//------------------------------------------------------------------------
2098
// GfxShading
2099
//------------------------------------------------------------------------
2100
2101
5.90k
GfxShading::GfxShading(int typeA) {
2102
5.90k
  type = typeA;
2103
5.90k
  colorSpace = NULL;
2104
5.90k
}
2105
2106
1.86k
GfxShading::GfxShading(GfxShading *shading) {
2107
1.86k
  int i;
2108
2109
1.86k
  type = shading->type;
2110
1.86k
  colorSpace = shading->colorSpace->copy();
2111
61.5k
  for (i = 0; i < gfxColorMaxComps; ++i) {
2112
59.6k
    background.c[i] = shading->background.c[i];
2113
59.6k
  }
2114
1.86k
  hasBackground = shading->hasBackground;
2115
1.86k
  xMin = shading->xMin;
2116
1.86k
  yMin = shading->yMin;
2117
1.86k
  xMax = shading->xMax;
2118
1.86k
  yMax = shading->yMax;
2119
1.86k
  hasBBox = shading->hasBBox;
2120
1.86k
}
2121
2122
7.67k
GfxShading::~GfxShading() {
2123
7.67k
  if (colorSpace) {
2124
5.75k
    delete colorSpace;
2125
5.75k
  }
2126
7.67k
}
2127
2128
GfxShading *GfxShading::parse(Object *obj
2129
13.4k
            ) {
2130
13.4k
  GfxShading *shading;
2131
13.4k
  Dict *dict;
2132
13.4k
  int typeA;
2133
13.4k
  Object obj1;
2134
2135
13.4k
  if (obj->isDict()) {
2136
5.54k
    dict = obj->getDict();
2137
7.89k
  } else if (obj->isStream()) {
2138
7.60k
    dict = obj->streamGetDict();
2139
7.60k
  } else {
2140
288
    return NULL;
2141
288
  }
2142
2143
13.1k
  if (!dict->lookup("ShadingType", &obj1)->isInt()) {
2144
288
    error(errSyntaxError, -1, "Invalid ShadingType in shading dictionary");
2145
288
    obj1.free();
2146
288
    return NULL;
2147
288
  }
2148
12.8k
  typeA = obj1.getInt();
2149
12.8k
  obj1.free();
2150
2151
12.8k
  switch (typeA) {
2152
1.16k
  case 1:
2153
1.16k
    shading = GfxFunctionShading::parse(dict
2154
1.16k
          );
2155
1.16k
    break;
2156
3.32k
  case 2:
2157
3.32k
    shading = GfxAxialShading::parse(dict
2158
3.32k
             );
2159
3.32k
    break;
2160
159
  case 3:
2161
159
    shading = GfxRadialShading::parse(dict
2162
159
              );
2163
159
    break;
2164
4.49k
  case 4:
2165
4.49k
    if (obj->isStream()) {
2166
4.22k
      shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream()
2167
4.22k
             );
2168
4.22k
    } else {
2169
274
      error(errSyntaxError, -1, "Invalid Type 4 shading object");
2170
274
      goto err1;
2171
274
    }
2172
4.22k
    break;
2173
4.22k
  case 5:
2174
563
    if (obj->isStream()) {
2175
427
      shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream()
2176
427
             );
2177
427
    } else {
2178
136
      error(errSyntaxError, -1, "Invalid Type 5 shading object");
2179
136
      goto err1;
2180
136
    }
2181
427
    break;
2182
2.00k
  case 6:
2183
2.00k
    if (obj->isStream()) {
2184
1.79k
      shading = GfxPatchMeshShading::parse(6, dict, obj->getStream()
2185
1.79k
             );
2186
1.79k
    } else {
2187
207
      error(errSyntaxError, -1, "Invalid Type 6 shading object");
2188
207
      goto err1;
2189
207
    }
2190
1.79k
    break;
2191
1.79k
  case 7:
2192
1.05k
    if (obj->isStream()) {
2193
850
      shading = GfxPatchMeshShading::parse(7, dict, obj->getStream()
2194
850
             );
2195
850
    } else {
2196
203
      error(errSyntaxError, -1, "Invalid Type 7 shading object");
2197
203
      goto err1;
2198
203
    }
2199
850
    break;
2200
850
  default:
2201
89
    error(errSyntaxError, -1, "Unknown shading type {0:d}", typeA);
2202
89
    goto err1;
2203
12.8k
  }
2204
2205
11.9k
  return shading;
2206
2207
909
 err1:
2208
909
  return NULL;
2209
12.8k
}
2210
2211
GBool GfxShading::init(Dict *dict
2212
5.90k
           ) {
2213
5.90k
  Object obj1, obj2;
2214
5.90k
  int i;
2215
2216
5.90k
  dict->lookup("ColorSpace", &obj1);
2217
5.90k
  if (!(colorSpace = GfxColorSpace::parse(&obj1
2218
5.90k
            ))) {
2219
1.92k
    error(errSyntaxError, -1, "Bad color space in shading dictionary");
2220
1.92k
    obj1.free();
2221
1.92k
    return gFalse;
2222
1.92k
  }
2223
3.98k
  obj1.free();
2224
2225
131k
  for (i = 0; i < gfxColorMaxComps; ++i) {
2226
127k
    background.c[i] = 0;
2227
127k
  }
2228
3.98k
  hasBackground = gFalse;
2229
3.98k
  if (dict->lookup("Background", &obj1)->isArray()) {
2230
19
    if (obj1.arrayGetLength() == colorSpace->getNComps()) {
2231
0
      hasBackground = gTrue;
2232
0
      for (i = 0; i < colorSpace->getNComps(); ++i) {
2233
0
  background.c[i] = dblToCol(obj1.arrayGet(i, &obj2)->getNum());
2234
0
  obj2.free();
2235
0
      }
2236
19
    } else {
2237
19
      error(errSyntaxError, -1, "Bad Background in shading dictionary");
2238
19
    }
2239
19
  }
2240
3.98k
  obj1.free();
2241
2242
3.98k
  xMin = yMin = xMax = yMax = 0;
2243
3.98k
  hasBBox = gFalse;
2244
3.98k
  if (dict->lookup("BBox", &obj1)->isArray()) {
2245
19
    if (obj1.arrayGetLength() == 4) {
2246
11
      hasBBox = gTrue;
2247
11
      xMin = obj1.arrayGet(0, &obj2)->getNum();
2248
11
      obj2.free();
2249
11
      yMin = obj1.arrayGet(1, &obj2)->getNum();
2250
11
      obj2.free();
2251
11
      xMax = obj1.arrayGet(2, &obj2)->getNum();
2252
11
      obj2.free();
2253
11
      yMax = obj1.arrayGet(3, &obj2)->getNum();
2254
11
      obj2.free();
2255
11
    } else {
2256
8
      error(errSyntaxError, -1, "Bad BBox in shading dictionary");
2257
8
    }
2258
19
  }
2259
3.98k
  obj1.free();
2260
2261
3.98k
  return gTrue;
2262
5.90k
}
2263
2264
//------------------------------------------------------------------------
2265
// GfxFunctionShading
2266
//------------------------------------------------------------------------
2267
2268
GfxFunctionShading::GfxFunctionShading(double x0A, double y0A,
2269
               double x1A, double y1A,
2270
               double *matrixA,
2271
               Function **funcsA, int nFuncsA):
2272
0
  GfxShading(1)
2273
0
{
2274
0
  int i;
2275
2276
0
  x0 = x0A;
2277
0
  y0 = y0A;
2278
0
  x1 = x1A;
2279
0
  y1 = y1A;
2280
0
  for (i = 0; i < 6; ++i) {
2281
0
    matrix[i] = matrixA[i];
2282
0
  }
2283
0
  nFuncs = nFuncsA;
2284
0
  for (i = 0; i < nFuncs; ++i) {
2285
0
    funcs[i] = funcsA[i];
2286
0
  }
2287
0
}
2288
2289
GfxFunctionShading::GfxFunctionShading(GfxFunctionShading *shading):
2290
0
  GfxShading(shading)
2291
0
{
2292
0
  int i;
2293
2294
0
  x0 = shading->x0;
2295
0
  y0 = shading->y0;
2296
0
  x1 = shading->x1;
2297
0
  y1 = shading->y1;
2298
0
  for (i = 0; i < 6; ++i) {
2299
0
    matrix[i] = shading->matrix[i];
2300
0
  }
2301
0
  nFuncs = shading->nFuncs;
2302
0
  for (i = 0; i < nFuncs; ++i) {
2303
0
    funcs[i] = shading->funcs[i]->copy();
2304
0
  }
2305
0
}
2306
2307
0
GfxFunctionShading::~GfxFunctionShading() {
2308
0
  int i;
2309
2310
0
  for (i = 0; i < nFuncs; ++i) {
2311
0
    delete funcs[i];
2312
0
  }
2313
0
}
2314
2315
GfxFunctionShading *GfxFunctionShading::parse(Dict *dict
2316
1.16k
                ) {
2317
1.16k
  GfxFunctionShading *shading;
2318
1.16k
  double x0A, y0A, x1A, y1A;
2319
1.16k
  double matrixA[6];
2320
1.16k
  Function *funcsA[gfxColorMaxComps];
2321
1.16k
  int nFuncsA;
2322
1.16k
  Object obj1, obj2;
2323
1.16k
  GBool ok;
2324
1.16k
  int i;
2325
2326
1.16k
  x0A = y0A = 0;
2327
1.16k
  x1A = y1A = 1;
2328
1.16k
  if (dict->lookup("Domain", &obj1)->isArray() &&
2329
48
      obj1.arrayGetLength() == 4) {
2330
31
    x0A = obj1.arrayGet(0, &obj2)->getNum();
2331
31
    obj2.free();
2332
31
    x1A = obj1.arrayGet(1, &obj2)->getNum();
2333
31
    obj2.free();
2334
31
    y0A = obj1.arrayGet(2, &obj2)->getNum();
2335
31
    obj2.free();
2336
31
    y1A = obj1.arrayGet(3, &obj2)->getNum();
2337
31
    obj2.free();
2338
31
  }
2339
1.16k
  obj1.free();
2340
2341
1.16k
  matrixA[0] = 1; matrixA[1] = 0;
2342
1.16k
  matrixA[2] = 0; matrixA[3] = 1;
2343
1.16k
  matrixA[4] = 0; matrixA[5] = 0;
2344
1.16k
  if (dict->lookup("Matrix", &obj1)->isArray() &&
2345
797
      obj1.arrayGetLength() == 6) {
2346
659
    matrixA[0] = obj1.arrayGet(0, &obj2)->getNum();
2347
659
    obj2.free();
2348
659
    matrixA[1] = obj1.arrayGet(1, &obj2)->getNum();
2349
659
    obj2.free();
2350
659
    matrixA[2] = obj1.arrayGet(2, &obj2)->getNum();
2351
659
    obj2.free();
2352
659
    matrixA[3] = obj1.arrayGet(3, &obj2)->getNum();
2353
659
    obj2.free();
2354
659
    matrixA[4] = obj1.arrayGet(4, &obj2)->getNum();
2355
659
    obj2.free();
2356
659
    matrixA[5] = obj1.arrayGet(5, &obj2)->getNum();
2357
659
    obj2.free();
2358
659
  }
2359
1.16k
  obj1.free();
2360
2361
1.16k
  dict->lookup("Function", &obj1);
2362
1.16k
  if (obj1.isArray()) {
2363
13
    nFuncsA = obj1.arrayGetLength();
2364
13
    if (nFuncsA > gfxColorMaxComps) {
2365
3
      error(errSyntaxError, -1,
2366
3
      "Invalid Function array in shading dictionary");
2367
3
      goto err1;
2368
3
    }
2369
10
    for (i = 0; i < nFuncsA; ++i) {
2370
10
      obj1.arrayGet(i, &obj2);
2371
10
      if (!(funcsA[i] = Function::parse(&obj2, 2, 1))) {
2372
10
  goto err2;
2373
10
      }
2374
0
      obj2.free();
2375
0
    }
2376
1.15k
  } else {
2377
1.15k
    nFuncsA = 1;
2378
1.15k
    if (!(funcsA[0] = Function::parse(&obj1, 2, -1))) {
2379
1.15k
      goto err1;
2380
1.15k
    }
2381
1.15k
  }
2382
0
  obj1.free();
2383
2384
0
  shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA,
2385
0
           funcsA, nFuncsA);
2386
0
  if (!shading->init(dict
2387
0
         )) {
2388
0
    delete shading;
2389
0
    return NULL;
2390
0
  }
2391
2392
0
  ok = gFalse;
2393
0
  if (shading->nFuncs == 1) {
2394
0
    ok = shading->funcs[0]->getOutputSize()
2395
0
           == shading->getColorSpace()->getNComps();
2396
0
  } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) {
2397
0
    ok = gTrue;
2398
0
    for (i = 0; i < shading->nFuncs; ++i) {
2399
0
      ok = ok && shading->funcs[i]->getOutputSize() == 1;
2400
0
    }
2401
0
  }
2402
0
  if (!ok) {
2403
0
    error(errSyntaxError, -1, "Invalid function in shading dictionary");
2404
0
    delete shading;
2405
0
    return NULL;
2406
0
  }
2407
2408
0
  return shading;
2409
2410
10
 err2:
2411
10
  obj2.free();
2412
1.16k
 err1:
2413
1.16k
  obj1.free();
2414
1.16k
  return NULL;
2415
10
}
2416
2417
0
GfxShading *GfxFunctionShading::copy() {
2418
0
  return new GfxFunctionShading(this);
2419
0
}
2420
2421
0
void GfxFunctionShading::getColor(double x, double y, GfxColor *color) {
2422
0
  double in[2], out[gfxColorMaxComps];
2423
0
  int i;
2424
2425
  // NB: there can be one function with n outputs or n functions with
2426
  // one output each (where n = number of color components)
2427
0
  for (i = 0; i < gfxColorMaxComps; ++i) {
2428
0
    out[i] = 0;
2429
0
  }
2430
0
  in[0] = x;
2431
0
  in[1] = y;
2432
0
  for (i = 0; i < nFuncs; ++i) {
2433
0
    funcs[i]->transform(in, &out[i]);
2434
0
  }
2435
0
  for (i = 0; i < gfxColorMaxComps; ++i) {
2436
0
    color->c[i] = dblToCol(out[i]);
2437
0
  }
2438
0
}
2439
2440
//------------------------------------------------------------------------
2441
// GfxAxialShading
2442
//------------------------------------------------------------------------
2443
2444
GfxAxialShading::GfxAxialShading(double x0A, double y0A,
2445
         double x1A, double y1A,
2446
         double t0A, double t1A,
2447
         Function **funcsA, int nFuncsA,
2448
         GBool extend0A, GBool extend1A):
2449
2.03k
  GfxShading(2)
2450
2.03k
{
2451
2.03k
  int i;
2452
2453
2.03k
  x0 = x0A;
2454
2.03k
  y0 = y0A;
2455
2.03k
  x1 = x1A;
2456
2.03k
  y1 = y1A;
2457
2.03k
  t0 = t0A;
2458
2.03k
  t1 = t1A;
2459
2.03k
  nFuncs = nFuncsA;
2460
4.06k
  for (i = 0; i < nFuncs; ++i) {
2461
2.03k
    funcs[i] = funcsA[i];
2462
2.03k
  }
2463
2.03k
  extend0 = extend0A;
2464
2.03k
  extend1 = extend1A;
2465
2.03k
}
2466
2467
GfxAxialShading::GfxAxialShading(GfxAxialShading *shading):
2468
25
  GfxShading(shading)
2469
25
{
2470
25
  int i;
2471
2472
25
  x0 = shading->x0;
2473
25
  y0 = shading->y0;
2474
25
  x1 = shading->x1;
2475
25
  y1 = shading->y1;
2476
25
  t0 = shading->t0;
2477
25
  t1 = shading->t1;
2478
25
  nFuncs = shading->nFuncs;
2479
50
  for (i = 0; i < nFuncs; ++i) {
2480
25
    funcs[i] = shading->funcs[i]->copy();
2481
25
  }
2482
25
  extend0 = shading->extend0;
2483
25
  extend1 = shading->extend1;
2484
25
}
2485
2486
2.04k
GfxAxialShading::~GfxAxialShading() {
2487
2.04k
  int i;
2488
2489
4.09k
  for (i = 0; i < nFuncs; ++i) {
2490
2.04k
    delete funcs[i];
2491
2.04k
  }
2492
2.04k
}
2493
2494
GfxAxialShading *GfxAxialShading::parse(Dict *dict
2495
3.32k
          ) {
2496
3.32k
  GfxAxialShading *shading;
2497
3.32k
  double x0A, y0A, x1A, y1A;
2498
3.32k
  double t0A, t1A;
2499
3.32k
  Function *funcsA[gfxColorMaxComps];
2500
3.32k
  int nFuncsA;
2501
3.32k
  GBool extend0A, extend1A, ok;
2502
3.32k
  Object obj1, obj2;
2503
3.32k
  int i;
2504
2505
3.32k
  x0A = y0A = x1A = y1A = 0;
2506
3.32k
  if (dict->lookup("Coords", &obj1)->isArray() &&
2507
3.19k
      obj1.arrayGetLength() == 4) {
2508
3.11k
    x0A = obj1.arrayGet(0, &obj2)->getNum();
2509
3.11k
    obj2.free();
2510
3.11k
    y0A = obj1.arrayGet(1, &obj2)->getNum();
2511
3.11k
    obj2.free();
2512
3.11k
    x1A = obj1.arrayGet(2, &obj2)->getNum();
2513
3.11k
    obj2.free();
2514
3.11k
    y1A = obj1.arrayGet(3, &obj2)->getNum();
2515
3.11k
    obj2.free();
2516
3.11k
  } else {
2517
211
    error(errSyntaxError, -1,
2518
211
    "Missing or invalid Coords in shading dictionary");
2519
211
    obj1.free();
2520
211
    goto err1;
2521
211
  }
2522
3.11k
  obj1.free();
2523
2524
3.11k
  t0A = 0;
2525
3.11k
  t1A = 1;
2526
3.11k
  if (dict->lookup("Domain", &obj1)->isArray() &&
2527
965
      obj1.arrayGetLength() == 2) {
2528
941
    t0A = obj1.arrayGet(0, &obj2)->getNum();
2529
941
    obj2.free();
2530
941
    t1A = obj1.arrayGet(1, &obj2)->getNum();
2531
941
    obj2.free();
2532
941
  }
2533
3.11k
  obj1.free();
2534
2535
3.11k
  dict->lookup("Function", &obj1);
2536
3.11k
  if (obj1.isArray()) {
2537
18
    nFuncsA = obj1.arrayGetLength();
2538
18
    if (nFuncsA > gfxColorMaxComps) {
2539
6
      error(errSyntaxError, -1,
2540
6
      "Invalid Function array in shading dictionary");
2541
6
      goto err1;
2542
6
    }
2543
12
    for (i = 0; i < nFuncsA; ++i) {
2544
12
      obj1.arrayGet(i, &obj2);
2545
12
      if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) {
2546
12
  obj1.free();
2547
12
  obj2.free();
2548
12
  goto err1;
2549
12
      }
2550
0
      obj2.free();
2551
0
    }
2552
3.09k
  } else {
2553
3.09k
    nFuncsA = 1;
2554
3.09k
    if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) {
2555
1.06k
      obj1.free();
2556
1.06k
      goto err1;
2557
1.06k
    }
2558
3.09k
  }
2559
2.03k
  obj1.free();
2560
2561
2.03k
  extend0A = extend1A = gFalse;
2562
2.03k
  if (dict->lookup("Extend", &obj1)->isArray() &&
2563
1.88k
      obj1.arrayGetLength() == 2) {
2564
1.50k
    extend0A = obj1.arrayGet(0, &obj2)->getBool();
2565
1.50k
    obj2.free();
2566
1.50k
    extend1A = obj1.arrayGet(1, &obj2)->getBool();
2567
1.50k
    obj2.free();
2568
1.50k
  }
2569
2.03k
  obj1.free();
2570
2571
2.03k
  shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
2572
2.03k
        funcsA, nFuncsA, extend0A, extend1A);
2573
2.03k
  if (!shading->init(dict
2574
2.03k
         )) {
2575
287
    delete shading;
2576
287
    return NULL;
2577
287
  }
2578
2579
1.74k
  ok = gFalse;
2580
1.74k
  if (shading->nFuncs == 1) {
2581
1.74k
    ok = shading->funcs[0]->getOutputSize()
2582
1.74k
           == shading->getColorSpace()->getNComps();
2583
1.74k
  } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) {
2584
0
    ok = gTrue;
2585
0
    for (i = 0; i < shading->nFuncs; ++i) {
2586
0
      ok = ok && shading->funcs[i]->getOutputSize() == 1;
2587
0
    }
2588
0
  }
2589
1.74k
  if (!ok) {
2590
48
    error(errSyntaxError, -1, "Invalid function in shading dictionary");
2591
48
    delete shading;
2592
48
    return NULL;
2593
48
  }
2594
2595
1.69k
  return shading;
2596
2597
1.29k
 err1:
2598
1.29k
  return NULL;
2599
1.74k
}
2600
2601
25
GfxShading *GfxAxialShading::copy() {
2602
25
  return new GfxAxialShading(this);
2603
25
}
2604
2605
4.50k
void GfxAxialShading::getColor(double t, GfxColor *color) {
2606
4.50k
  double out[gfxColorMaxComps];
2607
4.50k
  int i;
2608
2609
  // NB: there can be one function with n outputs or n functions with
2610
  // one output each (where n = number of color components)
2611
148k
  for (i = 0; i < gfxColorMaxComps; ++i) {
2612
144k
    out[i] = 0;
2613
144k
  }
2614
9.00k
  for (i = 0; i < nFuncs; ++i) {
2615
4.50k
    funcs[i]->transform(&t, &out[i]);
2616
4.50k
  }
2617
148k
  for (i = 0; i < gfxColorMaxComps; ++i) {
2618
144k
    color->c[i] = dblToCol(out[i]);
2619
144k
  }
2620
4.50k
}
2621
2622
//------------------------------------------------------------------------
2623
// GfxRadialShading
2624
//------------------------------------------------------------------------
2625
2626
GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A,
2627
           double x1A, double y1A, double r1A,
2628
           double t0A, double t1A,
2629
           Function **funcsA, int nFuncsA,
2630
           GBool extend0A, GBool extend1A):
2631
42
  GfxShading(3)
2632
42
{
2633
42
  int i;
2634
2635
42
  x0 = x0A;
2636
42
  y0 = y0A;
2637
42
  r0 = r0A;
2638
42
  x1 = x1A;
2639
42
  y1 = y1A;
2640
42
  r1 = r1A;
2641
42
  t0 = t0A;
2642
42
  t1 = t1A;
2643
42
  nFuncs = nFuncsA;
2644
81
  for (i = 0; i < nFuncs; ++i) {
2645
39
    funcs[i] = funcsA[i];
2646
39
  }
2647
42
  extend0 = extend0A;
2648
42
  extend1 = extend1A;
2649
42
}
2650
2651
GfxRadialShading::GfxRadialShading(GfxRadialShading *shading):
2652
22
  GfxShading(shading)
2653
22
{
2654
22
  int i;
2655
2656
22
  x0 = shading->x0;
2657
22
  y0 = shading->y0;
2658
22
  r0 = shading->r0;
2659
22
  x1 = shading->x1;
2660
22
  y1 = shading->y1;
2661
22
  r1 = shading->r1;
2662
22
  t0 = shading->t0;
2663
22
  t1 = shading->t1;
2664
22
  nFuncs = shading->nFuncs;
2665
44
  for (i = 0; i < nFuncs; ++i) {
2666
22
    funcs[i] = shading->funcs[i]->copy();
2667
22
  }
2668
22
  extend0 = shading->extend0;
2669
22
  extend1 = shading->extend1;
2670
22
}
2671
2672
59
GfxRadialShading::~GfxRadialShading() {
2673
59
  int i;
2674
2675
115
  for (i = 0; i < nFuncs; ++i) {
2676
56
    delete funcs[i];
2677
56
  }
2678
59
}
2679
2680
GfxRadialShading *GfxRadialShading::parse(Dict *dict
2681
159
            ) {
2682
159
  GfxRadialShading *shading;
2683
159
  double x0A, y0A, r0A, x1A, y1A, r1A;
2684
159
  double t0A, t1A;
2685
159
  Function *funcsA[gfxColorMaxComps];
2686
159
  int nFuncsA;
2687
159
  GBool extend0A, extend1A, ok;
2688
159
  Object obj1, obj2;
2689
159
  int i;
2690
2691
159
  x0A = y0A = r0A = x1A = y1A = r1A = 0;
2692
159
  if (dict->lookup("Coords", &obj1)->isArray() &&
2693
75
      obj1.arrayGetLength() == 6) {
2694
69
    x0A = obj1.arrayGet(0, &obj2)->getNum();
2695
69
    obj2.free();
2696
69
    y0A = obj1.arrayGet(1, &obj2)->getNum();
2697
69
    obj2.free();
2698
69
    r0A = obj1.arrayGet(2, &obj2)->getNum();
2699
69
    obj2.free();
2700
69
    x1A = obj1.arrayGet(3, &obj2)->getNum();
2701
69
    obj2.free();
2702
69
    y1A = obj1.arrayGet(4, &obj2)->getNum();
2703
69
    obj2.free();
2704
69
    r1A = obj1.arrayGet(5, &obj2)->getNum();
2705
69
    obj2.free();
2706
90
  } else {
2707
90
    error(errSyntaxError, -1,
2708
90
    "Missing or invalid Coords in shading dictionary");
2709
90
    goto err1;
2710
90
  }
2711
69
  obj1.free();
2712
2713
69
  t0A = 0;
2714
69
  t1A = 1;
2715
69
  if (dict->lookup("Domain", &obj1)->isArray() &&
2716
46
      obj1.arrayGetLength() == 2) {
2717
41
    t0A = obj1.arrayGet(0, &obj2)->getNum();
2718
41
    obj2.free();
2719
41
    t1A = obj1.arrayGet(1, &obj2)->getNum();
2720
41
    obj2.free();
2721
41
  }
2722
69
  obj1.free();
2723
2724
69
  dict->lookup("Function", &obj1);
2725
69
  if (obj1.isArray()) {
2726
8
    nFuncsA = obj1.arrayGetLength();
2727
8
    if (nFuncsA > gfxColorMaxComps) {
2728
1
      error(errSyntaxError, -1,
2729
1
      "Invalid Function array in shading dictionary");
2730
1
      goto err1;
2731
1
    }
2732
7
    for (i = 0; i < nFuncsA; ++i) {
2733
4
      obj1.arrayGet(i, &obj2);
2734
4
      if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) {
2735
4
  obj1.free();
2736
4
  obj2.free();
2737
4
  goto err1;
2738
4
      }
2739
0
      obj2.free();
2740
0
    }
2741
61
  } else {
2742
61
    nFuncsA = 1;
2743
61
    if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) {
2744
22
      obj1.free();
2745
22
      goto err1;
2746
22
    }
2747
61
  }
2748
42
  obj1.free();
2749
2750
42
  extend0A = extend1A = gFalse;
2751
42
  if (dict->lookup("Extend", &obj1)->isArray() &&
2752
27
      obj1.arrayGetLength() == 2) {
2753
12
    extend0A = obj1.arrayGet(0, &obj2)->getBool();
2754
12
    obj2.free();
2755
12
    extend1A = obj1.arrayGet(1, &obj2)->getBool();
2756
12
    obj2.free();
2757
12
  }
2758
42
  obj1.free();
2759
2760
42
  shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
2761
42
         funcsA, nFuncsA, extend0A, extend1A);
2762
42
  if (!shading->init(dict
2763
42
         )) {
2764
10
    delete shading;
2765
10
    return NULL;
2766
10
  }
2767
2768
32
  ok = gFalse;
2769
32
  if (shading->nFuncs == 1) {
2770
32
    ok = shading->funcs[0]->getOutputSize()
2771
32
           == shading->getColorSpace()->getNComps();
2772
32
  } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) {
2773
0
    ok = gTrue;
2774
0
    for (i = 0; i < shading->nFuncs; ++i) {
2775
0
      ok = ok && shading->funcs[i]->getOutputSize() == 1;
2776
0
    }
2777
0
  }
2778
32
  if (!ok) {
2779
3
    error(errSyntaxError, -1, "Invalid function in shading dictionary");
2780
3
    delete shading;
2781
3
    return NULL;
2782
3
  }
2783
2784
29
  return shading;
2785
2786
117
 err1:
2787
117
  return NULL;
2788
32
}
2789
2790
22
GfxShading *GfxRadialShading::copy() {
2791
22
  return new GfxRadialShading(this);
2792
22
}
2793
2794
192
void GfxRadialShading::getColor(double t, GfxColor *color) {
2795
192
  double out[gfxColorMaxComps];
2796
192
  int i;
2797
2798
  // NB: there can be one function with n outputs or n functions with
2799
  // one output each (where n = number of color components)
2800
6.33k
  for (i = 0; i < gfxColorMaxComps; ++i) {
2801
6.14k
    out[i] = 0;
2802
6.14k
  }
2803
384
  for (i = 0; i < nFuncs; ++i) {
2804
192
    funcs[i]->transform(&t, &out[i]);
2805
192
  }
2806
6.33k
  for (i = 0; i < gfxColorMaxComps; ++i) {
2807
6.14k
    color->c[i] = dblToCol(out[i]);
2808
6.14k
  }
2809
192
}
2810
2811
//------------------------------------------------------------------------
2812
// GfxShadingBitBuf
2813
//------------------------------------------------------------------------
2814
2815
class GfxShadingBitBuf {
2816
public:
2817
2818
  GfxShadingBitBuf(Stream *strA);
2819
  ~GfxShadingBitBuf();
2820
  GBool getBits(int n, Guint *val);
2821
  void flushBits();
2822
2823
private:
2824
2825
  Stream *str;
2826
  int bitBuf;
2827
  int nBits;
2828
};
2829
2830
3.93k
GfxShadingBitBuf::GfxShadingBitBuf(Stream *strA) {
2831
3.93k
  str = strA;
2832
3.93k
  str->reset();
2833
3.93k
  bitBuf = 0;
2834
3.93k
  nBits = 0;
2835
3.93k
}
2836
2837
3.93k
GfxShadingBitBuf::~GfxShadingBitBuf() {
2838
3.93k
  str->close();
2839
3.93k
}
2840
2841
4.62M
GBool GfxShadingBitBuf::getBits(int n, Guint *val) {
2842
4.62M
  int x;
2843
2844
4.62M
  if (nBits >= n) {
2845
328k
    x = (bitBuf >> (nBits - n)) & ((1 << n) - 1);
2846
328k
    nBits -= n;
2847
4.29M
  } else {
2848
4.29M
    x = 0;
2849
4.29M
    if (nBits > 0) {
2850
243k
      x = bitBuf & ((1 << nBits) - 1);
2851
243k
      n -= nBits;
2852
243k
      nBits = 0;
2853
243k
    }
2854
13.9M
    while (n > 0) {
2855
9.69M
      if ((bitBuf = str->getChar()) == EOF) {
2856
3.85k
  nBits = 0;
2857
3.85k
  return gFalse;
2858
3.85k
      }
2859
9.68M
      if (n >= 8) {
2860
9.30M
  x = (x << 8) | bitBuf;
2861
9.30M
  n -= 8;
2862
9.30M
      } else {
2863
380k
  x = (x << n) | (bitBuf >> (8 - n));
2864
380k
  nBits = 8 - n;
2865
380k
  n = 0;
2866
380k
      }
2867
9.68M
    }
2868
4.29M
  }
2869
4.62M
  *val = x;
2870
4.62M
  return gTrue;
2871
4.62M
}
2872
2873
755k
void GfxShadingBitBuf::flushBits() {
2874
755k
  bitBuf = 0;
2875
755k
  nBits = 0;
2876
755k
}
2877
2878
//------------------------------------------------------------------------
2879
// GfxGouraudTriangleShading
2880
//------------------------------------------------------------------------
2881
2882
GfxGouraudTriangleShading::GfxGouraudTriangleShading(
2883
             int typeA,
2884
             GfxGouraudVertex *verticesA, int nVerticesA,
2885
             int (*trianglesA)[3], int nTrianglesA,
2886
             int nCompsA, Function **funcsA, int nFuncsA):
2887
2.51k
  GfxShading(typeA)
2888
2.51k
{
2889
2.51k
  int i;
2890
2891
2.51k
  vertices = verticesA;
2892
2.51k
  nVertices = nVerticesA;
2893
2.51k
  triangles = trianglesA;
2894
2.51k
  nTriangles = nTrianglesA;
2895
2.51k
  nComps = nCompsA;
2896
2.51k
  nFuncs = nFuncsA;
2897
2.89k
  for (i = 0; i < nFuncs; ++i) {
2898
377
    funcs[i] = funcsA[i];
2899
377
  }
2900
2.51k
}
2901
2902
GfxGouraudTriangleShading::GfxGouraudTriangleShading(
2903
             GfxGouraudTriangleShading *shading):
2904
673
  GfxShading(shading)
2905
673
{
2906
673
  int i;
2907
2908
673
  nVertices = shading->nVertices;
2909
673
  vertices = (GfxGouraudVertex *)gmallocn(nVertices, sizeof(GfxGouraudVertex));
2910
673
  memcpy(vertices, shading->vertices, nVertices * sizeof(GfxGouraudVertex));
2911
673
  nTriangles = shading->nTriangles;
2912
673
  triangles = (int (*)[3])gmallocn(nTriangles * 3, sizeof(int));
2913
673
  memcpy(triangles, shading->triangles, nTriangles * 3 * sizeof(int));
2914
673
  nComps = shading->nComps;
2915
673
  nFuncs = shading->nFuncs;
2916
998
  for (i = 0; i < nFuncs; ++i) {
2917
325
    funcs[i] = shading->funcs[i]->copy();
2918
325
  }
2919
673
}
2920
2921
3.10k
GfxGouraudTriangleShading::~GfxGouraudTriangleShading() {
2922
3.10k
  int i;
2923
2924
3.10k
  gfree(vertices);
2925
3.10k
  gfree(triangles);
2926
3.73k
  for (i = 0; i < nFuncs; ++i) {
2927
630
    delete funcs[i];
2928
630
  }
2929
3.10k
}
2930
2931
GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(
2932
             int typeA, Dict *dict, Stream *str
2933
4.65k
             ) {
2934
4.65k
  GfxGouraudTriangleShading *shading;
2935
4.65k
  Function *funcsA[gfxColorMaxComps];
2936
4.65k
  int nFuncsA;
2937
4.65k
  int coordBits, compBits, flagBits, vertsPerRow, nRows;
2938
4.65k
  double xMin, xMax, yMin, yMax;
2939
4.65k
  double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps];
2940
4.65k
  double xMul, yMul;
2941
4.65k
  double cMul[gfxColorMaxComps];
2942
4.65k
  GfxGouraudVertex *verticesA;
2943
4.65k
  int (*trianglesA)[3];
2944
4.65k
  int nCompsA, nVerticesA, nTrianglesA, vertSize, triSize;
2945
4.65k
  Guint x, y, flag;
2946
4.65k
  Guint c[gfxColorMaxComps];
2947
4.65k
  GfxShadingBitBuf *bitBuf;
2948
4.65k
  Object obj1, obj2;
2949
4.65k
  GBool ok;
2950
4.65k
  int i, j, k, state;
2951
2952
4.65k
  if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) {
2953
4.38k
    coordBits = obj1.getInt();
2954
4.38k
  } else {
2955
269
    error(errSyntaxError, -1,
2956
269
    "Missing or invalid BitsPerCoordinate in shading dictionary");
2957
269
    goto err2;
2958
269
  }
2959
4.38k
  if (coordBits <= 0 || coordBits > 32) {
2960
280
    error(errSyntaxError, -1,
2961
280
    "Invalid BitsPerCoordinate in shading dictionary");
2962
280
    goto err2;
2963
280
  }
2964
4.10k
  obj1.free();
2965
4.10k
  if (dict->lookup("BitsPerComponent", &obj1)->isInt()) {
2966
3.85k
    compBits = obj1.getInt();
2967
3.85k
  } else {
2968
247
    error(errSyntaxError, -1,
2969
247
    "Missing or invalid BitsPerComponent in shading dictionary");
2970
247
    goto err2;
2971
247
  }
2972
3.85k
  if (compBits <= 0 || compBits > 16) {
2973
37
    error(errSyntaxError, -1,
2974
37
    "Invalid BitsPerComponent in shading dictionary");
2975
37
    goto err2;
2976
37
  }
2977
3.81k
  obj1.free();
2978
3.81k
  flagBits = vertsPerRow = 0; // make gcc happy
2979
3.81k
  if (typeA == 4) {
2980
3.39k
    if (dict->lookup("BitsPerFlag", &obj1)->isInt()) {
2981
3.12k
      flagBits = obj1.getInt();
2982
3.12k
    } else {
2983
267
      error(errSyntaxError, -1,
2984
267
      "Missing or invalid BitsPerFlag in shading dictionary");
2985
267
      goto err2;
2986
267
    }
2987
3.12k
    if (flagBits < 2 || flagBits > 8) {
2988
120
      error(errSyntaxError, -1, "Invalid BitsPerFlag in shading dictionary");
2989
120
      goto err2;
2990
120
    }
2991
3.00k
    obj1.free();
2992
3.00k
  } else {
2993
422
    if (dict->lookup("VerticesPerRow", &obj1)->isInt()) {
2994
351
      vertsPerRow = obj1.getInt();
2995
351
    } else {
2996
71
      error(errSyntaxError, -1,
2997
71
      "Missing or invalid VerticesPerRow in shading dictionary");
2998
71
      goto err2;
2999
71
    }
3000
351
    obj1.free();
3001
351
    if (vertsPerRow < 2) {
3002
20
      error(errSyntaxError, -1,
3003
20
      "Invalid VerticesPerRow in shading dictionary");
3004
20
      goto err2;
3005
20
    }
3006
351
  }
3007
3.34k
  if (dict->lookup("Decode", &obj1)->isArray() &&
3008
3.13k
      obj1.arrayGetLength() >= 6) {
3009
2.89k
    xMin = obj1.arrayGet(0, &obj2)->getNum();
3010
2.89k
    obj2.free();
3011
2.89k
    xMax = obj1.arrayGet(1, &obj2)->getNum();
3012
2.89k
    obj2.free();
3013
2.89k
    xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1);
3014
2.89k
    yMin = obj1.arrayGet(2, &obj2)->getNum();
3015
2.89k
    obj2.free();
3016
2.89k
    yMax = obj1.arrayGet(3, &obj2)->getNum();
3017
2.89k
    obj2.free();
3018
2.89k
    yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1);
3019
8.59k
    for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) {
3020
5.70k
      cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum();
3021
5.70k
      obj2.free();
3022
5.70k
      cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum();
3023
5.70k
      obj2.free();
3024
5.70k
      cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1);
3025
5.70k
    }
3026
2.89k
    nCompsA = i;
3027
2.89k
  } else {
3028
443
    error(errSyntaxError, -1,
3029
443
    "Missing or invalid Decode array in shading dictionary");
3030
443
    goto err2;
3031
443
  }
3032
2.89k
  obj1.free();
3033
3034
2.89k
  if (!dict->lookup("Function", &obj1)->isNull()) {
3035
753
    if (obj1.isArray()) {
3036
214
      nFuncsA = obj1.arrayGetLength();
3037
214
      if (nFuncsA > gfxColorMaxComps) {
3038
88
  error(errSyntaxError, -1,
3039
88
        "Invalid Function array in shading dictionary");
3040
88
  goto err1;
3041
88
      }
3042
126
      for (i = 0; i < nFuncsA; ++i) {
3043
126
  obj1.arrayGet(i, &obj2);
3044
126
  if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) {
3045
126
    obj1.free();
3046
126
    obj2.free();
3047
126
    goto err1;
3048
126
  }
3049
0
  obj2.free();
3050
0
      }
3051
539
    } else {
3052
539
      nFuncsA = 1;
3053
539
      if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) {
3054
148
  obj1.free();
3055
148
  goto err1;
3056
148
      }
3057
539
    }
3058
2.14k
  } else {
3059
2.14k
    nFuncsA = 0;
3060
2.14k
  }
3061
2.53k
  obj1.free();
3062
3063
2.53k
  nVerticesA = nTrianglesA = 0;
3064
2.53k
  verticesA = NULL;
3065
2.53k
  trianglesA = NULL;
3066
2.53k
  vertSize = triSize = 0;
3067
2.53k
  state = 0;
3068
2.53k
  flag = 0; // make gcc happy
3069
2.53k
  bitBuf = new GfxShadingBitBuf(str);
3070
733k
  while (1) {
3071
733k
    if (typeA == 4) {
3072
316k
      if (!bitBuf->getBits(flagBits, &flag)) {
3073
307
  break;
3074
307
      }
3075
316k
    }
3076
733k
    if (!bitBuf->getBits(coordBits, &x) ||
3077
732k
  !bitBuf->getBits(coordBits, &y)) {
3078
1.22k
      break;
3079
1.22k
    }
3080
2.72M
    for (i = 0; i < nCompsA; ++i) {
3081
1.99M
      if (!bitBuf->getBits(compBits, &c[i])) {
3082
1.00k
  break;
3083
1.00k
      }
3084
1.99M
    }
3085
732k
    if (i < nCompsA) {
3086
1.00k
      break;
3087
1.00k
    }
3088
731k
    if (nVerticesA == vertSize) {
3089
9.12k
      vertSize = (vertSize == 0) ? 16 : 2 * vertSize;
3090
9.12k
      verticesA = (GfxGouraudVertex *)
3091
9.12k
                greallocn(verticesA, vertSize, sizeof(GfxGouraudVertex));
3092
9.12k
    }
3093
731k
    verticesA[nVerticesA].x = xMin + xMul * (double)x;
3094
731k
    verticesA[nVerticesA].y = yMin + yMul * (double)y;
3095
2.72M
    for (i = 0; i < nCompsA; ++i) {
3096
1.98M
      verticesA[nVerticesA].color[i] = cMin[i] + cMul[i] * (double)c[i];
3097
1.98M
    }
3098
731k
    ++nVerticesA;
3099
731k
    bitBuf->flushBits();
3100
731k
    if (typeA == 4) {
3101
314k
      if (state == 0 || state == 1) {
3102
14.0k
  ++state;
3103
300k
      } else if (state == 2 || flag > 0) {
3104
290k
  if (nTrianglesA == triSize) {
3105
6.55k
    triSize = (triSize == 0) ? 16 : 2 * triSize;
3106
6.55k
    trianglesA = (int (*)[3])
3107
6.55k
                     greallocn(trianglesA, triSize * 3, sizeof(int));
3108
6.55k
  }
3109
290k
  if (state == 2) {
3110
11.5k
    trianglesA[nTrianglesA][0] = nVerticesA - 3;
3111
11.5k
    trianglesA[nTrianglesA][1] = nVerticesA - 2;
3112
11.5k
    trianglesA[nTrianglesA][2] = nVerticesA - 1;
3113
11.5k
    ++state;
3114
279k
  } else if (flag == 1) {
3115
3.84k
    trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][1];
3116
3.84k
    trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2];
3117
3.84k
    trianglesA[nTrianglesA][2] = nVerticesA - 1;
3118
275k
  } else { // flag == 2
3119
275k
    trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][0];
3120
275k
    trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2];
3121
275k
    trianglesA[nTrianglesA][2] = nVerticesA - 1;
3122
275k
  }
3123
290k
  ++nTrianglesA;
3124
290k
      } else { // state == 3 && flag == 0
3125
9.87k
  state = 1;
3126
9.87k
      }
3127
314k
    }
3128
731k
  }
3129
2.53k
  delete bitBuf;
3130
2.53k
  if (typeA == 5) {
3131
283
    nRows = nVerticesA / vertsPerRow;
3132
283
    if (nRows == 0) {
3133
20
      error(errSyntaxError, -1,
3134
20
      "Invalid VerticesPerRow in shading dictionary");
3135
20
      goto err3;
3136
20
    }
3137
263
    nTrianglesA = (nRows - 1) * 2 * (vertsPerRow - 1);
3138
263
    trianglesA = (int (*)[3])gmallocn(nTrianglesA * 3, sizeof(int));
3139
263
    k = 0;
3140
26.1k
    for (i = 0; i < nRows - 1; ++i) {
3141
410k
      for (j = 0; j < vertsPerRow - 1; ++j) {
3142
384k
  trianglesA[k][0] = i * vertsPerRow + j;
3143
384k
  trianglesA[k][1] = i * vertsPerRow + j+1;
3144
384k
  trianglesA[k][2] = (i+1) * vertsPerRow + j;
3145
384k
  ++k;
3146
384k
  trianglesA[k][0] = i * vertsPerRow + j+1;
3147
384k
  trianglesA[k][1] = (i+1) * vertsPerRow + j;
3148
384k
  trianglesA[k][2] = (i+1) * vertsPerRow + j+1;
3149
384k
  ++k;
3150
384k
      }
3151
25.8k
    }
3152
263
  }
3153
3154
2.51k
  shading = new GfxGouraudTriangleShading(typeA, verticesA, nVerticesA,
3155
2.51k
            trianglesA, nTrianglesA,
3156
2.51k
            nCompsA, funcsA, nFuncsA);
3157
2.51k
  if (!shading->init(dict
3158
2.51k
         )) {
3159
1.45k
    delete shading;
3160
1.45k
    return NULL;
3161
1.45k
  }
3162
3163
1.05k
  ok = gFalse;
3164
1.05k
  if (shading->nFuncs == 0) {
3165
683
    ok = shading->nComps == shading->getColorSpace()->getNComps();
3166
683
  } else if (shading->nFuncs == 1) {
3167
374
    ok = shading->funcs[0]->getOutputSize()
3168
374
           == shading->getColorSpace()->getNComps();
3169
374
  } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) {
3170
0
    ok = gTrue;
3171
0
    for (i = 0; i < shading->nFuncs; ++i) {
3172
0
      ok = ok && shading->funcs[i]->getOutputSize() == 1;
3173
0
    }
3174
0
  }
3175
1.05k
  if (!ok) {
3176
224
    error(errSyntaxError, -1, "Invalid function in shading dictionary");
3177
224
    delete shading;
3178
224
    return NULL;
3179
224
  }
3180
3181
833
  return shading;
3182
3183
20
 err3:
3184
20
  gfree(trianglesA);
3185
20
  gfree(verticesA);
3186
34
  for (i = 0; i < nFuncsA; ++i) {
3187
14
    delete funcsA[i];
3188
14
  }
3189
1.77k
 err2:
3190
1.77k
  obj1.free();
3191
2.13k
 err1:
3192
2.13k
  return NULL;
3193
1.77k
}
3194
3195
673
GfxShading *GfxGouraudTriangleShading::copy() {
3196
673
  return new GfxGouraudTriangleShading(this);
3197
673
}
3198
3199
void GfxGouraudTriangleShading::getTriangle(
3200
            int i,
3201
            double *x0, double *y0, double *color0,
3202
            double *x1, double *y1, double *color1,
3203
672k
            double *x2, double *y2, double *color2) {
3204
672k
  int v, j;
3205
3206
672k
  v = triangles[i][0];
3207
672k
  *x0 = vertices[v].x;
3208
672k
  *y0 = vertices[v].y;
3209
2.09M
  for (j = 0; j < nComps; ++j) {
3210
1.42M
    color0[j] = vertices[v].color[j];
3211
1.42M
  }
3212
672k
  v = triangles[i][1];
3213
672k
  *x1 = vertices[v].x;
3214
672k
  *y1 = vertices[v].y;
3215
2.09M
  for (j = 0; j < nComps; ++j) {
3216
1.42M
    color1[j] = vertices[v].color[j];
3217
1.42M
  }
3218
672k
  v = triangles[i][2];
3219
672k
  *x2 = vertices[v].x;
3220
672k
  *y2 = vertices[v].y;
3221
2.09M
  for (j = 0; j < nComps; ++j) {
3222
1.42M
    color2[j] = vertices[v].color[j];
3223
1.42M
  }
3224
672k
}
3225
3226
void GfxGouraudTriangleShading::getBBox(double *xMinA, double *yMinA,
3227
744
          double *xMaxA, double *yMaxA) {
3228
744
  double xxMin = 0;
3229
744
  double yyMin = 0;
3230
744
  double xxMax = 0;
3231
744
  double yyMax = 0;
3232
744
  if (nVertices > 0) {
3233
731
    xxMin = xxMax = vertices[0].x;
3234
731
    yyMin = yyMax = vertices[0].y;
3235
731
  }
3236
618k
  for (int i = 1; i < nVertices; ++i) {
3237
617k
    if (vertices[i].x < xxMin) {
3238
3.46k
      xxMin = vertices[i].x;
3239
614k
    } else if (vertices[i].x > xxMax) {
3240
3.41k
      xxMax = vertices[i].x;
3241
3.41k
    }
3242
617k
    if (vertices[i].y < yyMin) {
3243
1.50k
      yyMin = vertices[i].y;
3244
616k
    } else if (vertices[i].y > yyMax) {
3245
3.30k
      yyMax = vertices[i].y;
3246
3.30k
    }
3247
617k
  }
3248
744
  *xMinA = xxMin;
3249
744
  *yMinA = yyMin;
3250
744
  *xMaxA = xxMax;
3251
744
  *yMaxA = yyMax;
3252
744
}
3253
3254
76.0k
void GfxGouraudTriangleShading::getColor(double *in, GfxColor *out) {
3255
76.0k
  double c[gfxColorMaxComps];
3256
76.0k
  int i;
3257
3258
76.0k
  if (nFuncs > 0) {
3259
73.4k
    for (i = 0; i < nFuncs; ++i) {
3260
36.7k
      funcs[i]->transform(in, &c[i]);
3261
36.7k
    }
3262
146k
    for (i = 0; i < colorSpace->getNComps(); ++i) {
3263
110k
      out->c[i] = dblToCol(c[i]);
3264
110k
    }
3265
39.3k
  } else {
3266
174k
    for (i = 0; i < nComps; ++i) {
3267
134k
      out->c[i] = dblToCol(in[i]);
3268
134k
    }
3269
39.3k
  }
3270
76.0k
}
3271
3272
//------------------------------------------------------------------------
3273
// GfxPatchMeshShading
3274
//------------------------------------------------------------------------
3275
3276
GfxPatchMeshShading::GfxPatchMeshShading(int typeA,
3277
           GfxPatch *patchesA, int nPatchesA,
3278
           int nCompsA,
3279
           Function **funcsA, int nFuncsA):
3280
1.31k
  GfxShading(typeA)
3281
1.31k
{
3282
1.31k
  int i;
3283
3284
1.31k
  patches = patchesA;
3285
1.31k
  nPatches = nPatchesA;
3286
1.31k
  nComps = nCompsA;
3287
1.31k
  nFuncs = nFuncsA;
3288
1.62k
  for (i = 0; i < nFuncs; ++i) {
3289
305
    funcs[i] = funcsA[i];
3290
305
  }
3291
1.31k
}
3292
3293
GfxPatchMeshShading::GfxPatchMeshShading(GfxPatchMeshShading *shading):
3294
1.14k
  GfxShading(shading)
3295
1.14k
{
3296
1.14k
  int i;
3297
3298
1.14k
  nPatches = shading->nPatches;
3299
1.14k
  patches = (GfxPatch *)gmallocn(nPatches, sizeof(GfxPatch));
3300
1.14k
  memcpy(patches, shading->patches, nPatches * sizeof(GfxPatch));
3301
1.14k
  nComps = shading->nComps;
3302
1.14k
  nFuncs = shading->nFuncs;
3303
1.48k
  for (i = 0; i < nFuncs; ++i) {
3304
339
    funcs[i] = shading->funcs[i]->copy();
3305
339
  }
3306
1.14k
}
3307
3308
2.46k
GfxPatchMeshShading::~GfxPatchMeshShading() {
3309
2.46k
  int i;
3310
3311
2.46k
  gfree(patches);
3312
3.10k
  for (i = 0; i < nFuncs; ++i) {
3313
644
    delete funcs[i];
3314
644
  }
3315
2.46k
}
3316
3317
GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
3318
            Stream *str
3319
2.64k
            ) {
3320
2.64k
  GfxPatchMeshShading *shading;
3321
2.64k
  Function *funcsA[gfxColorMaxComps];
3322
2.64k
  int nFuncsA;
3323
2.64k
  int coordBits, compBits, flagBits;
3324
2.64k
  double xMin, xMax, yMin, yMax;
3325
2.64k
  double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps];
3326
2.64k
  double xMul, yMul;
3327
2.64k
  double cMul[gfxColorMaxComps];
3328
2.64k
  GfxPatch *patchesA, *p;
3329
2.64k
  int nCompsA, nPatchesA, patchesSize, nPts, nColors;
3330
2.64k
  Guint flag;
3331
2.64k
  double x[16], y[16];
3332
2.64k
  Guint xi, yi;
3333
2.64k
  double c[4][gfxColorMaxComps];
3334
2.64k
  Guint ci;
3335
2.64k
  GfxShadingBitBuf *bitBuf;
3336
2.64k
  Object obj1, obj2;
3337
2.64k
  GBool ok;
3338
2.64k
  int i, j;
3339
3340
2.64k
  nPatchesA = 0;
3341
2.64k
  patchesA = NULL;
3342
2.64k
  patchesSize = 0;
3343
3344
2.64k
  if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) {
3345
2.43k
    coordBits = obj1.getInt();
3346
2.43k
  } else {
3347
217
    error(errSyntaxError, -1,
3348
217
    "Missing or invalid BitsPerCoordinate in shading dictionary");
3349
217
    goto err2;
3350
217
  }
3351
2.43k
  if (coordBits <= 0 || coordBits > 32) {
3352
71
    error(errSyntaxError, -1,
3353
71
    "Invalid BitsPerCoordinate in shading dictionary");
3354
71
    goto err2;
3355
71
  }
3356
2.36k
  obj1.free();
3357
2.36k
  if (dict->lookup("BitsPerComponent", &obj1)->isInt()) {
3358
2.26k
    compBits = obj1.getInt();
3359
2.26k
  } else {
3360
94
    error(errSyntaxError, -1,
3361
94
    "Missing or invalid BitsPerComponent in shading dictionary");
3362
94
    goto err2;
3363
94
  }
3364
2.26k
  if (compBits <= 0 || compBits > 16) {
3365
77
    error(errSyntaxError, -1,
3366
77
    "Invalid BitsPerComponent in shading dictionary");
3367
77
    goto err2;
3368
77
  }
3369
2.19k
  obj1.free();
3370
2.19k
  if (dict->lookup("BitsPerFlag", &obj1)->isInt()) {
3371
2.11k
    flagBits = obj1.getInt();
3372
2.11k
  } else {
3373
79
    error(errSyntaxError, -1,
3374
79
    "Missing or invalid BitsPerFlag in shading dictionary");
3375
79
    goto err2;
3376
79
  }
3377
2.11k
  if (flagBits < 2 || flagBits > 8) {
3378
43
    error(errSyntaxError, -1, "Invalid BitsPerFlag in shading dictionary");
3379
43
    goto err2;
3380
43
  }
3381
2.06k
  obj1.free();
3382
2.06k
  if (dict->lookup("Decode", &obj1)->isArray() &&
3383
1.99k
      obj1.arrayGetLength() >= 6) {
3384
1.90k
    xMin = obj1.arrayGet(0, &obj2)->getNum();
3385
1.90k
    obj2.free();
3386
1.90k
    xMax = obj1.arrayGet(1, &obj2)->getNum();
3387
1.90k
    obj2.free();
3388
1.90k
    xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1);
3389
1.90k
    yMin = obj1.arrayGet(2, &obj2)->getNum();
3390
1.90k
    obj2.free();
3391
1.90k
    yMax = obj1.arrayGet(3, &obj2)->getNum();
3392
1.90k
    obj2.free();
3393
1.90k
    yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1);
3394
8.05k
    for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) {
3395
6.15k
      cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum();
3396
6.15k
      obj2.free();
3397
6.15k
      cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum();
3398
6.15k
      obj2.free();
3399
6.15k
      cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1);
3400
6.15k
    }
3401
1.90k
    nCompsA = i;
3402
1.90k
  } else {
3403
168
    error(errSyntaxError, -1,
3404
168
    "Missing or invalid Decode array in shading dictionary");
3405
168
    goto err2;
3406
168
  }
3407
1.90k
  obj1.free();
3408
3409
1.90k
  if (!dict->lookup("Function", &obj1)->isNull()) {
3410
835
    if (obj1.isArray()) {
3411
179
      nFuncsA = obj1.arrayGetLength();
3412
179
      if (nFuncsA > gfxColorMaxComps) {
3413
79
  error(errSyntaxError, -1,
3414
79
        "Invalid Function array in shading dictionary");
3415
79
  goto err1;
3416
79
      }
3417
121
      for (i = 0; i < nFuncsA; ++i) {
3418
111
  obj1.arrayGet(i, &obj2);
3419
111
  if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) {
3420
90
    obj1.free();
3421
90
    obj2.free();
3422
90
    goto err1;
3423
90
  }
3424
21
  obj2.free();
3425
21
      }
3426
656
    } else {
3427
656
      nFuncsA = 1;
3428
656
      if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) {
3429
335
  obj1.free();
3430
335
  goto err1;
3431
335
      }
3432
656
    }
3433
1.06k
  } else {
3434
1.06k
    nFuncsA = 0;
3435
1.06k
  }
3436
1.39k
  obj1.free();
3437
3438
1.39k
  bitBuf = new GfxShadingBitBuf(str);
3439
26.1k
  while (1) {
3440
26.1k
    if (!bitBuf->getBits(flagBits, &flag)) {
3441
233
      break;
3442
233
    }
3443
25.8k
    flag &= 3;
3444
25.8k
    if (flag != 0 && nPatchesA == 0) {
3445
78
      error(errSyntaxError, -1, "Invalid patch in patch mesh shading");
3446
78
      delete bitBuf;
3447
78
      goto err1;
3448
78
    }
3449
25.8k
    if (typeA == 6) {
3450
14.0k
      switch (flag) {
3451
7.04k
      case 0: nPts = 12; nColors = 4; break;
3452
2.38k
      case 1:
3453
4.81k
      case 2:
3454
6.98k
      case 3:
3455
6.98k
      default: nPts =  8; nColors = 2; break;
3456
14.0k
      }
3457
14.0k
    } else {
3458
11.7k
      switch (flag) {
3459
4.93k
      case 0: nPts = 16; nColors = 4; break;
3460
2.32k
      case 1:
3461
4.59k
      case 2:
3462
6.84k
      case 3:
3463
6.84k
      default: nPts = 12; nColors = 2; break;
3464
11.7k
      }
3465
11.7k
    }
3466
323k
    for (i = 0; i < nPts; ++i) {
3467
298k
      if (!bitBuf->getBits(coordBits, &xi) ||
3468
298k
    !bitBuf->getBits(coordBits, &yi)) {
3469
848
  break;
3470
848
      }
3471
297k
      x[i] = xMin + xMul * (double)xi;
3472
297k
      y[i] = yMin + yMul * (double)yi;
3473
297k
    }
3474
25.8k
    if (i < nPts) {
3475
848
      break;
3476
848
    }
3477
97.3k
    for (i = 0; i < nColors; ++i) {
3478
302k
      for (j = 0; j < nCompsA; ++j) {
3479
229k
  if (!bitBuf->getBits(compBits, &ci)) {
3480
237
    break;
3481
237
  }
3482
229k
  c[i][j] = cMin[j] + cMul[j] * (double)ci;
3483
229k
      }
3484
72.6k
      if (j < nCompsA) {
3485
237
  break;
3486
237
      }
3487
72.6k
    }
3488
24.9k
    if (i < nColors) {
3489
237
      break;
3490
237
    }
3491
24.7k
    if (nPatchesA == patchesSize) {
3492
2.02k
      patchesSize = (patchesSize == 0) ? 16 : 2 * patchesSize;
3493
2.02k
      patchesA = (GfxPatch *)greallocn(patchesA,
3494
2.02k
               patchesSize, sizeof(GfxPatch));
3495
2.02k
    }
3496
24.7k
    p = &patchesA[nPatchesA];
3497
24.7k
    if (typeA == 6) {
3498
13.4k
      switch (flag) {
3499
6.70k
      case 0:
3500
6.70k
  p->x[0][0] = x[0];
3501
6.70k
  p->y[0][0] = y[0];
3502
6.70k
  p->x[0][1] = x[1];
3503
6.70k
  p->y[0][1] = y[1];
3504
6.70k
  p->x[0][2] = x[2];
3505
6.70k
  p->y[0][2] = y[2];
3506
6.70k
  p->x[0][3] = x[3];
3507
6.70k
  p->y[0][3] = y[3];
3508
6.70k
  p->x[1][3] = x[4];
3509
6.70k
  p->y[1][3] = y[4];
3510
6.70k
  p->x[2][3] = x[5];
3511
6.70k
  p->y[2][3] = y[5];
3512
6.70k
  p->x[3][3] = x[6];
3513
6.70k
  p->y[3][3] = y[6];
3514
6.70k
  p->x[3][2] = x[7];
3515
6.70k
  p->y[3][2] = y[7];
3516
6.70k
  p->x[3][1] = x[8];
3517
6.70k
  p->y[3][1] = y[8];
3518
6.70k
  p->x[3][0] = x[9];
3519
6.70k
  p->y[3][0] = y[9];
3520
6.70k
  p->x[2][0] = x[10];
3521
6.70k
  p->y[2][0] = y[10];
3522
6.70k
  p->x[1][0] = x[11];
3523
6.70k
  p->y[1][0] = y[11];
3524
22.8k
  for (j = 0; j < nCompsA; ++j) {
3525
16.1k
    p->color[0][0][j] = c[0][j];
3526
16.1k
    p->color[0][1][j] = c[1][j];
3527
16.1k
    p->color[1][1][j] = c[2][j];
3528
16.1k
    p->color[1][0][j] = c[3][j];
3529
16.1k
  }
3530
6.70k
  break;
3531
2.11k
      case 1:
3532
2.11k
  p->x[0][0] = patchesA[nPatchesA-1].x[0][3];
3533
2.11k
  p->y[0][0] = patchesA[nPatchesA-1].y[0][3];
3534
2.11k
  p->x[0][1] = patchesA[nPatchesA-1].x[1][3];
3535
2.11k
  p->y[0][1] = patchesA[nPatchesA-1].y[1][3];
3536
2.11k
  p->x[0][2] = patchesA[nPatchesA-1].x[2][3];
3537
2.11k
  p->y[0][2] = patchesA[nPatchesA-1].y[2][3];
3538
2.11k
  p->x[0][3] = patchesA[nPatchesA-1].x[3][3];
3539
2.11k
  p->y[0][3] = patchesA[nPatchesA-1].y[3][3];
3540
2.11k
  p->x[1][3] = x[0];
3541
2.11k
  p->y[1][3] = y[0];
3542
2.11k
  p->x[2][3] = x[1];
3543
2.11k
  p->y[2][3] = y[1];
3544
2.11k
  p->x[3][3] = x[2];
3545
2.11k
  p->y[3][3] = y[2];
3546
2.11k
  p->x[3][2] = x[3];
3547
2.11k
  p->y[3][2] = y[3];
3548
2.11k
  p->x[3][1] = x[4];
3549
2.11k
  p->y[3][1] = y[4];
3550
2.11k
  p->x[3][0] = x[5];
3551
2.11k
  p->y[3][0] = y[5];
3552
2.11k
  p->x[2][0] = x[6];
3553
2.11k
  p->y[2][0] = y[6];
3554
2.11k
  p->x[1][0] = x[7];
3555
2.11k
  p->y[1][0] = y[7];
3556
8.67k
  for (j = 0; j < nCompsA; ++j) {
3557
6.55k
    p->color[0][0][j] = patchesA[nPatchesA-1].color[0][1][j];
3558
6.55k
    p->color[0][1][j] = patchesA[nPatchesA-1].color[1][1][j];
3559
6.55k
    p->color[1][1][j] = c[0][j];
3560
6.55k
    p->color[1][0][j] = c[1][j];
3561
6.55k
  }
3562
2.11k
  break;
3563
2.42k
      case 2:
3564
2.42k
  p->x[0][0] = patchesA[nPatchesA-1].x[3][3];
3565
2.42k
  p->y[0][0] = patchesA[nPatchesA-1].y[3][3];
3566
2.42k
  p->x[0][1] = patchesA[nPatchesA-1].x[3][2];
3567
2.42k
  p->y[0][1] = patchesA[nPatchesA-1].y[3][2];
3568
2.42k
  p->x[0][2] = patchesA[nPatchesA-1].x[3][1];
3569
2.42k
  p->y[0][2] = patchesA[nPatchesA-1].y[3][1];
3570
2.42k
  p->x[0][3] = patchesA[nPatchesA-1].x[3][0];
3571
2.42k
  p->y[0][3] = patchesA[nPatchesA-1].y[3][0];
3572
2.42k
  p->x[1][3] = x[0];
3573
2.42k
  p->y[1][3] = y[0];
3574
2.42k
  p->x[2][3] = x[1];
3575
2.42k
  p->y[2][3] = y[1];
3576
2.42k
  p->x[3][3] = x[2];
3577
2.42k
  p->y[3][3] = y[2];
3578
2.42k
  p->x[3][2] = x[3];
3579
2.42k
  p->y[3][2] = y[3];
3580
2.42k
  p->x[3][1] = x[4];
3581
2.42k
  p->y[3][1] = y[4];
3582
2.42k
  p->x[3][0] = x[5];
3583
2.42k
  p->y[3][0] = y[5];
3584
2.42k
  p->x[2][0] = x[6];
3585
2.42k
  p->y[2][0] = y[6];
3586
2.42k
  p->x[1][0] = x[7];
3587
2.42k
  p->y[1][0] = y[7];
3588
7.83k
  for (j = 0; j < nCompsA; ++j) {
3589
5.41k
    p->color[0][0][j] = patchesA[nPatchesA-1].color[1][1][j];
3590
5.41k
    p->color[0][1][j] = patchesA[nPatchesA-1].color[1][0][j];
3591
5.41k
    p->color[1][1][j] = c[0][j];
3592
5.41k
    p->color[1][0][j] = c[1][j];
3593
5.41k
  }
3594
2.42k
  break;
3595
2.16k
      case 3:
3596
2.16k
  p->x[0][0] = patchesA[nPatchesA-1].x[3][0];
3597
2.16k
  p->y[0][0] = patchesA[nPatchesA-1].y[3][0];
3598
2.16k
  p->x[0][1] = patchesA[nPatchesA-1].x[2][0];
3599
2.16k
  p->y[0][1] = patchesA[nPatchesA-1].y[2][0];
3600
2.16k
  p->x[0][2] = patchesA[nPatchesA-1].x[1][0];
3601
2.16k
  p->y[0][2] = patchesA[nPatchesA-1].y[1][0];
3602
2.16k
  p->x[0][3] = patchesA[nPatchesA-1].x[0][0];
3603
2.16k
  p->y[0][3] = patchesA[nPatchesA-1].y[0][0];
3604
2.16k
  p->x[1][3] = x[0];
3605
2.16k
  p->y[1][3] = y[0];
3606
2.16k
  p->x[2][3] = x[1];
3607
2.16k
  p->y[2][3] = y[1];
3608
2.16k
  p->x[3][3] = x[2];
3609
2.16k
  p->y[3][3] = y[2];
3610
2.16k
  p->x[3][2] = x[3];
3611
2.16k
  p->y[3][2] = y[3];
3612
2.16k
  p->x[3][1] = x[4];
3613
2.16k
  p->y[3][1] = y[4];
3614
2.16k
  p->x[3][0] = x[5];
3615
2.16k
  p->y[3][0] = y[5];
3616
2.16k
  p->x[2][0] = x[6];
3617
2.16k
  p->y[2][0] = y[6];
3618
2.16k
  p->x[1][0] = x[7];
3619
2.16k
  p->y[1][0] = y[7];
3620
8.78k
  for (j = 0; j < nCompsA; ++j) {
3621
6.61k
    p->color[0][0][j] = patchesA[nPatchesA-1].color[1][0][j];
3622
6.61k
    p->color[0][1][j] = patchesA[nPatchesA-1].color[0][0][j];
3623
6.61k
    p->color[1][1][j] = c[0][j];
3624
6.61k
    p->color[1][0][j] = c[1][j];
3625
6.61k
  }
3626
2.16k
  break;
3627
13.4k
      }
3628
13.4k
    } else {
3629
11.3k
      switch (flag) {
3630
4.66k
      case 0:
3631
4.66k
  p->x[0][0] = x[0];
3632
4.66k
  p->y[0][0] = y[0];
3633
4.66k
  p->x[0][1] = x[1];
3634
4.66k
  p->y[0][1] = y[1];
3635
4.66k
  p->x[0][2] = x[2];
3636
4.66k
  p->y[0][2] = y[2];
3637
4.66k
  p->x[0][3] = x[3];
3638
4.66k
  p->y[0][3] = y[3];
3639
4.66k
  p->x[1][3] = x[4];
3640
4.66k
  p->y[1][3] = y[4];
3641
4.66k
  p->x[2][3] = x[5];
3642
4.66k
  p->y[2][3] = y[5];
3643
4.66k
  p->x[3][3] = x[6];
3644
4.66k
  p->y[3][3] = y[6];
3645
4.66k
  p->x[3][2] = x[7];
3646
4.66k
  p->y[3][2] = y[7];
3647
4.66k
  p->x[3][1] = x[8];
3648
4.66k
  p->y[3][1] = y[8];
3649
4.66k
  p->x[3][0] = x[9];
3650
4.66k
  p->y[3][0] = y[9];
3651
4.66k
  p->x[2][0] = x[10];
3652
4.66k
  p->y[2][0] = y[10];
3653
4.66k
  p->x[1][0] = x[11];
3654
4.66k
  p->y[1][0] = y[11];
3655
4.66k
  p->x[1][1] = x[12];
3656
4.66k
  p->y[1][1] = y[12];
3657
4.66k
  p->x[1][2] = x[13];
3658
4.66k
  p->y[1][2] = y[13];
3659
4.66k
  p->x[2][2] = x[14];
3660
4.66k
  p->y[2][2] = y[14];
3661
4.66k
  p->x[2][1] = x[15];
3662
4.66k
  p->y[2][1] = y[15];
3663
22.8k
  for (j = 0; j < nCompsA; ++j) {
3664
18.1k
    p->color[0][0][j] = c[0][j];
3665
18.1k
    p->color[0][1][j] = c[1][j];
3666
18.1k
    p->color[1][1][j] = c[2][j];
3667
18.1k
    p->color[1][0][j] = c[3][j];
3668
18.1k
  }
3669
4.66k
  break;
3670
2.23k
      case 1:
3671
2.23k
  p->x[0][0] = patchesA[nPatchesA-1].x[0][3];
3672
2.23k
  p->y[0][0] = patchesA[nPatchesA-1].y[0][3];
3673
2.23k
  p->x[0][1] = patchesA[nPatchesA-1].x[1][3];
3674
2.23k
  p->y[0][1] = patchesA[nPatchesA-1].y[1][3];
3675
2.23k
  p->x[0][2] = patchesA[nPatchesA-1].x[2][3];
3676
2.23k
  p->y[0][2] = patchesA[nPatchesA-1].y[2][3];
3677
2.23k
  p->x[0][3] = patchesA[nPatchesA-1].x[3][3];
3678
2.23k
  p->y[0][3] = patchesA[nPatchesA-1].y[3][3];
3679
2.23k
  p->x[1][3] = x[0];
3680
2.23k
  p->y[1][3] = y[0];
3681
2.23k
  p->x[2][3] = x[1];
3682
2.23k
  p->y[2][3] = y[1];
3683
2.23k
  p->x[3][3] = x[2];
3684
2.23k
  p->y[3][3] = y[2];
3685
2.23k
  p->x[3][2] = x[3];
3686
2.23k
  p->y[3][2] = y[3];
3687
2.23k
  p->x[3][1] = x[4];
3688
2.23k
  p->y[3][1] = y[4];
3689
2.23k
  p->x[3][0] = x[5];
3690
2.23k
  p->y[3][0] = y[5];
3691
2.23k
  p->x[2][0] = x[6];
3692
2.23k
  p->y[2][0] = y[6];
3693
2.23k
  p->x[1][0] = x[7];
3694
2.23k
  p->y[1][0] = y[7];
3695
2.23k
  p->x[1][1] = x[8];
3696
2.23k
  p->y[1][1] = y[8];
3697
2.23k
  p->x[1][2] = x[9];
3698
2.23k
  p->y[1][2] = y[9];
3699
2.23k
  p->x[2][2] = x[10];
3700
2.23k
  p->y[2][2] = y[10];
3701
2.23k
  p->x[2][1] = x[11];
3702
2.23k
  p->y[2][1] = y[11];
3703
10.9k
  for (j = 0; j < nCompsA; ++j) {
3704
8.68k
    p->color[0][0][j] = patchesA[nPatchesA-1].color[0][1][j];
3705
8.68k
    p->color[0][1][j] = patchesA[nPatchesA-1].color[1][1][j];
3706
8.68k
    p->color[1][1][j] = c[0][j];
3707
8.68k
    p->color[1][0][j] = c[1][j];
3708
8.68k
  }
3709
2.23k
  break;
3710
2.23k
      case 2:
3711
2.23k
  p->x[0][0] = patchesA[nPatchesA-1].x[3][3];
3712
2.23k
  p->y[0][0] = patchesA[nPatchesA-1].y[3][3];
3713
2.23k
  p->x[0][1] = patchesA[nPatchesA-1].x[3][2];
3714
2.23k
  p->y[0][1] = patchesA[nPatchesA-1].y[3][2];
3715
2.23k
  p->x[0][2] = patchesA[nPatchesA-1].x[3][1];
3716
2.23k
  p->y[0][2] = patchesA[nPatchesA-1].y[3][1];
3717
2.23k
  p->x[0][3] = patchesA[nPatchesA-1].x[3][0];
3718
2.23k
  p->y[0][3] = patchesA[nPatchesA-1].y[3][0];
3719
2.23k
  p->x[1][3] = x[0];
3720
2.23k
  p->y[1][3] = y[0];
3721
2.23k
  p->x[2][3] = x[1];
3722
2.23k
  p->y[2][3] = y[1];
3723
2.23k
  p->x[3][3] = x[2];
3724
2.23k
  p->y[3][3] = y[2];
3725
2.23k
  p->x[3][2] = x[3];
3726
2.23k
  p->y[3][2] = y[3];
3727
2.23k
  p->x[3][1] = x[4];
3728
2.23k
  p->y[3][1] = y[4];
3729
2.23k
  p->x[3][0] = x[5];
3730
2.23k
  p->y[3][0] = y[5];
3731
2.23k
  p->x[2][0] = x[6];
3732
2.23k
  p->y[2][0] = y[6];
3733
2.23k
  p->x[1][0] = x[7];
3734
2.23k
  p->y[1][0] = y[7];
3735
2.23k
  p->x[1][1] = x[8];
3736
2.23k
  p->y[1][1] = y[8];
3737
2.23k
  p->x[1][2] = x[9];
3738
2.23k
  p->y[1][2] = y[9];
3739
2.23k
  p->x[2][2] = x[10];
3740
2.23k
  p->y[2][2] = y[10];
3741
2.23k
  p->x[2][1] = x[11];
3742
2.23k
  p->y[2][1] = y[11];
3743
10.9k
  for (j = 0; j < nCompsA; ++j) {
3744
8.68k
    p->color[0][0][j] = patchesA[nPatchesA-1].color[1][1][j];
3745
8.68k
    p->color[0][1][j] = patchesA[nPatchesA-1].color[1][0][j];
3746
8.68k
    p->color[1][1][j] = c[0][j];
3747
8.68k
    p->color[1][0][j] = c[1][j];
3748
8.68k
  }
3749
2.23k
  break;
3750
2.17k
      case 3:
3751
2.17k
  p->x[0][0] = patchesA[nPatchesA-1].x[3][0];
3752
2.17k
  p->y[0][0] = patchesA[nPatchesA-1].y[3][0];
3753
2.17k
  p->x[0][1] = patchesA[nPatchesA-1].x[2][0];
3754
2.17k
  p->y[0][1] = patchesA[nPatchesA-1].y[2][0];
3755
2.17k
  p->x[0][2] = patchesA[nPatchesA-1].x[1][0];
3756
2.17k
  p->y[0][2] = patchesA[nPatchesA-1].y[1][0];
3757
2.17k
  p->x[0][3] = patchesA[nPatchesA-1].x[0][0];
3758
2.17k
  p->y[0][3] = patchesA[nPatchesA-1].y[0][0];
3759
2.17k
  p->x[1][3] = x[0];
3760
2.17k
  p->y[1][3] = y[0];
3761
2.17k
  p->x[2][3] = x[1];
3762
2.17k
  p->y[2][3] = y[1];
3763
2.17k
  p->x[3][3] = x[2];
3764
2.17k
  p->y[3][3] = y[2];
3765
2.17k
  p->x[3][2] = x[3];
3766
2.17k
  p->y[3][2] = y[3];
3767
2.17k
  p->x[3][1] = x[4];
3768
2.17k
  p->y[3][1] = y[4];
3769
2.17k
  p->x[3][0] = x[5];
3770
2.17k
  p->y[3][0] = y[5];
3771
2.17k
  p->x[2][0] = x[6];
3772
2.17k
  p->y[2][0] = y[6];
3773
2.17k
  p->x[1][0] = x[7];
3774
2.17k
  p->y[1][0] = y[7];
3775
2.17k
  p->x[1][1] = x[8];
3776
2.17k
  p->y[1][1] = y[8];
3777
2.17k
  p->x[1][2] = x[9];
3778
2.17k
  p->y[1][2] = y[9];
3779
2.17k
  p->x[2][2] = x[10];
3780
2.17k
  p->y[2][2] = y[10];
3781
2.17k
  p->x[2][1] = x[11];
3782
2.17k
  p->y[2][1] = y[11];
3783
10.5k
  for (j = 0; j < nCompsA; ++j) {
3784
8.42k
    p->color[0][0][j] = patchesA[nPatchesA-1].color[1][0][j];
3785
8.42k
    p->color[0][1][j] = patchesA[nPatchesA-1].color[0][0][j];
3786
8.42k
    p->color[1][1][j] = c[0][j];
3787
8.42k
    p->color[1][0][j] = c[1][j];
3788
8.42k
  }
3789
2.17k
  break;
3790
11.3k
      }
3791
11.3k
    }
3792
24.7k
    ++nPatchesA;
3793
24.7k
    bitBuf->flushBits();
3794
24.7k
  }
3795
1.31k
  delete bitBuf;
3796
3797
1.31k
  if (typeA == 6) {
3798
14.1k
    for (i = 0; i < nPatchesA; ++i) {
3799
13.4k
      p = &patchesA[i];
3800
13.4k
      p->x[1][1] = (-4 * p->x[0][0]
3801
13.4k
        +6 * (p->x[0][1] + p->x[1][0])
3802
13.4k
        -2 * (p->x[0][3] + p->x[3][0])
3803
13.4k
        +3 * (p->x[3][1] + p->x[1][3])
3804
13.4k
        - p->x[3][3]) / 9;
3805
13.4k
      p->y[1][1] = (-4 * p->y[0][0]
3806
13.4k
        +6 * (p->y[0][1] + p->y[1][0])
3807
13.4k
        -2 * (p->y[0][3] + p->y[3][0])
3808
13.4k
        +3 * (p->y[3][1] + p->y[1][3])
3809
13.4k
        - p->y[3][3]) / 9;
3810
13.4k
      p->x[1][2] = (-4 * p->x[0][3]
3811
13.4k
        +6 * (p->x[0][2] + p->x[1][3])
3812
13.4k
        -2 * (p->x[0][0] + p->x[3][3])
3813
13.4k
        +3 * (p->x[3][2] + p->x[1][0])
3814
13.4k
        - p->x[3][0]) / 9;
3815
13.4k
      p->y[1][2] = (-4 * p->y[0][3]
3816
13.4k
        +6 * (p->y[0][2] + p->y[1][3])
3817
13.4k
        -2 * (p->y[0][0] + p->y[3][3])
3818
13.4k
        +3 * (p->y[3][2] + p->y[1][0])
3819
13.4k
        - p->y[3][0]) / 9;
3820
13.4k
      p->x[2][1] = (-4 * p->x[3][0]
3821
13.4k
        +6 * (p->x[3][1] + p->x[2][0])
3822
13.4k
        -2 * (p->x[3][3] + p->x[0][0])
3823
13.4k
        +3 * (p->x[0][1] + p->x[2][3])
3824
13.4k
        - p->x[0][3]) / 9;
3825
13.4k
      p->y[2][1] = (-4 * p->y[3][0]
3826
13.4k
        +6 * (p->y[3][1] + p->y[2][0])
3827
13.4k
        -2 * (p->y[3][3] + p->y[0][0])
3828
13.4k
        +3 * (p->y[0][1] + p->y[2][3])
3829
13.4k
        - p->y[0][3]) / 9;
3830
13.4k
      p->x[2][2] = (-4 * p->x[3][3]
3831
13.4k
        +6 * (p->x[3][2] + p->x[2][3])
3832
13.4k
        -2 * (p->x[3][0] + p->x[0][3])
3833
13.4k
        +3 * (p->x[0][2] + p->x[2][0])
3834
13.4k
        - p->x[0][0]) / 9;
3835
13.4k
      p->y[2][2] = (-4 * p->y[3][3]
3836
13.4k
        +6 * (p->y[3][2] + p->y[2][3])
3837
13.4k
        -2 * (p->y[3][0] + p->y[0][3])
3838
13.4k
        +3 * (p->y[0][2] + p->y[2][0])
3839
13.4k
        - p->y[0][0]) / 9;
3840
13.4k
    }
3841
786
  }
3842
3843
1.31k
  shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA,
3844
1.31k
            nCompsA, funcsA, nFuncsA);
3845
1.31k
  if (!shading->init(dict
3846
1.31k
         )) {
3847
165
    delete shading;
3848
165
    return NULL;
3849
165
  }
3850
3851
1.15k
  ok = gFalse;
3852
1.15k
  if (shading->nFuncs == 0) {
3853
852
    ok = shading->nComps == shading->getColorSpace()->getNComps();
3854
852
  } else if (shading->nFuncs == 1) {
3855
301
    ok = shading->funcs[0]->getOutputSize()
3856
301
           == shading->getColorSpace()->getNComps();
3857
301
  } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) {
3858
0
    ok = gTrue;
3859
0
    for (i = 0; i < shading->nFuncs; ++i) {
3860
0
      ok = ok && shading->funcs[i]->getOutputSize() == 1;
3861
0
    }
3862
0
  }
3863
1.15k
  if (!ok) {
3864
185
    error(errSyntaxError, -1, "Invalid function in shading dictionary");
3865
185
    delete shading;
3866
185
    return NULL;
3867
185
  }
3868
3869
968
  return shading;
3870
3871
749
 err2:
3872
749
  obj1.free();
3873
1.33k
 err1:
3874
1.33k
  if (patchesA) {
3875
0
    gfree(patchesA);
3876
0
  }
3877
1.33k
  return NULL;
3878
749
}
3879
3880
1.14k
GfxShading *GfxPatchMeshShading::copy() {
3881
1.14k
  return new GfxPatchMeshShading(this);
3882
1.14k
}
3883
3884
void GfxPatchMeshShading::getBBox(double *xMinA, double *yMinA,
3885
482
          double *xMaxA, double *yMaxA) {
3886
482
  double xxMin = 0;
3887
482
  double yyMin = 0;
3888
482
  double xxMax = 0;
3889
482
  double yyMax = 0;
3890
482
  if (nPatches > 0) {
3891
453
    xxMin = patches[0].x[0][0];
3892
453
    yyMin = patches[0].y[0][0];
3893
453
  }
3894
11.7k
  for (int i = 0; i < nPatches; ++i) {
3895
56.2k
    for (int j = 0; j < 4; ++j) {
3896
224k
      for (int k = 0; k < 4; ++k) {
3897
179k
  if (patches[i].x[j][k] < xxMin) {
3898
3.28k
    xxMin = patches[i].x[j][k];
3899
176k
  } else if (patches[i].x[j][k] > xxMax) {
3900
3.10k
    xxMax = patches[i].x[j][k];
3901
3.10k
  }
3902
179k
  if (patches[i].y[j][k] < yyMin) {
3903
2.88k
    yyMin = patches[i].y[j][k];
3904
177k
  } else if (patches[i].y[j][k] > yyMax) {
3905
728
    yyMax = patches[i].y[j][k];
3906
728
  }
3907
179k
      }
3908
44.9k
    }
3909
11.2k
  }
3910
482
  *xMinA = xxMin;
3911
482
  *yMinA = yyMin;
3912
482
  *xMaxA = xxMax;
3913
482
  *yMaxA = yyMax;
3914
482
}
3915
3916
13.3M
void GfxPatchMeshShading::getColor(double *in, GfxColor *out) {
3917
13.3M
  double c[gfxColorMaxComps];
3918
13.3M
  int i;
3919
3920
13.3M
  if (nFuncs > 0) {
3921
7.49k
    for (i = 0; i < nFuncs; ++i) {
3922
3.74k
      funcs[i]->transform(in, &c[i]);
3923
3.74k
    }
3924
14.9k
    for (i = 0; i < colorSpace->getNComps(); ++i) {
3925
11.2k
      out->c[i] = dblToCol(c[i]);
3926
11.2k
    }
3927
13.3M
  } else {
3928
66.7M
    for (i = 0; i < nComps; ++i) {
3929
53.4M
      out->c[i] = dblToCol(in[i]);
3930
53.4M
    }
3931
13.3M
  }
3932
13.3M
}
3933
3934
//------------------------------------------------------------------------
3935
// GfxImageColorMap
3936
//------------------------------------------------------------------------
3937
3938
GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
3939
           GfxColorSpace *colorSpaceA,
3940
27.3k
           int maxAllowedBits) {
3941
27.3k
  GfxIndexedColorSpace *indexedCS;
3942
27.3k
  GfxSeparationColorSpace *sepCS;
3943
27.3k
  int maxPixel, indexHigh;
3944
27.3k
  Guchar *indexedLookup;
3945
27.3k
  Function *sepFunc;
3946
27.3k
  Object obj;
3947
27.3k
  double defaultLow[gfxColorMaxComps], defaultRange[gfxColorMaxComps];
3948
27.3k
  double x[gfxColorMaxComps], y[gfxColorMaxComps];
3949
27.3k
  int i, j, k;
3950
3951
27.3k
  ok = gTrue;
3952
3953
  // bits per component and color space
3954
27.3k
  bits = bitsA;
3955
27.3k
  if (bits <= maxAllowedBits) {
3956
27.1k
    maxPixel = (1 << bits) - 1;
3957
27.1k
  } else {
3958
194
    maxPixel = (1 << maxAllowedBits) - 1;
3959
194
  }
3960
27.3k
  colorSpace = colorSpaceA;
3961
3962
  // initialize
3963
901k
  for (k = 0; k < gfxColorMaxComps; ++k) {
3964
874k
    lookup[k] = NULL;
3965
874k
    lookup2[k] = NULL;
3966
874k
  }
3967
3968
  // get decode map
3969
27.3k
  colorSpace->getDefaultRanges(defaultLow, defaultRange, maxPixel);
3970
27.3k
  if (decode->isNull()) {
3971
19.3k
    nComps = colorSpace->getNComps();
3972
53.1k
    for (i = 0; i < nComps; ++i) {
3973
33.7k
      decodeLow[i] = defaultLow[i];
3974
33.7k
      decodeRange[i] = defaultRange[i];
3975
33.7k
    }
3976
19.3k
  } else if (decode->isArray()) {
3977
7.36k
    nComps = decode->arrayGetLength() / 2;
3978
7.36k
    if (nComps < colorSpace->getNComps()) {
3979
514
      goto err1;
3980
514
    }
3981
6.85k
    if (nComps > colorSpace->getNComps()) {
3982
25
      error(errSyntaxWarning, -1, "Too many elements in Decode array");
3983
25
      nComps = colorSpace->getNComps();
3984
25
    }
3985
13.3k
    for (i = 0; i < nComps; ++i) {
3986
6.88k
      decode->arrayGet(2*i, &obj);
3987
6.88k
      if (!obj.isNum()) {
3988
94
  goto err2;
3989
94
      }
3990
6.79k
      decodeLow[i] = obj.getNum();
3991
6.79k
      obj.free();
3992
6.79k
      decode->arrayGet(2*i+1, &obj);
3993
6.79k
      if (!obj.isNum()) {
3994
252
  goto err2;
3995
252
      }
3996
6.54k
      decodeRange[i] = obj.getNum() - decodeLow[i];
3997
6.54k
      obj.free();
3998
6.54k
    }
3999
6.85k
  } else {
4000
606
    goto err1;
4001
606
  }
4002
4003
  // Construct a lookup table -- this stores pre-computed decoded
4004
  // values for each component, i.e., the result of applying the
4005
  // decode mapping to each possible image pixel component value.
4006
66.1k
  for (k = 0; k < nComps; ++k) {
4007
40.2k
    lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
4008
40.2k
           sizeof(GfxColorComp));
4009
7.57M
    for (i = 0; i <= maxPixel; ++i) {
4010
7.53M
      double t = decodeLow[k] + (i * decodeRange[k]) / maxPixel;
4011
7.53M
      if (t < defaultLow[k]) {
4012
263
  t = defaultLow[k];
4013
7.53M
      } else if (t > defaultLow[k] + defaultRange[k]) {
4014
837
  t = defaultLow[k] + defaultRange[k];
4015
837
      }
4016
7.53M
      lookup[k][i] = dblToCol(t);
4017
7.53M
    }
4018
40.2k
  }
4019
4020
  // Optimization: for Indexed and Separation color spaces (which have
4021
  // only one component), we pre-compute a second lookup table with
4022
  // color values
4023
25.8k
  colorSpace2 = NULL;
4024
25.8k
  nComps2 = 0;
4025
25.8k
  if (colorSpace->getMode() == csIndexed) {
4026
    // Note that indexHigh may not be the same as maxPixel --
4027
    // Distiller will remove unused palette entries, resulting in
4028
    // indexHigh < maxPixel.
4029
974
    indexedCS = (GfxIndexedColorSpace *)colorSpace;
4030
974
    colorSpace2 = indexedCS->getBase();
4031
974
    indexHigh = indexedCS->getIndexHigh();
4032
974
    nComps2 = colorSpace2->getNComps();
4033
974
    indexedLookup = indexedCS->getLookup();
4034
974
    colorSpace2->getDefaultRanges(x, y, indexHigh);
4035
3.89k
    for (k = 0; k < nComps2; ++k) {
4036
2.91k
      lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
4037
2.91k
              sizeof(GfxColorComp));
4038
2.91k
    }
4039
109k
    for (i = 0; i <= maxPixel; ++i) {
4040
108k
      j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
4041
108k
      if (j < 0) {
4042
0
  j = 0;
4043
108k
      } else if (j > indexHigh) {
4044
52.0k
  j = indexHigh;
4045
52.0k
      }
4046
432k
      for (k = 0; k < nComps2; ++k) {
4047
323k
  lookup2[k][i] =
4048
323k
      dblToCol(x[k] + (indexedLookup[j*nComps2 + k] / 255.0) * y[k]);
4049
323k
      }
4050
108k
    }
4051
24.8k
  } else if (colorSpace->getMode() == csSeparation) {
4052
22
    sepCS = (GfxSeparationColorSpace *)colorSpace;
4053
22
    colorSpace2 = sepCS->getAlt();
4054
22
    nComps2 = colorSpace2->getNComps();
4055
22
    sepFunc = sepCS->getFunc();
4056
88
    for (k = 0; k < nComps2; ++k) {
4057
66
      lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
4058
66
              sizeof(GfxColorComp));
4059
66
    }
4060
5.65k
    for (i = 0; i <= maxPixel; ++i) {
4061
5.63k
      double t = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
4062
5.63k
      if (t < defaultLow[0]) {
4063
0
  t = defaultLow[0];
4064
5.63k
      } else if (t > defaultLow[0] + defaultRange[0]) {
4065
0
  t = defaultLow[0] + defaultRange[0];
4066
0
      }
4067
5.63k
      x[0] = t;
4068
5.63k
      sepFunc->transform(x, y);
4069
22.5k
      for (k = 0; k < nComps2; ++k) {
4070
16.8k
  lookup2[k][i] = dblToCol(y[k]);
4071
16.8k
      }
4072
5.63k
    }
4073
22
  }
4074
4075
25.8k
  return;
4076
4077
346
 err2:
4078
346
  obj.free();
4079
1.46k
 err1:
4080
1.46k
  ok = gFalse;
4081
1.46k
}
4082
4083
0
GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) {
4084
0
  int n, i, k;
4085
4086
0
  colorSpace = colorMap->colorSpace->copy();
4087
0
  bits = colorMap->bits;
4088
0
  nComps = colorMap->nComps;
4089
0
  nComps2 = colorMap->nComps2;
4090
0
  colorSpace2 = NULL;
4091
0
  for (k = 0; k < gfxColorMaxComps; ++k) {
4092
0
    lookup[k] = NULL;
4093
0
    lookup2[k] = NULL;
4094
0
  }
4095
0
  if (bits <= 8) {
4096
0
    n = 1 << bits;
4097
0
  } else {
4098
0
    n = 256;
4099
0
  }
4100
0
  for (k = 0; k < nComps; ++k) {
4101
0
    lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
4102
0
    memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp));
4103
0
  }
4104
0
  if (colorSpace->getMode() == csIndexed) {
4105
0
    colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase();
4106
0
    for (k = 0; k < nComps2; ++k) {
4107
0
      lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
4108
0
      memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp));
4109
0
    }
4110
0
  } else if (colorSpace->getMode() == csSeparation) {
4111
0
    colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt();
4112
0
    for (k = 0; k < nComps2; ++k) {
4113
0
      lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
4114
0
      memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp));
4115
0
    }
4116
0
  }
4117
0
  for (i = 0; i < nComps; ++i) {
4118
0
    decodeLow[i] = colorMap->decodeLow[i];
4119
0
    decodeRange[i] = colorMap->decodeRange[i];
4120
0
  }
4121
0
  ok = gTrue;
4122
0
}
4123
4124
27.3k
GfxImageColorMap::~GfxImageColorMap() {
4125
27.3k
  int i;
4126
4127
27.3k
  delete colorSpace;
4128
901k
  for (i = 0; i < gfxColorMaxComps; ++i) {
4129
874k
    gfree(lookup[i]);
4130
874k
    gfree(lookup2[i]);
4131
874k
  }
4132
27.3k
}
4133
4134
void GfxImageColorMap::getGray(Guchar *x, GfxGray *gray,
4135
479k
             GfxRenderingIntent ri) {
4136
479k
  GfxColor color;
4137
479k
  int i;
4138
4139
479k
  if (colorSpace2) {
4140
0
    for (i = 0; i < nComps2; ++i) {
4141
0
      color.c[i] = lookup2[i][x[0]];
4142
0
    }
4143
0
    colorSpace2->getGray(&color, gray, ri);
4144
479k
  } else {
4145
958k
    for (i = 0; i < nComps; ++i) {
4146
479k
      color.c[i] = lookup[i][x[i]];
4147
479k
    }
4148
479k
    colorSpace->getGray(&color, gray, ri);
4149
479k
  }
4150
479k
}
4151
4152
1.52M
void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb, GfxRenderingIntent ri) {
4153
1.52M
  GfxColor color;
4154
1.52M
  int i;
4155
4156
1.52M
  if (colorSpace2) {
4157
454k
    for (i = 0; i < nComps2; ++i) {
4158
340k
      color.c[i] = lookup2[i][x[0]];
4159
340k
    }
4160
113k
    colorSpace2->getRGB(&color, rgb, ri);
4161
1.41M
  } else {
4162
2.82M
    for (i = 0; i < nComps; ++i) {
4163
1.41M
      color.c[i] = lookup[i][x[i]];
4164
1.41M
    }
4165
1.41M
    colorSpace->getRGB(&color, rgb, ri);
4166
1.41M
  }
4167
1.52M
}
4168
4169
void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk,
4170
45.3k
             GfxRenderingIntent ri) {
4171
45.3k
  GfxColor color;
4172
45.3k
  int i;
4173
4174
45.3k
  if (colorSpace2) {
4175
0
    for (i = 0; i < nComps2; ++i) {
4176
0
      color.c[i] = lookup2[i][x[0]];
4177
0
    }
4178
0
    colorSpace2->getCMYK(&color, cmyk, ri);
4179
45.3k
  } else {
4180
90.7k
    for (i = 0; i < nComps; ++i) {
4181
45.3k
      color.c[i] = lookup[i][x[i]];
4182
45.3k
    }
4183
45.3k
    colorSpace->getCMYK(&color, cmyk, ri);
4184
45.3k
  }
4185
45.3k
}
4186
4187
4188
0
void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) {
4189
0
  int i;
4190
4191
0
  for (i = 0; i < nComps; ++i) {
4192
0
    color->c[i] = lookup[i][x[i]];
4193
0
  }
4194
0
}
4195
4196
void GfxImageColorMap::getGrayByteLine(Guchar *in, Guchar *out, int n,
4197
0
               GfxRenderingIntent ri) {
4198
0
  GfxColor color;
4199
0
  GfxGray gray;
4200
0
  int i, j;
4201
4202
0
  if (colorSpace2) {
4203
0
    for (j = 0; j < n; ++j) {
4204
0
      for (i = 0; i < nComps2; ++i) {
4205
0
  color.c[i] = lookup2[i][in[j]];
4206
0
      }
4207
0
      colorSpace2->getGray(&color, &gray, ri);
4208
0
      out[j] = colToByte(gray);
4209
0
    }
4210
0
  } else {
4211
0
    for (j = 0; j < n; ++j) {
4212
0
      for (i = 0; i < nComps; ++i) {
4213
0
  color.c[i] = lookup[i][in[j * nComps + i]];
4214
0
      }
4215
0
      colorSpace->getGray(&color, &gray, ri);
4216
0
      out[j] = colToByte(gray);
4217
0
    }
4218
0
  }
4219
0
}
4220
4221
void GfxImageColorMap::getRGBByteLine(Guchar *in, Guchar *out, int n,
4222
11.8k
              GfxRenderingIntent ri) {
4223
11.8k
  GfxColor color;
4224
11.8k
  GfxRGB rgb;
4225
11.8k
  int i, j;
4226
4227
11.8k
  if (colorSpace2) {
4228
0
    for (j = 0; j < n; ++j) {
4229
0
      for (i = 0; i < nComps2; ++i) {
4230
0
  color.c[i] = lookup2[i][in[j]];
4231
0
      }
4232
0
      colorSpace2->getRGB(&color, &rgb, ri);
4233
0
      out[j*3] = colToByte(rgb.r);
4234
0
      out[j*3 + 1] = colToByte(rgb.g);
4235
0
      out[j*3 + 2] = colToByte(rgb.b);
4236
0
    }
4237
11.8k
  } else {
4238
1.85M
    for (j = 0; j < n; ++j) {
4239
7.39M
      for (i = 0; i < nComps; ++i) {
4240
5.54M
  color.c[i] = lookup[i][in[j * nComps + i]];
4241
5.54M
      }
4242
1.84M
      colorSpace->getRGB(&color, &rgb, ri);
4243
1.84M
      out[j*3] = colToByte(rgb.r);
4244
1.84M
      out[j*3 + 1] = colToByte(rgb.g);
4245
1.84M
      out[j*3 + 2] = colToByte(rgb.b);
4246
1.84M
    }
4247
11.8k
  }
4248
11.8k
}
4249
4250
void GfxImageColorMap::getCMYKByteLine(Guchar *in, Guchar *out, int n,
4251
0
               GfxRenderingIntent ri) {
4252
0
  GfxColor color;
4253
0
  GfxCMYK cmyk;
4254
0
  int i, j;
4255
4256
0
  if (colorSpace2) {
4257
0
    for (j = 0; j < n; ++j) {
4258
0
      for (i = 0; i < nComps2; ++i) {
4259
0
  color.c[i] = lookup2[i][in[j]];
4260
0
      }
4261
0
      colorSpace2->getCMYK(&color, &cmyk, ri);
4262
0
      out[j*4] = colToByte(cmyk.c);
4263
0
      out[j*4 + 1] = colToByte(cmyk.m);
4264
0
      out[j*4 + 2] = colToByte(cmyk.y);
4265
0
      out[j*4 + 3] = colToByte(cmyk.k);
4266
0
    }
4267
0
  } else {
4268
0
    for (j = 0; j < n; ++j) {
4269
0
      for (i = 0; i < nComps; ++i) {
4270
0
  color.c[i] = lookup[i][in[j * nComps + i]];
4271
0
      }
4272
0
      colorSpace->getCMYK(&color, &cmyk, ri);
4273
0
      out[j*4] = colToByte(cmyk.c);
4274
0
      out[j*4 + 1] = colToByte(cmyk.m);
4275
0
      out[j*4 + 2] = colToByte(cmyk.y);
4276
0
      out[j*4 + 3] = colToByte(cmyk.k);
4277
0
    }
4278
0
  }
4279
0
}
4280
4281
4282
//------------------------------------------------------------------------
4283
// GfxSubpath and GfxPath
4284
//------------------------------------------------------------------------
4285
4286
405k
GfxSubpath::GfxSubpath(double x1, double y1) {
4287
405k
  size = 16;
4288
405k
  x = (double *)gmallocn(size, sizeof(double));
4289
405k
  y = (double *)gmallocn(size, sizeof(double));
4290
405k
  curve = (GBool *)gmallocn(size, sizeof(GBool));
4291
405k
  n = 1;
4292
405k
  x[0] = x1;
4293
405k
  y[0] = y1;
4294
405k
  curve[0] = gFalse;
4295
405k
  closed = gFalse;
4296
405k
}
4297
4298
517k
GfxSubpath::~GfxSubpath() {
4299
517k
  gfree(x);
4300
517k
  gfree(y);
4301
517k
  gfree(curve);
4302
517k
}
4303
4304
// Used for copy().
4305
111k
GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
4306
111k
  size = subpath->size;
4307
111k
  n = subpath->n;
4308
111k
  x = (double *)gmallocn(size, sizeof(double));
4309
111k
  y = (double *)gmallocn(size, sizeof(double));
4310
111k
  curve = (GBool *)gmallocn(size, sizeof(GBool));
4311
111k
  memcpy(x, subpath->x, n * sizeof(double));
4312
111k
  memcpy(y, subpath->y, n * sizeof(double));
4313
111k
  memcpy(curve, subpath->curve, n * sizeof(GBool));
4314
111k
  closed = subpath->closed;
4315
111k
}
4316
4317
1.31M
void GfxSubpath::lineTo(double x1, double y1) {
4318
1.31M
  if (n >= size) {
4319
646
    size *= 2;
4320
646
    x = (double *)greallocn(x, size, sizeof(double));
4321
646
    y = (double *)greallocn(y, size, sizeof(double));
4322
646
    curve = (GBool *)greallocn(curve, size, sizeof(GBool));
4323
646
  }
4324
1.31M
  x[n] = x1;
4325
1.31M
  y[n] = y1;
4326
1.31M
  curve[n] = gFalse;
4327
1.31M
  ++n;
4328
1.31M
}
4329
4330
void GfxSubpath::curveTo(double x1, double y1, double x2, double y2,
4331
95.2k
       double x3, double y3) {
4332
95.2k
  if (n+3 > size) {
4333
1.17k
    size *= 2;
4334
1.17k
    x = (double *)greallocn(x, size, sizeof(double));
4335
1.17k
    y = (double *)greallocn(y, size, sizeof(double));
4336
1.17k
    curve = (GBool *)greallocn(curve, size, sizeof(GBool));
4337
1.17k
  }
4338
95.2k
  x[n] = x1;
4339
95.2k
  y[n] = y1;
4340
95.2k
  x[n+1] = x2;
4341
95.2k
  y[n+1] = y2;
4342
95.2k
  x[n+2] = x3;
4343
95.2k
  y[n+2] = y3;
4344
95.2k
  curve[n] = curve[n+1] = gTrue;
4345
95.2k
  curve[n+2] = gFalse;
4346
95.2k
  n += 3;
4347
95.2k
}
4348
4349
359k
void GfxSubpath::close() {
4350
359k
  if (x[n-1] != x[0] || y[n-1] != y[0]) {
4351
309k
    lineTo(x[0], y[0]);
4352
309k
  }
4353
359k
  closed = gTrue;
4354
359k
}
4355
4356
0
void GfxSubpath::offset(double dx, double dy) {
4357
0
  int i;
4358
4359
0
  for (i = 0; i < n; ++i) {
4360
0
    x[i] += dx;
4361
0
    y[i] += dy;
4362
0
  }
4363
0
}
4364
4365
1.24M
GfxPath::GfxPath() {
4366
1.24M
  justMoved = gFalse;
4367
1.24M
  size = 16;
4368
1.24M
  n = 0;
4369
1.24M
  firstX = firstY = 0;
4370
1.24M
  subpaths = (GfxSubpath **)gmallocn(size, sizeof(GfxSubpath *));
4371
1.24M
}
4372
4373
3.05M
GfxPath::~GfxPath() {
4374
3.05M
  int i;
4375
4376
3.56M
  for (i = 0; i < n; ++i)
4377
517k
    delete subpaths[i];
4378
3.05M
  gfree(subpaths);
4379
3.05M
}
4380
4381
// Used for copy().
4382
GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1,
4383
1.80M
     GfxSubpath **subpaths1, int n1, int size1) {
4384
1.80M
  int i;
4385
4386
1.80M
  justMoved = justMoved1;
4387
1.80M
  firstX = firstX1;
4388
1.80M
  firstY = firstY1;
4389
1.80M
  size = size1;
4390
1.80M
  n = n1;
4391
1.80M
  subpaths = (GfxSubpath **)gmallocn(size, sizeof(GfxSubpath *));
4392
1.91M
  for (i = 0; i < n; ++i)
4393
111k
    subpaths[i] = subpaths1[i]->copy();
4394
1.80M
}
4395
4396
0
double GfxPath::getCurX() {
4397
0
  if (justMoved) {
4398
0
    return firstX;
4399
0
  } else if (n > 0) {
4400
0
    return subpaths[n-1]->getLastX();
4401
0
  } else {
4402
0
    return 0;
4403
0
  }
4404
0
}
4405
4406
0
double GfxPath::getCurY() {
4407
0
  if (justMoved) {
4408
0
    return firstY;
4409
0
  } else if (n > 0) {
4410
0
    return subpaths[n-1]->getLastY();
4411
0
  } else {
4412
0
    return 0;
4413
0
  }
4414
0
}
4415
4416
2.13M
void GfxPath::moveTo(double x, double y) {
4417
2.13M
  justMoved = gTrue;
4418
2.13M
  firstX = x;
4419
2.13M
  firstY = y;
4420
2.13M
}
4421
4422
1.00M
void GfxPath::lineTo(double x, double y) {
4423
1.00M
  if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) {
4424
338k
    if (n >= size) {
4425
223
      size *= 2;
4426
223
      subpaths = (GfxSubpath **)
4427
223
             greallocn(subpaths, size, sizeof(GfxSubpath *));
4428
223
    }
4429
338k
    if (justMoved) {
4430
335k
      subpaths[n] = new GfxSubpath(firstX, firstY);
4431
335k
    } else {
4432
3.57k
      subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(),
4433
3.57k
           subpaths[n-1]->getLastY());
4434
3.57k
    }
4435
338k
    ++n;
4436
338k
    justMoved = gFalse;
4437
338k
  }
4438
1.00M
  subpaths[n-1]->lineTo(x, y);
4439
1.00M
}
4440
4441
void GfxPath::curveTo(double x1, double y1, double x2, double y2,
4442
95.2k
       double x3, double y3) {
4443
95.2k
  if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) {
4444
57.6k
    if (n >= size) {
4445
43
      size *= 2;
4446
43
      subpaths = (GfxSubpath **)
4447
43
             greallocn(subpaths, size, sizeof(GfxSubpath *));
4448
43
    }
4449
57.6k
    if (justMoved) {
4450
53.0k
      subpaths[n] = new GfxSubpath(firstX, firstY);
4451
53.0k
    } else {
4452
4.59k
      subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(),
4453
4.59k
           subpaths[n-1]->getLastY());
4454
4.59k
    }
4455
57.6k
    ++n;
4456
57.6k
    justMoved = gFalse;
4457
57.6k
  }
4458
95.2k
  subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
4459
95.2k
}
4460
4461
359k
void GfxPath::close() {
4462
  // this is necessary to handle the pathological case of
4463
  // moveto/closepath/clip, which defines an empty clipping region
4464
359k
  if (justMoved) {
4465
9.04k
    if (n >= size) {
4466
14
      size *= 2;
4467
14
      subpaths = (GfxSubpath **)
4468
14
             greallocn(subpaths, size, sizeof(GfxSubpath *));
4469
14
    }
4470
9.04k
    subpaths[n] = new GfxSubpath(firstX, firstY);
4471
9.04k
    ++n;
4472
9.04k
    justMoved = gFalse;
4473
9.04k
  }
4474
359k
  subpaths[n-1]->close();
4475
359k
}
4476
4477
0
void GfxPath::append(GfxPath *path) {
4478
0
  int i;
4479
4480
0
  if (n + path->n > size) {
4481
0
    size = n + path->n;
4482
0
    subpaths = (GfxSubpath **)
4483
0
                 greallocn(subpaths, size, sizeof(GfxSubpath *));
4484
0
  }
4485
0
  for (i = 0; i < path->n; ++i) {
4486
0
    subpaths[n++] = path->subpaths[i]->copy();
4487
0
  }
4488
0
  justMoved = gFalse;
4489
0
}
4490
4491
0
void GfxPath::offset(double dx, double dy) {
4492
0
  int i;
4493
4494
0
  for (i = 0; i < n; ++i) {
4495
0
    subpaths[i]->offset(dx, dy);
4496
0
  }
4497
0
}
4498
4499
//------------------------------------------------------------------------
4500
// GfxState
4501
//------------------------------------------------------------------------
4502
4503
GfxState::GfxState(LocalParams *localParamsA,
4504
       double hDPIA, double vDPIA, PDFRectangle *pageBox,
4505
       int rotateA, GBool upsideDown
4506
376k
       ) {
4507
376k
  double kx, ky;
4508
4509
376k
  localParams = localParamsA;
4510
376k
  hDPI = hDPIA;
4511
376k
  vDPI = vDPIA;
4512
376k
  rotate = rotateA;
4513
376k
  px1 = pageBox->x1;
4514
376k
  py1 = pageBox->y1;
4515
376k
  px2 = pageBox->x2;
4516
376k
  py2 = pageBox->y2;
4517
376k
  kx = hDPI / 72.0;
4518
376k
  ky = vDPI / 72.0;
4519
376k
  if (rotate == 90) {
4520
0
    ctm[0] = 0;
4521
0
    ctm[1] = upsideDown ? ky : -ky;
4522
0
    ctm[2] = kx;
4523
0
    ctm[3] = 0;
4524
0
    ctm[4] = -kx * py1;
4525
0
    ctm[5] = ky * (upsideDown ? -px1 : px2);
4526
0
    pageWidth = kx * (py2 - py1);
4527
0
    pageHeight = ky * (px2 - px1);
4528
376k
  } else if (rotate == 180) {
4529
0
    ctm[0] = -kx;
4530
0
    ctm[1] = 0;
4531
0
    ctm[2] = 0;
4532
0
    ctm[3] = upsideDown ? ky : -ky;
4533
0
    ctm[4] = kx * px2;
4534
0
    ctm[5] = ky * (upsideDown ? -py1 : py2);
4535
0
    pageWidth = kx * (px2 - px1);
4536
0
    pageHeight = ky * (py2 - py1);
4537
376k
  } else if (rotate == 270) {
4538
0
    ctm[0] = 0;
4539
0
    ctm[1] = upsideDown ? -ky : ky;
4540
0
    ctm[2] = -kx;
4541
0
    ctm[3] = 0;
4542
0
    ctm[4] = kx * py2;
4543
0
    ctm[5] = ky * (upsideDown ? px2 : -px1);
4544
0
    pageWidth = kx * (py2 - py1);
4545
0
    pageHeight = ky * (px2 - px1);
4546
376k
  } else {
4547
376k
    ctm[0] = kx;
4548
376k
    ctm[1] = 0;
4549
376k
    ctm[2] = 0;
4550
376k
    ctm[3] = upsideDown ? -ky : ky;
4551
376k
    ctm[4] = -kx * px1;
4552
376k
    ctm[5] = ky * (upsideDown ? py2 : -py1);
4553
376k
    pageWidth = kx * (px2 - px1);
4554
376k
    pageHeight = ky * (py2 - py1);
4555
376k
  }
4556
4557
376k
  fillColorSpace = GfxColorSpace::create(csDeviceGray);
4558
376k
  strokeColorSpace = GfxColorSpace::create(csDeviceGray);
4559
376k
  fillColor.c[0] = 0;
4560
376k
  strokeColor.c[0] = 0;
4561
376k
  fillPattern = NULL;
4562
376k
  strokePattern = NULL;
4563
376k
  blendMode = gfxBlendNormal;
4564
376k
  fillOpacity = 1;
4565
376k
  strokeOpacity = 1;
4566
376k
  fillOverprint = gFalse;
4567
376k
  strokeOverprint = gFalse;
4568
376k
  if (localParams) {
4569
0
    renderingIntent = localParams->getDefaultRenderingIntent();
4570
376k
  } else {
4571
376k
    renderingIntent = gfxRenderingIntentRelativeColorimetric;
4572
376k
  }
4573
376k
  overprintMode = 0;
4574
376k
  transfer[0] = transfer[1] = transfer[2] = transfer[3] = NULL;
4575
4576
376k
  lineWidth = 1;
4577
376k
  lineDash = NULL;
4578
376k
  lineDashLength = 0;
4579
376k
  lineDashStart = 0;
4580
376k
  flatness = 1;
4581
376k
  lineJoin = 0;
4582
376k
  lineCap = 0;
4583
376k
  miterLimit = 10;
4584
376k
  strokeAdjust = gFalse;
4585
376k
  alphaIsShape = gFalse;
4586
4587
376k
  font = NULL;
4588
376k
  fontSize = 0;
4589
376k
  textMat[0] = 1; textMat[1] = 0;
4590
376k
  textMat[2] = 0; textMat[3] = 1;
4591
376k
  textMat[4] = 0; textMat[5] = 0;
4592
376k
  charSpace = 0;
4593
376k
  wordSpace = 0;
4594
376k
  horizScaling = 1;
4595
376k
  leading = 0;
4596
376k
  rise = 0;
4597
376k
  render = 0;
4598
4599
376k
  path = new GfxPath();
4600
376k
  curX = curY = 0;
4601
376k
  lineX = lineY = 0;
4602
4603
376k
  clipXMin = 0;
4604
376k
  clipYMin = 0;
4605
376k
  clipXMax = pageWidth;
4606
376k
  clipYMax = pageHeight;
4607
4608
376k
  ignoreColorOps = gFalse;
4609
4610
376k
  saved = NULL;
4611
376k
}
4612
4613
2.82M
GfxState::~GfxState() {
4614
2.82M
  int i;
4615
4616
2.82M
  if (fillColorSpace) {
4617
2.82M
    delete fillColorSpace;
4618
2.82M
  }
4619
2.82M
  if (strokeColorSpace) {
4620
2.82M
    delete strokeColorSpace;
4621
2.82M
  }
4622
2.82M
  if (fillPattern) {
4623
48.3k
    delete fillPattern;
4624
48.3k
  }
4625
2.82M
  if (strokePattern) {
4626
157
    delete strokePattern;
4627
157
  }
4628
14.1M
  for (i = 0; i < 4; ++i) {
4629
11.2M
    if (transfer[i]) {
4630
278
      delete transfer[i];
4631
278
    }
4632
11.2M
  }
4633
2.82M
  gfree(lineDash);
4634
2.82M
  if (path) {
4635
    // this gets set to NULL by restore()
4636
2.18M
    delete path;
4637
2.18M
  }
4638
2.82M
}
4639
4640
// Used for copy();
4641
2.44M
GfxState::GfxState(GfxState *state, GBool copyPath) {
4642
2.44M
  int i;
4643
4644
2.44M
  memcpy(this, state, sizeof(GfxState));
4645
2.44M
  if (fillColorSpace) {
4646
2.44M
    fillColorSpace = state->fillColorSpace->copy();
4647
2.44M
  }
4648
2.44M
  if (strokeColorSpace) {
4649
2.44M
    strokeColorSpace = state->strokeColorSpace->copy();
4650
2.44M
  }
4651
2.44M
  if (fillPattern) {
4652
60.3k
    fillPattern = state->fillPattern->copy();
4653
60.3k
  }
4654
2.44M
  if (strokePattern) {
4655
303
    strokePattern = state->strokePattern->copy();
4656
303
  }
4657
12.2M
  for (i = 0; i < 4; ++i) {
4658
9.78M
    if (transfer[i]) {
4659
236
      transfer[i] = state->transfer[i]->copy();
4660
236
    }
4661
9.78M
  }
4662
2.44M
  if (lineDashLength > 0) {
4663
2.85k
    lineDash = (double *)gmallocn(lineDashLength, sizeof(double));
4664
2.85k
    memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
4665
2.85k
  }
4666
2.44M
  if (copyPath) {
4667
1.80M
    path = state->path->copy();
4668
1.80M
  }
4669
2.44M
  saved = NULL;
4670
2.44M
}
4671
4672
0
void GfxState::setPath(GfxPath *pathA) {
4673
0
  delete path;
4674
0
  path = pathA;
4675
0
}
4676
4677
void GfxState::getUserClipBBox(double *xMin, double *yMin,
4678
0
             double *xMax, double *yMax) {
4679
0
  double ictm[6];
4680
0
  double xMin1, yMin1, xMax1, yMax1, det, tx, ty;
4681
4682
  // invert the CTM
4683
0
  det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
4684
0
  ictm[0] = ctm[3] * det;
4685
0
  ictm[1] = -ctm[1] * det;
4686
0
  ictm[2] = -ctm[2] * det;
4687
0
  ictm[3] = ctm[0] * det;
4688
0
  ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
4689
0
  ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
4690
4691
  // transform all four corners of the clip bbox; find the min and max
4692
  // x and y values
4693
0
  xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4];
4694
0
  yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5];
4695
0
  tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4];
4696
0
  ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5];
4697
0
  if (tx < xMin1) {
4698
0
    xMin1 = tx;
4699
0
  } else if (tx > xMax1) {
4700
0
    xMax1 = tx;
4701
0
  }
4702
0
  if (ty < yMin1) {
4703
0
    yMin1 = ty;
4704
0
  } else if (ty > yMax1) {
4705
0
    yMax1 = ty;
4706
0
  }
4707
0
  tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4];
4708
0
  ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5];
4709
0
  if (tx < xMin1) {
4710
0
    xMin1 = tx;
4711
0
  } else if (tx > xMax1) {
4712
0
    xMax1 = tx;
4713
0
  }
4714
0
  if (ty < yMin1) {
4715
0
    yMin1 = ty;
4716
0
  } else if (ty > yMax1) {
4717
0
    yMax1 = ty;
4718
0
  }
4719
0
  tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4];
4720
0
  ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5];
4721
0
  if (tx < xMin1) {
4722
0
    xMin1 = tx;
4723
0
  } else if (tx > xMax1) {
4724
0
    xMax1 = tx;
4725
0
  }
4726
0
  if (ty < yMin1) {
4727
0
    yMin1 = ty;
4728
0
  } else if (ty > yMax1) {
4729
0
    yMax1 = ty;
4730
0
  }
4731
4732
0
  *xMin = xMin1;
4733
0
  *yMin = yMin1;
4734
0
  *xMax = xMax1;
4735
0
  *yMax = yMax1;
4736
0
}
4737
4738
0
double GfxState::transformWidth(double w) {
4739
0
  double x, y;
4740
4741
0
  x = ctm[0] + ctm[2];
4742
0
  y = ctm[1] + ctm[3];
4743
0
  return w * sqrt(0.5 * (x * x + y * y));
4744
0
}
4745
4746
0
double GfxState::getTransformedFontSize() {
4747
0
  double x1, y1, x2, y2;
4748
4749
0
  x1 = textMat[2] * fontSize;
4750
0
  y1 = textMat[3] * fontSize;
4751
0
  x2 = ctm[0] * x1 + ctm[2] * y1;
4752
0
  y2 = ctm[1] * x1 + ctm[3] * y1;
4753
0
  return sqrt(x2 * x2 + y2 * y2);
4754
0
}
4755
4756
void GfxState::getFontTransMat(double *m11, double *m12,
4757
0
             double *m21, double *m22) {
4758
0
  *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize * horizScaling;
4759
0
  *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize * horizScaling;
4760
0
  *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
4761
0
  *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
4762
0
}
4763
4764
void GfxState::setCTM(double a, double b, double c,
4765
1.65M
          double d, double e, double f) {
4766
1.65M
  int i;
4767
4768
1.65M
  ctm[0] = a;
4769
1.65M
  ctm[1] = b;
4770
1.65M
  ctm[2] = c;
4771
1.65M
  ctm[3] = d;
4772
1.65M
  ctm[4] = e;
4773
1.65M
  ctm[5] = f;
4774
4775
  // avoid FP exceptions on badly messed up PDF files
4776
11.5M
  for (i = 0; i < 6; ++i) {
4777
9.90M
    if (ctm[i] > 1e10) {
4778
2.41M
      ctm[i] = 1e10;
4779
7.48M
    } else if (ctm[i] < -1e10) {
4780
1.61M
      ctm[i] = -1e10;
4781
1.61M
    }
4782
9.90M
  }
4783
1.65M
}
4784
4785
void GfxState::concatCTM(double a, double b, double c,
4786
276k
       double d, double e, double f) {
4787
276k
  double a1 = ctm[0];
4788
276k
  double b1 = ctm[1];
4789
276k
  double c1 = ctm[2];
4790
276k
  double d1 = ctm[3];
4791
276k
  int i;
4792
4793
276k
  ctm[0] = a * a1 + b * c1;
4794
276k
  ctm[1] = a * b1 + b * d1;
4795
276k
  ctm[2] = c * a1 + d * c1;
4796
276k
  ctm[3] = c * b1 + d * d1;
4797
276k
  ctm[4] = e * a1 + f * c1 + ctm[4];
4798
276k
  ctm[5] = e * b1 + f * d1 + ctm[5];
4799
4800
  // avoid FP exceptions on badly messed up PDF files
4801
1.93M
  for (i = 0; i < 6; ++i) {
4802
1.65M
    if (ctm[i] > 1e10) {
4803
178k
      ctm[i] = 1e10;
4804
1.47M
    } else if (ctm[i] < -1e10) {
4805
447k
      ctm[i] = -1e10;
4806
447k
    }
4807
1.65M
  }
4808
276k
}
4809
4810
10.1k
void GfxState::shiftCTM(double tx, double ty) {
4811
10.1k
  ctm[4] += tx;
4812
10.1k
  ctm[5] += ty;
4813
10.1k
  clipXMin += tx;
4814
10.1k
  clipYMin += ty;
4815
10.1k
  clipXMax += tx;
4816
10.1k
  clipYMax += ty;
4817
10.1k
}
4818
4819
230k
void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
4820
230k
  if (fillColorSpace) {
4821
230k
    delete fillColorSpace;
4822
230k
  }
4823
230k
  fillColorSpace = colorSpace;
4824
230k
}
4825
4826
149k
void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
4827
149k
  if (strokeColorSpace) {
4828
149k
    delete strokeColorSpace;
4829
149k
  }
4830
149k
  strokeColorSpace = colorSpace;
4831
149k
}
4832
4833
269k
void GfxState::setFillPattern(GfxPattern *pattern) {
4834
269k
  if (fillPattern) {
4835
32.7k
    delete fillPattern;
4836
32.7k
  }
4837
269k
  fillPattern = pattern;
4838
269k
}
4839
4840
151k
void GfxState::setStrokePattern(GfxPattern *pattern) {
4841
151k
  if (strokePattern) {
4842
338
    delete strokePattern;
4843
338
  }
4844
151k
  strokePattern = pattern;
4845
151k
}
4846
4847
2.65k
void GfxState::setRenderingIntent(GfxRenderingIntent ri) {
4848
2.65k
  if (!(localParams && localParams->getForceRenderingIntent())) {
4849
2.65k
    renderingIntent = ri;
4850
2.65k
  }
4851
2.65k
}
4852
4853
897
void GfxState::setTransfer(Function **funcs) {
4854
897
  int i;
4855
4856
4.48k
  for (i = 0; i < 4; ++i) {
4857
3.58k
    if (transfer[i]) {
4858
195
      delete transfer[i];
4859
195
    }
4860
3.58k
    transfer[i] = funcs[i];
4861
3.58k
  }
4862
897
}
4863
4864
38.4k
void GfxState::setLineDash(double *dash, int length, double start) {
4865
38.4k
  if (lineDash)
4866
1.33k
    gfree(lineDash);
4867
38.4k
  lineDash = dash;
4868
38.4k
  lineDashLength = length;
4869
38.4k
  lineDashStart = start;
4870
38.4k
}
4871
4872
868k
void GfxState::clearPath() {
4873
868k
  delete path;
4874
868k
  path = new GfxPath();
4875
868k
}
4876
4877
220k
void GfxState::clip() {
4878
220k
  double xMin, yMin, xMax, yMax, x, y;
4879
220k
  GfxSubpath *subpath;
4880
220k
  int i, j;
4881
4882
220k
  xMin = xMax = yMin = yMax = 0; // make gcc happy
4883
446k
  for (i = 0; i < path->getNumSubpaths(); ++i) {
4884
226k
    subpath = path->getSubpath(i);
4885
1.35M
    for (j = 0; j < subpath->getNumPoints(); ++j) {
4886
1.12M
      transform(subpath->getX(j), subpath->getY(j), &x, &y);
4887
1.12M
      if (i == 0 && j == 0) {
4888
216k
  xMin = xMax = x;
4889
216k
  yMin = yMax = y;
4890
911k
      } else {
4891
911k
  if (x < xMin) {
4892
106k
    xMin = x;
4893
805k
  } else if (x > xMax) {
4894
107k
    xMax = x;
4895
107k
  }
4896
911k
  if (y < yMin) {
4897
124k
    yMin = y;
4898
787k
  } else if (y > yMax) {
4899
38.6k
    yMax = y;
4900
38.6k
  }
4901
911k
      }
4902
1.12M
    }
4903
226k
  }
4904
220k
  if (xMin > clipXMin) {
4905
26.3k
    clipXMin = xMin;
4906
26.3k
  }
4907
220k
  if (yMin > clipYMin) {
4908
30.5k
    clipYMin = yMin;
4909
30.5k
  }
4910
220k
  if (xMax < clipXMax) {
4911
30.1k
    clipXMax = xMax;
4912
30.1k
  }
4913
220k
  if (yMax < clipYMax) {
4914
16.1k
    clipYMax = yMax;
4915
16.1k
  }
4916
220k
}
4917
4918
256
void GfxState::clipToStrokePath() {
4919
  // We compute the stroke path bbox in user space (line width and
4920
  // miter limt are handled in user space), and then transform the
4921
  // bbox to device space.  This can result in a larger-than-needed
4922
  // bbox if the matrix isn't "square", but that's ok.
4923
  //
4924
  // There are two cases for each point on the path:
4925
  // (1) miter join, under miter limit => compute the miter point
4926
  // (2) all other joins and caps => use the path point +/- 0.5 * line width
4927
256
  double uxMin = 0, uyMin = 0, uxMax = 0, uyMax = 0;
4928
256
  double w = 0.5 * lineWidth;
4929
645
  for (int i = 0; i < path->getNumSubpaths(); ++i) {
4930
389
    GfxSubpath *subpath = path->getSubpath(i);
4931
389
    int nPoints;
4932
389
    if (subpath->isClosed()) {
4933
218
      nPoints = subpath->getNumPoints() - 1;
4934
218
    } else {
4935
171
      nPoints = subpath->getNumPoints();
4936
171
    }
4937
1.87k
    for (int j = 0; j < nPoints; ++j) {
4938
1.48k
      double x1 = subpath->getX(j);
4939
1.48k
      double y1 = subpath->getY(j);
4940
1.48k
      if (i == 0 && j == 0) {
4941
256
  uxMin = uxMax = x1;
4942
256
  uyMin = uyMax = y1;
4943
256
      }
4944
1.48k
      GBool useMiter = gFalse;
4945
1.48k
      if (lineJoin == 0 &&  // miter join
4946
1.48k
    (subpath->isClosed() || (j > 0 && j < subpath->getNumPoints() - 1))) {
4947
1.14k
  double x0, y0, x2, y2;
4948
1.14k
  if (j == 0) {
4949
218
    x0 = subpath->getX(nPoints - 1);
4950
218
    y0 = subpath->getY(nPoints - 1);
4951
924
  } else {
4952
924
    x0 = subpath->getX(j - 1);
4953
924
    y0 = subpath->getY(j - 1);
4954
924
  }
4955
1.14k
  x2 = subpath->getX(j + 1);
4956
1.14k
  y2 = subpath->getY(j + 1);
4957
1.14k
  if ((fabs(x1 - x0) > 0.0001 || fabs(y1 - y0) > 0.0001) &&
4958
934
      (fabs(x2 - x1) > 0.0001 || fabs(y2 - y1) > 0.0001)) {
4959
788
    double d01 = 1 / sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
4960
788
    double ux = (x1 - x0) * d01;
4961
788
    double uy = (y1 - y0) * d01;
4962
788
    double d12 = 1 / sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
4963
788
    double vx = (x2 - x1) * d12;
4964
788
    double vy = (y2 - y1) * d12;
4965
788
    double dot = -ux * vx - uy * vy;
4966
788
    if (dot < 0.9999) {
4967
759
      double miter = sqrt(2 / (1 - dot));
4968
759
      if (miter <= miterLimit) {
4969
735
        double cross = ux * vy - uy * vx;
4970
735
        double m = sqrt(2 / (1 - dot) - 1);
4971
735
        double ax, ay;
4972
735
        if (cross >= 0) {
4973
699
    ax = x1 + w * uy;
4974
699
    ay = y1 - w * ux;
4975
699
        } else {
4976
36
    ax = x1 - w * uy;
4977
36
    ay = y1 + w * ux;
4978
36
        }
4979
735
        double mx = ax + m * w * ux;
4980
735
        double my = ay + m * w * uy;
4981
735
        if (mx < uxMin) {
4982
197
    uxMin = mx;
4983
538
        } else if (mx > uxMax) {
4984
154
    uxMax = mx;
4985
154
        }
4986
735
        if (my < uyMin) {
4987
181
    uyMin = my;
4988
554
        } else if (my > uyMax) {
4989
165
    uyMax = my;
4990
165
        }
4991
735
        useMiter = gTrue;
4992
735
      }
4993
759
    }
4994
788
  }
4995
1.14k
      }
4996
1.48k
      if (!useMiter) {
4997
749
  if (x1 - w < uxMin) {
4998
205
    uxMin = x1 - w;
4999
205
  }
5000
749
  if (x1 + w > uxMax) {
5001
222
    uxMax = x1 + w;
5002
222
  }
5003
749
  if (y1 - w < uyMin) {
5004
189
    uyMin = y1 - w;
5005
189
  }
5006
749
  if (y1 + w > uyMax) {
5007
160
    uyMax = y1 + w;
5008
160
  }
5009
749
      }
5010
1.48k
    }
5011
389
  }
5012
5013
256
  double dxMin, dyMin, dxMax, dyMax, xx, yy;
5014
256
  transform(uxMin, uyMin, &xx, &yy);
5015
256
  dxMin = dxMax = xx;
5016
256
  dyMin = dyMax = yy;
5017
256
  transform(uxMin, uyMax, &xx, &yy);
5018
256
  if (xx < dxMin) {
5019
14
    dxMin = xx;
5020
242
  } else if (xx > dxMax) {
5021
55
    dxMax = xx;
5022
55
  }
5023
256
  if (yy < dyMin) {
5024
81
    dyMin = yy;
5025
175
  } else if (yy > dyMax) {
5026
111
    dyMax = yy;
5027
111
  }
5028
256
  transform(uxMax, uyMin, &xx, &yy);
5029
256
  if (xx < dxMin) {
5030
23
    dxMin = xx;
5031
233
  } else if (xx > dxMax) {
5032
186
    dxMax = xx;
5033
186
  }
5034
256
  if (yy < dyMin) {
5035
59
    dyMin = yy;
5036
197
  } else if (yy > dyMax) {
5037
10
    dyMax = yy;
5038
10
  }
5039
256
  transform(uxMax, uyMax, &xx, &yy);
5040
256
  if (xx < dxMin) {
5041
13
    dxMin = xx;
5042
243
  } else if (xx > dxMax) {
5043
29
    dxMax = xx;
5044
29
  }
5045
256
  if (yy < dyMin) {
5046
59
    dyMin = yy;
5047
197
  } else if (yy > dyMax) {
5048
10
    dyMax = yy;
5049
10
  }
5050
5051
256
  if (dxMin > clipXMin) {
5052
106
    clipXMin = dxMin;
5053
106
  }
5054
256
  if (dyMin > clipYMin) {
5055
63
    clipYMin = dyMin;
5056
63
  }
5057
256
  if (dxMax < clipXMax) {
5058
88
    clipXMax = dxMax;
5059
88
  }
5060
256
  if (dyMax < clipYMax) {
5061
68
    clipYMax = dyMax;
5062
68
  }
5063
256
}
5064
5065
41.8k
void GfxState::clipToRect(double xMin, double yMin, double xMax, double yMax) {
5066
41.8k
  double x, y, xMin1, yMin1, xMax1, yMax1;
5067
5068
41.8k
  transform(xMin, yMin, &x, &y);
5069
41.8k
  xMin1 = xMax1 = x;
5070
41.8k
  yMin1 = yMax1 = y;
5071
41.8k
  transform(xMax, yMin, &x, &y);
5072
41.8k
  if (x < xMin1) {
5073
19.7k
    xMin1 = x;
5074
22.1k
  } else if (x > xMax1) {
5075
4.02k
    xMax1 = x;
5076
4.02k
  }
5077
41.8k
  if (y < yMin1) {
5078
3.95k
    yMin1 = y;
5079
37.9k
  } else if (y > yMax1) {
5080
2.14k
    yMax1 = y;
5081
2.14k
  }
5082
41.8k
  transform(xMax, yMax, &x, &y);
5083
41.8k
  if (x < xMin1) {
5084
695
    xMin1 = x;
5085
41.1k
  } else if (x > xMax1) {
5086
2.63k
    xMax1 = x;
5087
2.63k
  }
5088
41.8k
  if (y < yMin1) {
5089
7.10k
    yMin1 = y;
5090
34.7k
  } else if (y > yMax1) {
5091
3.24k
    yMax1 = y;
5092
3.24k
  }
5093
41.8k
  transform(xMin, yMax, &x, &y);
5094
41.8k
  if (x < xMin1) {
5095
36
    xMin1 = x;
5096
41.8k
  } else if (x > xMax1) {
5097
38
    xMax1 = x;
5098
38
  }
5099
41.8k
  if (y < yMin1) {
5100
333
    yMin1 = y;
5101
41.5k
  } else if (y > yMax1) {
5102
139
    yMax1 = y;
5103
139
  }
5104
5105
41.8k
  if (xMin1 > clipXMin) {
5106
599
    clipXMin = xMin1;
5107
599
  }
5108
41.8k
  if (yMin1 > clipYMin) {
5109
3.13k
    clipYMin = yMin1;
5110
3.13k
  }
5111
41.8k
  if (xMax1 < clipXMax) {
5112
400
    clipXMax = xMax1;
5113
400
  }
5114
41.8k
  if (yMax1 < clipYMax) {
5115
12.1k
    clipYMax = yMax1;
5116
12.1k
  }
5117
41.8k
}
5118
5119
315k
void GfxState::textShift(double tx, double ty) {
5120
315k
  double dx, dy;
5121
5122
315k
  textTransformDelta(tx, ty, &dx, &dy);
5123
315k
  curX += dx;
5124
315k
  curY += dy;
5125
315k
}
5126
5127
4.40M
void GfxState::shift(double dx, double dy) {
5128
4.40M
  curX += dx;
5129
4.40M
  curY += dy;
5130
4.40M
}
5131
5132
640k
GfxState *GfxState::save() {
5133
640k
  GfxState *newState;
5134
5135
640k
  newState = copy();
5136
640k
  newState->saved = this;
5137
640k
  return newState;
5138
640k
}
5139
5140
747k
GfxState *GfxState::restore() {
5141
747k
  GfxState *oldState;
5142
5143
747k
  if (saved) {
5144
639k
    oldState = saved;
5145
5146
    // these attributes aren't saved/restored by the q/Q operators
5147
639k
    oldState->path = path;
5148
639k
    oldState->curX = curX;
5149
639k
    oldState->curY = curY;
5150
639k
    oldState->lineX = lineX;
5151
639k
    oldState->lineY = lineY;
5152
5153
639k
    path = NULL;
5154
639k
    saved = NULL;
5155
639k
    delete this;
5156
5157
639k
  } else {
5158
108k
    oldState = this;
5159
108k
  }
5160
5161
747k
  return oldState;
5162
747k
}
5163
5164
6.16k
GBool GfxState::parseBlendMode(Object *obj, GfxBlendMode *mode) {
5165
6.16k
  Object obj2;
5166
6.16k
  int i, j;
5167
5168
6.16k
  if (obj->isName()) {
5169
37.1k
    for (i = 0; i < nGfxBlendModeNames; ++i) {
5170
36.6k
      if (!strcmp(obj->getName(), gfxBlendModeNames[i].name)) {
5171
4.68k
  *mode = gfxBlendModeNames[i].mode;
5172
4.68k
  return gTrue;
5173
4.68k
      }
5174
36.6k
    }
5175
440
    return gFalse;
5176
5.12k
  } else if (obj->isArray()) {
5177
931
    for (i = 0; i < obj->arrayGetLength(); ++i) {
5178
928
      obj->arrayGet(i, &obj2);
5179
928
      if (!obj2.isName()) {
5180
61
  obj2.free();
5181
61
  return gFalse;
5182
61
      }
5183
9.85k
      for (j = 0; j < nGfxBlendModeNames; ++j) {
5184
9.80k
  if (!strcmp(obj2.getName(), gfxBlendModeNames[j].name)) {
5185
822
    obj2.free();
5186
822
    *mode = gfxBlendModeNames[j].mode;
5187
822
    return gTrue;
5188
822
  }
5189
9.80k
      }
5190
45
      obj2.free();
5191
45
    }
5192
3
    *mode = gfxBlendNormal;
5193
3
    return gTrue;
5194
886
  } else {
5195
153
    return gFalse;
5196
153
  }
5197
6.16k
}