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