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