27static inline double clip01(
double x) {
28 return (x < 0) ? 0 : ((x > 1) ? 1 : x);
35GfxColorSpace::GfxColorSpace() {
38GfxColorSpace::~GfxColorSpace() {
41GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
46 if (csObj->isName()) {
47 if (csObj->isName(
"DeviceGray") || csObj->isName(
"G")) {
48 cs =
new GfxDeviceGrayColorSpace();
49 }
else if (csObj->isName(
"DeviceRGB") || csObj->isName(
"RGB")) {
50 cs =
new GfxDeviceRGBColorSpace();
51 }
else if (csObj->isName(
"DeviceCMYK") || csObj->isName(
"CMYK")) {
52 cs =
new GfxDeviceCMYKColorSpace();
53 }
else if (csObj->isName(
"Pattern")) {
54 cs =
new GfxPatternColorSpace(NULL);
56 error(-1,
"Bad color space '%s'", csObj->getName());
58 }
else if (csObj->isArray()) {
59 csObj->arrayGet(0, &obj1);
60 if (obj1.isName(
"DeviceGray") || obj1.isName(
"G")) {
61 cs =
new GfxDeviceGrayColorSpace();
62 }
else if (obj1.isName(
"DeviceRGB") || obj1.isName(
"RGB")) {
63 cs =
new GfxDeviceRGBColorSpace();
64 }
else if (obj1.isName(
"DeviceCMYK") || obj1.isName(
"CMYK")) {
65 cs =
new GfxDeviceCMYKColorSpace();
66 }
else if (obj1.isName(
"CalGray")) {
67 cs = GfxCalGrayColorSpace::parse(csObj->getArray());
68 }
else if (obj1.isName(
"CalRGB")) {
69 cs = GfxCalRGBColorSpace::parse(csObj->getArray());
70 }
else if (obj1.isName(
"Lab")) {
71 cs = GfxLabColorSpace::parse(csObj->getArray());
72 }
else if (obj1.isName(
"ICCBased")) {
73 cs = GfxICCBasedColorSpace::parse(csObj->getArray());
74 }
else if (obj1.isName(
"Indexed") || obj1.isName(
"I")) {
75 cs = GfxIndexedColorSpace::parse(csObj->getArray());
76 }
else if (obj1.isName(
"Separation")) {
77 cs = GfxSeparationColorSpace::parse(csObj->getArray());
78 }
else if (obj1.isName(
"DeviceN")) {
79 cs = GfxDeviceNColorSpace::parse(csObj->getArray());
80 }
else if (obj1.isName(
"Pattern")) {
81 cs = GfxPatternColorSpace::parse(csObj->getArray());
83 error(-1,
"Bad color space '%s'", csObj->getName());
87 error(-1,
"Bad color space - expected name or array");
92void GfxColorSpace::getDefaultRanges(
double *decodeLow,
double *decodeRange,
96 for (i = 0; i < getNComps(); ++i) {
106GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() {
109GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() {
112GfxColorSpace *GfxDeviceGrayColorSpace::copy()
const {
113 return new GfxDeviceGrayColorSpace();
116void GfxDeviceGrayColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
117 *gray = clip01(color->c[0]);
120void GfxDeviceGrayColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
121 rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
124void GfxDeviceGrayColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
125 cmyk->c = cmyk->m = cmyk->y = 0;
126 cmyk->k = clip01(1 - color->c[0]);
133GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
134 whiteX = whiteY = whiteZ = 1;
135 blackX = blackY = blackZ = 0;
139GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
142GfxColorSpace *GfxCalGrayColorSpace::copy()
const {
143 GfxCalGrayColorSpace *cs;
145 cs =
new GfxCalGrayColorSpace();
156GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
157 GfxCalGrayColorSpace *cs;
158 Object obj1, obj2, obj3;
161 if (!obj1.isDict()) {
162 error(-1,
"Bad CalGray color space");
166 cs =
new GfxCalGrayColorSpace();
167 if (obj1.dictLookup(
"WhitePoint", &obj2)->isArray() &&
168 obj2.arrayGetLength() == 3) {
169 obj2.arrayGet(0, &obj3);
170 cs->whiteX = obj3.getNum();
172 obj2.arrayGet(1, &obj3);
173 cs->whiteY = obj3.getNum();
175 obj2.arrayGet(2, &obj3);
176 cs->whiteZ = obj3.getNum();
180 if (obj1.dictLookup(
"BlackPoint", &obj2)->isArray() &&
181 obj2.arrayGetLength() == 3) {
182 obj2.arrayGet(0, &obj3);
183 cs->blackX = obj3.getNum();
185 obj2.arrayGet(1, &obj3);
186 cs->blackY = obj3.getNum();
188 obj2.arrayGet(2, &obj3);
189 cs->blackZ = obj3.getNum();
193 if (obj1.dictLookup(
"Gamma", &obj2)->isNum()) {
194 cs->gamma = obj2.getNum();
201void GfxCalGrayColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
202 *gray = clip01(color->c[0]);
205void GfxCalGrayColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
206 rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
209void GfxCalGrayColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
210 cmyk->c = cmyk->m = cmyk->y = 0;
211 cmyk->k = clip01(1 - color->c[0]);
218GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() {
221GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() {
224GfxColorSpace *GfxDeviceRGBColorSpace::copy()
const {
225 return new GfxDeviceRGBColorSpace();
228void GfxDeviceRGBColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
229 *gray = clip01(0.299 * color->c[0] +
230 0.587 * color->c[1] +
231 0.114 * color->c[2]);
234void GfxDeviceRGBColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
235 rgb->r = clip01(color->c[0]);
236 rgb->g = clip01(color->c[1]);
237 rgb->b = clip01(color->c[2]);
240void GfxDeviceRGBColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
243 c = clip01(1 - color->c[0]);
244 m = clip01(1 - color->c[1]);
245 y = clip01(1 - color->c[2]);
263GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
264 whiteX = whiteY = whiteZ = 1;
265 blackX = blackY = blackZ = 0;
266 gammaR = gammaG = gammaB = 1;
267 mat[0] = 1; mat[1] = 0; mat[2] = 0;
268 mat[3] = 0; mat[4] = 1; mat[5] = 0;
269 mat[6] = 0; mat[7] = 0; mat[8] = 1;
272GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
275GfxColorSpace *GfxCalRGBColorSpace::copy()
const {
276 GfxCalRGBColorSpace *cs;
279 cs =
new GfxCalRGBColorSpace();
289 for (i = 0; i < 9; ++i) {
295GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
296 GfxCalRGBColorSpace *cs;
297 Object obj1, obj2, obj3;
301 if (!obj1.isDict()) {
302 error(-1,
"Bad CalRGB color space");
306 cs =
new GfxCalRGBColorSpace();
307 if (obj1.dictLookup(
"WhitePoint", &obj2)->isArray() &&
308 obj2.arrayGetLength() == 3) {
309 obj2.arrayGet(0, &obj3);
310 cs->whiteX = obj3.getNum();
312 obj2.arrayGet(1, &obj3);
313 cs->whiteY = obj3.getNum();
315 obj2.arrayGet(2, &obj3);
316 cs->whiteZ = obj3.getNum();
320 if (obj1.dictLookup(
"BlackPoint", &obj2)->isArray() &&
321 obj2.arrayGetLength() == 3) {
322 obj2.arrayGet(0, &obj3);
323 cs->blackX = obj3.getNum();
325 obj2.arrayGet(1, &obj3);
326 cs->blackY = obj3.getNum();
328 obj2.arrayGet(2, &obj3);
329 cs->blackZ = obj3.getNum();
333 if (obj1.dictLookup(
"Gamma", &obj2)->isArray() &&
334 obj2.arrayGetLength() == 3) {
335 obj2.arrayGet(0, &obj3);
336 cs->gammaR = obj3.getNum();
338 obj2.arrayGet(1, &obj3);
339 cs->gammaG = obj3.getNum();
341 obj2.arrayGet(2, &obj3);
342 cs->gammaB = obj3.getNum();
346 if (obj1.dictLookup(
"Matrix", &obj2)->isArray() &&
347 obj2.arrayGetLength() == 9) {
348 for (i = 0; i < 9; ++i) {
349 obj2.arrayGet(i, &obj3);
350 cs->mat[i] = obj3.getNum();
359void GfxCalRGBColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
360 *gray = clip01(0.299 * color->c[0] +
361 0.587 * color->c[1] +
362 0.114 * color->c[2]);
365void GfxCalRGBColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
366 rgb->r = clip01(color->c[0]);
367 rgb->g = clip01(color->c[1]);
368 rgb->b = clip01(color->c[2]);
371void GfxCalRGBColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
374 c = clip01(1 - color->c[0]);
375 m = clip01(1 - color->c[1]);
376 y = clip01(1 - color->c[2]);
394GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
397GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
400GfxColorSpace *GfxDeviceCMYKColorSpace::copy()
const {
401 return new GfxDeviceCMYKColorSpace();
404void GfxDeviceCMYKColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
405 *gray = clip01(1 - color->c[3]
406 - 0.299 * color->c[0]
407 - 0.587 * color->c[1]
408 - 0.114 * color->c[2]);
411void GfxDeviceCMYKColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
412 double c, m, y, aw, ac, am, ay, ar, ag, ab;
414 c = clip01(color->c[0] + color->c[3]);
415 m = clip01(color->c[1] + color->c[3]);
416 y = clip01(color->c[2] + color->c[3]);
417 aw = (1-c) * (1-m) * (1-y);
418 ac = c * (1-m) * (1-y);
419 am = (1-c) * m * (1-y);
420 ay = (1-c) * (1-m) * y;
424 rgb->r = clip01(aw + 0.9137*am + 0.9961*ay + 0.9882*ar);
425 rgb->g = clip01(aw + 0.6196*ac + ay + 0.5176*ag);
426 rgb->b = clip01(aw + 0.7804*ac + 0.5412*am + 0.0667*ar + 0.2118*ag +
430void GfxDeviceCMYKColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
431 cmyk->c = clip01(color->c[0]);
432 cmyk->m = clip01(color->c[1]);
433 cmyk->y = clip01(color->c[2]);
434 cmyk->k = clip01(color->c[3]);
443static double xyzrgb[3][3] = {
444 { 3.240449, -1.537136, -0.498531 },
445 { -0.969265, 1.876011, 0.041556 },
446 { 0.055643, -0.204026, 1.057229 }
449GfxLabColorSpace::GfxLabColorSpace() {
450 whiteX = whiteY = whiteZ = 1;
451 blackX = blackY = blackZ = 0;
456GfxLabColorSpace::~GfxLabColorSpace() {
459GfxColorSpace *GfxLabColorSpace::copy()
const {
460 GfxLabColorSpace *cs;
462 cs =
new GfxLabColorSpace();
479GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
480 GfxLabColorSpace *cs;
481 Object obj1, obj2, obj3;
484 if (!obj1.isDict()) {
485 error(-1,
"Bad Lab color space");
489 cs =
new GfxLabColorSpace();
490 if (obj1.dictLookup(
"WhitePoint", &obj2)->isArray() &&
491 obj2.arrayGetLength() == 3) {
492 obj2.arrayGet(0, &obj3);
493 cs->whiteX = obj3.getNum();
495 obj2.arrayGet(1, &obj3);
496 cs->whiteY = obj3.getNum();
498 obj2.arrayGet(2, &obj3);
499 cs->whiteZ = obj3.getNum();
503 if (obj1.dictLookup(
"BlackPoint", &obj2)->isArray() &&
504 obj2.arrayGetLength() == 3) {
505 obj2.arrayGet(0, &obj3);
506 cs->blackX = obj3.getNum();
508 obj2.arrayGet(1, &obj3);
509 cs->blackY = obj3.getNum();
511 obj2.arrayGet(2, &obj3);
512 cs->blackZ = obj3.getNum();
516 if (obj1.dictLookup(
"Range", &obj2)->isArray() &&
517 obj2.arrayGetLength() == 4) {
518 obj2.arrayGet(0, &obj3);
519 cs->aMin = obj3.getNum();
521 obj2.arrayGet(1, &obj3);
522 cs->aMax = obj3.getNum();
524 obj2.arrayGet(2, &obj3);
525 cs->bMin = obj3.getNum();
527 obj2.arrayGet(3, &obj3);
528 cs->bMax = obj3.getNum();
534 cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
535 xyzrgb[0][1] * cs->whiteY +
536 xyzrgb[0][2] * cs->whiteZ);
537 cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
538 xyzrgb[1][1] * cs->whiteY +
539 xyzrgb[1][2] * cs->whiteZ);
540 cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
541 xyzrgb[2][1] * cs->whiteY +
542 xyzrgb[2][2] * cs->whiteZ);
547void GfxLabColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
551 *gray = clip01(0.299 * rgb.r +
556void GfxLabColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
562 t1 = (color->c[0] + 16) / 116;
563 t2 = t1 + color->c[1] / 500;
564 if (t2 >= (6.0 / 29.0)) {
567 X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
570 if (t1 >= (6.0 / 29.0)) {
573 Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
576 t2 = t1 - color->c[2] / 200;
577 if (t2 >= (6.0 / 29.0)) {
580 Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
585 r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
586 g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
587 b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
588 rgb->r = pow(clip01(r * kr), 0.5);
589 rgb->g = pow(clip01(g * kg), 0.5);
590 rgb->b = pow(clip01(b * kb), 0.5);
593void GfxLabColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
598 c = clip01(1 - rgb.r);
599 m = clip01(1 - rgb.g);
600 y = clip01(1 - rgb.b);
614void GfxLabColorSpace::getDefaultRanges(
double *decodeLow,
double *decodeRange,
617 decodeRange[0] = 100;
619 decodeRange[1] = aMax - aMin;
621 decodeRange[2] = bMax - bMin;
628GfxICCBasedColorSpace::GfxICCBasedColorSpace(
int nCompsA, GfxColorSpace *altA,
629 const Ref *iccProfileStreamA) {
632 iccProfileStream = *iccProfileStreamA;
633 rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
634 rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
637GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
641GfxColorSpace *GfxICCBasedColorSpace::copy()
const {
642 GfxICCBasedColorSpace *cs;
645 cs =
new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
646 for (i = 0; i < 4; ++i) {
647 cs->rangeMin[i] = rangeMin[i];
648 cs->rangeMax[i] = rangeMax[i];
653GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
654 GfxICCBasedColorSpace *cs;
655 Ref iccProfileStreamA;
659 Object obj1, obj2, obj3;
662 arr->getNF(1, &obj1);
664 iccProfileStreamA = obj1.getRef();
666 iccProfileStreamA.num = 0;
667 iccProfileStreamA.gen = 0;
671 if (!obj1.isStream()) {
672 error(-1,
"Bad ICCBased color space (stream)");
676 dict = obj1.streamGetDict();
677 if (!dict->lookup(
"N", &obj2)->isInt()) {
678 error(-1,
"Bad ICCBased color space (N)");
683 nCompsA = obj2.getInt();
685 if (nCompsA > gfxColorMaxComps) {
686 error(-1,
"ICCBased color space with too many (%d > %d) components",
687 nCompsA, gfxColorMaxComps);
688 nCompsA = gfxColorMaxComps;
690 if (dict->lookup(
"Alternate", &obj2)->isNull() ||
691 !(altA = GfxColorSpace::parse(&obj2))) {
694 altA =
new GfxDeviceGrayColorSpace();
697 altA =
new GfxDeviceRGBColorSpace();
700 altA =
new GfxDeviceCMYKColorSpace();
703 error(-1,
"Bad ICCBased color space - invalid N");
710 cs =
new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA);
711 if (dict->lookup(
"Range", &obj2)->isArray() &&
712 obj2.arrayGetLength() == 2 * nCompsA) {
713 for (i = 0; i < nCompsA; ++i) {
714 obj2.arrayGet(2*i, &obj3);
715 cs->rangeMin[i] = obj3.getNum();
717 obj2.arrayGet(2*i+1, &obj3);
718 cs->rangeMax[i] = obj3.getNum();
727void GfxICCBasedColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
728 alt->getGray(color, gray);
731void GfxICCBasedColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
732 alt->getRGB(color, rgb);
735void GfxICCBasedColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
736 alt->getCMYK(color, cmyk);
739void GfxICCBasedColorSpace::getDefaultRanges(
double *decodeLow,
744 for (i = 0; i < nComps; ++i) {
745 decodeLow[i] = rangeMin[i];
746 decodeRange[i] = rangeMax[i] - rangeMin[i];
754GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA,
757 indexHigh = indexHighA;
758 lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
762GfxIndexedColorSpace::~GfxIndexedColorSpace() {
767GfxColorSpace *GfxIndexedColorSpace::copy()
const {
768 GfxIndexedColorSpace *cs;
770 cs =
new GfxIndexedColorSpace(base->copy(), indexHigh);
771 memcpy(cs->lookup, lookup,
772 (indexHigh + 1) * base->getNComps() *
sizeof(Guchar));
776GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
777 GfxIndexedColorSpace *cs;
778 GfxColorSpace *baseA;
785 if (arr->getLength() != 4) {
786 error(-1,
"Bad Indexed color space");
790 if (!(baseA = GfxColorSpace::parse(&obj1))) {
791 error(-1,
"Bad Indexed color space (base color space)");
795 if (!arr->get(2, &obj1)->isInt()) {
796 error(-1,
"Bad Indexed color space (hival)");
799 indexHighA = obj1.getInt();
801 cs =
new GfxIndexedColorSpace(baseA, indexHighA);
803 n = baseA->getNComps();
804 if (obj1.isStream()) {
806 for (i = 0; i <= indexHighA; ++i) {
807 for (j = 0; j < n; ++j) {
808 if ((x = obj1.streamGetChar()) == EOF) {
809 error(-1,
"Bad Indexed color space (lookup table stream too short)");
812 cs->lookup[i*n + j] = (Guchar)x;
816 }
else if (obj1.isString()) {
817 if (obj1.getString()->getLength() < (indexHighA + 1) * n) {
818 error(-1,
"Bad Indexed color space (lookup table string too short)");
821 s = obj1.getString()->getCString();
822 for (i = 0; i <= indexHighA; ++i) {
823 for (j = 0; j < n; ++j) {
824 cs->lookup[i*n + j] = (Guchar)*s++;
828 error(-1,
"Bad Indexed color space (lookup table)");
842void GfxIndexedColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
845 double low[gfxColorMaxComps], range[gfxColorMaxComps];
848 n = base->getNComps();
849 base->getDefaultRanges(low, range, indexHigh);
850 p = &lookup[(int)(color->c[0] + 0.5) * n];
851 for (i = 0; i < n; ++i) {
852 color2.c[i] = low[i] + (p[i] / 255.0) * range[i];
854 base->getGray(&color2, gray);
857void GfxIndexedColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
860 double low[gfxColorMaxComps], range[gfxColorMaxComps];
863 n = base->getNComps();
864 base->getDefaultRanges(low, range, indexHigh);
865 p = &lookup[(int)(color->c[0] + 0.5) * n];
866 for (i = 0; i < n; ++i) {
867 color2.c[i] = low[i] + (p[i] / 255.0) * range[i];
869 base->getRGB(&color2, rgb);
872void GfxIndexedColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
875 double low[gfxColorMaxComps], range[gfxColorMaxComps];
878 n = base->getNComps();
879 base->getDefaultRanges(low, range, indexHigh);
880 p = &lookup[(int)(color->c[0] + 0.5) * n];
881 for (i = 0; i < n; ++i) {
882 color2.c[i] = low[i] + (p[i] / 255.0) * range[i];
884 base->getCMYK(&color2, cmyk);
887void GfxIndexedColorSpace::getDefaultRanges(
double *decodeLow,
889 int maxImgPixel)
const {
891 decodeRange[0] = maxImgPixel;
898GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
906GfxSeparationColorSpace::~GfxSeparationColorSpace() {
912GfxColorSpace *GfxSeparationColorSpace::copy()
const {
913 return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
917GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
918 GfxSeparationColorSpace *cs;
924 if (arr->getLength() != 4) {
925 error(-1,
"Bad Separation color space");
928 if (!arr->get(1, &obj1)->isName()) {
929 error(-1,
"Bad Separation color space (name)");
932 nameA =
new GString(obj1.getName());
935 if (!(altA = GfxColorSpace::parse(&obj1))) {
936 error(-1,
"Bad Separation color space (alternate color space)");
941 if (!(funcA = Function::parse(&obj1))) {
945 cs =
new GfxSeparationColorSpace(nameA, altA, funcA);
958void GfxSeparationColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
961 func->transform(color->c, color2.c);
962 alt->getGray(&color2, gray);
965void GfxSeparationColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
968 func->transform(color->c, color2.c);
969 alt->getRGB(&color2, rgb);
972void GfxSeparationColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
975 func->transform(color->c, color2.c);
976 alt->getCMYK(&color2, cmyk);
983GfxDeviceNColorSpace::GfxDeviceNColorSpace(
int nCompsA,
991GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
994 for (i = 0; i < nComps; ++i) {
1001GfxColorSpace *GfxDeviceNColorSpace::copy()
const {
1002 GfxDeviceNColorSpace *cs;
1005 cs =
new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
1006 for (i = 0; i < nComps; ++i) {
1007 cs->names[i] = names[i]->copy();
1013GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
1014 GfxDeviceNColorSpace *cs;
1016 GString *namesA[gfxColorMaxComps];
1017 GfxColorSpace *altA;
1022 if (arr->getLength() != 4 && arr->getLength() != 5) {
1023 error(-1,
"Bad DeviceN color space");
1026 if (!arr->get(1, &obj1)->isArray()) {
1027 error(-1,
"Bad DeviceN color space (names)");
1030 nCompsA = obj1.arrayGetLength();
1031 if (nCompsA > gfxColorMaxComps) {
1032 error(-1,
"DeviceN color space with too many (%d > %d) components",
1033 nCompsA, gfxColorMaxComps);
1034 nCompsA = gfxColorMaxComps;
1036 for (i = 0; i < nCompsA; ++i) {
1037 if (!obj1.arrayGet(i, &obj2)->isName()) {
1038 error(-1,
"Bad DeviceN color space (names)");
1042 namesA[i] =
new GString(obj2.getName());
1047 if (!(altA = GfxColorSpace::parse(&obj1))) {
1048 error(-1,
"Bad DeviceN color space (alternate color space)");
1053 if (!(funcA = Function::parse(&obj1))) {
1057 cs =
new GfxDeviceNColorSpace(nCompsA, altA, funcA);
1058 for (i = 0; i < nCompsA; ++i) {
1059 cs->names[i] = namesA[i];
1066 for (i = 0; i < nCompsA; ++i) {
1075void GfxDeviceNColorSpace::getGray(
const GfxColor *color,
double *gray)
const {
1078 func->transform(color->c, color2.c);
1079 alt->getGray(&color2, gray);
1082void GfxDeviceNColorSpace::getRGB(
const GfxColor *color, GfxRGB *rgb)
const {
1085 func->transform(color->c, color2.c);
1086 alt->getRGB(&color2, rgb);
1089void GfxDeviceNColorSpace::getCMYK(
const GfxColor *color, GfxCMYK *cmyk)
const {
1092 func->transform(color->c, color2.c);
1093 alt->getCMYK(&color2, cmyk);
1100GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) {
1104GfxPatternColorSpace::~GfxPatternColorSpace() {
1110GfxColorSpace *GfxPatternColorSpace::copy()
const {
1111 return new GfxPatternColorSpace(under ? under->copy() :
1112 (GfxColorSpace *)NULL);
1115GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
1116 GfxPatternColorSpace *cs;
1117 GfxColorSpace *underA;
1120 if (arr->getLength() != 1 && arr->getLength() != 2) {
1121 error(-1,
"Bad Pattern color space");
1125 if (arr->getLength() == 2) {
1127 if (!(underA = GfxColorSpace::parse(&obj1))) {
1128 error(-1,
"Bad Pattern color space (underlying color space)");
1134 cs =
new GfxPatternColorSpace(underA);
1138void GfxPatternColorSpace::getGray(
const GfxColor *,
double *gray)
const {
1142void GfxPatternColorSpace::getRGB(
const GfxColor *, GfxRGB *rgb)
const {
1143 rgb->r = rgb->g = rgb->b = 0;
1146void GfxPatternColorSpace::getCMYK(
const GfxColor *, GfxCMYK *cmyk)
const {
1147 cmyk->c = cmyk->m = cmyk->y = 0;
1155GfxPattern::GfxPattern(
int typeA) {
1159GfxPattern::~GfxPattern() {
1162GfxPattern *GfxPattern::parse(Object *obj) {
1163 GfxPattern *pattern;
1168 if (obj->isStream()) {
1169 dict = obj->streamGetDict();
1170 dict->lookup(
"PatternType", &obj1);
1171 if (obj1.isInt() && obj1.getInt() == 1) {
1172 pattern =
new GfxTilingPattern(dict, obj);
1183GfxTilingPattern::GfxTilingPattern(Dict *streamDict, Object *stream):
1189 if (streamDict->lookup(
"PaintType", &obj1)->isInt()) {
1190 paintType = obj1.getInt();
1193 error(-1,
"Invalid or missing PaintType in pattern");
1196 if (streamDict->lookup(
"TilingType", &obj1)->isInt()) {
1197 tilingType = obj1.getInt();
1200 error(-1,
"Invalid or missing TilingType in pattern");
1203 bbox[0] = bbox[1] = 0;
1204 bbox[2] = bbox[3] = 1;
1205 if (streamDict->lookup(
"BBox", &obj1)->isArray() &&
1206 obj1.arrayGetLength() == 4) {
1207 for (i = 0; i < 4; ++i) {
1208 if (obj1.arrayGet(i, &obj2)->isNum()) {
1209 bbox[i] = obj2.getNum();
1214 error(-1,
"Invalid or missing BBox in pattern");
1217 if (streamDict->lookup(
"XStep", &obj1)->isNum()) {
1218 xStep = obj1.getNum();
1221 error(-1,
"Invalid or missing XStep in pattern");
1224 if (streamDict->lookup(
"YStep", &obj1)->isNum()) {
1225 yStep = obj1.getNum();
1228 error(-1,
"Invalid or missing YStep in pattern");
1231 if (!streamDict->lookup(
"Resources", &resDict)->isDict()) {
1234 error(-1,
"Invalid or missing Resources in pattern");
1236 matrix[0] = 1; matrix[1] = 0;
1237 matrix[2] = 0; matrix[3] = 1;
1238 matrix[4] = 0; matrix[5] = 0;
1239 if (streamDict->lookup(
"Matrix", &obj1)->isArray() &&
1240 obj1.arrayGetLength() == 6) {
1241 for (i = 0; i < 6; ++i) {
1242 if (obj1.arrayGet(i, &obj2)->isNum()) {
1243 matrix[i] = obj2.getNum();
1249 stream->copy(&contentStream);
1252GfxTilingPattern::~GfxTilingPattern() {
1254 contentStream.free();
1257GfxPattern *GfxTilingPattern::copy() {
1258 return new GfxTilingPattern(
this);
1261GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
1264 memcpy(
this, pat,
sizeof(GfxTilingPattern));
1265 pat->resDict.copy(&resDict);
1266 pat->contentStream.copy(&contentStream);
1273GfxShading::GfxShading() {
1276GfxShading::~GfxShading() {
1280GfxShading *GfxShading::parse(Object *obj) {
1281 GfxShading *shading;
1283 GfxColorSpace *colorSpaceA;
1284 GfxColor backgroundA;
1285 GBool hasBackgroundA;
1286 double xMinA, yMinA, xMaxA, yMaxA;
1292 if (obj->isDict()) {
1294 if (!obj->dictLookup(
"ShadingType", &obj1)->isInt()) {
1295 error(-1,
"Invalid ShadingType in shading dictionary");
1299 typeA = obj1.getInt();
1302 obj->dictLookup(
"ColorSpace", &obj1);
1303 if (!(colorSpaceA = GfxColorSpace::parse(&obj1))) {
1304 error(-1,
"Bad color space in shading dictionary");
1310 for (i = 0; i < gfxColorMaxComps; ++i) {
1311 backgroundA.c[i] = 0;
1313 hasBackgroundA = gFalse;
1314 if (obj->dictLookup(
"Background", &obj1)->isArray()) {
1315 if (obj1.arrayGetLength() == colorSpaceA->getNComps()) {
1316 hasBackgroundA = gTrue;
1317 for (i = 0; i < colorSpaceA->getNComps(); ++i) {
1318 backgroundA.c[i] = obj1.arrayGet(i, &obj2)->getNum();
1322 error(-1,
"Bad Background in shading dictionary");
1327 xMinA = yMinA = xMaxA = yMaxA = 0;
1329 if (obj->dictLookup(
"BBox", &obj1)->isArray()) {
1330 if (obj1.arrayGetLength() == 4) {
1332 xMinA = obj1.arrayGet(0, &obj2)->getNum();
1334 yMinA = obj1.arrayGet(1, &obj2)->getNum();
1336 xMaxA = obj1.arrayGet(2, &obj2)->getNum();
1338 yMaxA = obj1.arrayGet(3, &obj2)->getNum();
1341 error(-1,
"Bad BBox in shading dictionary");
1348 shading = GfxAxialShading::parse(obj->getDict());
1351 shading = GfxRadialShading::parse(obj->getDict());
1354 error(-1,
"Unimplemented shading type %d", typeA);
1359 shading->type = typeA;
1360 shading->colorSpace = colorSpaceA;
1361 shading->background = backgroundA;
1362 shading->hasBackground = hasBackgroundA;
1363 shading->xMin = xMinA;
1364 shading->yMin = yMinA;
1365 shading->xMax = xMaxA;
1366 shading->yMax = yMaxA;
1367 shading->hasBBox = hasBBoxA;
1383GfxAxialShading::GfxAxialShading(
double x0A,
double y0A,
1384 double x1A,
double y1A,
1385 double t0A,
double t1A,
1386 Function **funcsA,
int nFuncsA,
1387 GBool extend0A, GBool extend1A) {
1397 for (i = 0; i < nFuncs; ++i) {
1398 funcs[i] = funcsA[i];
1404GfxAxialShading::~GfxAxialShading() {
1407 for (i = 0; i < nFuncs; ++i) {
1412GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
1413 double x0A, y0A, x1A, y1A;
1415 Function *funcsA[gfxColorMaxComps];
1417 GBool extend0A, extend1A;
1421 x0A = y0A = x1A = y1A = 0;
1422 if (dict->lookup(
"Coords", &obj1)->isArray() &&
1423 obj1.arrayGetLength() == 4) {
1424 x0A = obj1.arrayGet(0, &obj2)->getNum();
1426 y0A = obj1.arrayGet(1, &obj2)->getNum();
1428 x1A = obj1.arrayGet(2, &obj2)->getNum();
1430 y1A = obj1.arrayGet(3, &obj2)->getNum();
1433 error(-1,
"Missing or invalid Coords in shading dictionary");
1440 if (dict->lookup(
"Domain", &obj1)->isArray() &&
1441 obj1.arrayGetLength() == 2) {
1442 t0A = obj1.arrayGet(0, &obj2)->getNum();
1444 t1A = obj1.arrayGet(1, &obj2)->getNum();
1449 dict->lookup(
"Function", &obj1);
1450 if (obj1.isArray()) {
1451 nFuncsA = obj1.arrayGetLength();
1452 for (i = 0; i < nFuncsA; ++i) {
1453 obj1.arrayGet(i, &obj2);
1454 if (!(funcsA[i] = Function::parse(&obj2))) {
1463 if (!(funcsA[0] = Function::parse(&obj1))) {
1470 extend0A = extend1A = gFalse;
1471 if (dict->lookup(
"Extend", &obj1)->isArray() &&
1472 obj1.arrayGetLength() == 2) {
1473 extend0A = obj1.arrayGet(0, &obj2)->getBool();
1475 extend1A = obj1.arrayGet(1, &obj2)->getBool();
1480 return new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
1481 funcsA, nFuncsA, extend0A, extend1A);
1487void GfxAxialShading::getColor(
double t, GfxColor *color) {
1490 for (i = 0; i < nFuncs; ++i) {
1491 funcs[i]->transform(&t, &color->c[i]);
1499GfxRadialShading::GfxRadialShading(
double x0A,
double y0A,
double r0A,
1500 double x1A,
double y1A,
double r1A,
1501 double t0A,
double t1A,
1502 Function **funcsA,
int nFuncsA,
1503 GBool extend0A, GBool extend1A) {
1515 for (i = 0; i < nFuncs; ++i) {
1516 funcs[i] = funcsA[i];
1522GfxRadialShading::~GfxRadialShading() {
1525 for (i = 0; i < nFuncs; ++i) {
1530GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
1531 double x0A, y0A, r0A, x1A, y1A, r1A;
1533 Function *funcsA[gfxColorMaxComps];
1535 GBool extend0A, extend1A;
1539 x0A = y0A = r0A = x1A = y1A = r1A = 0;
1540 if (dict->lookup(
"Coords", &obj1)->isArray() &&
1541 obj1.arrayGetLength() == 6) {
1542 x0A = obj1.arrayGet(0, &obj2)->getNum();
1544 y0A = obj1.arrayGet(1, &obj2)->getNum();
1546 r0A = obj1.arrayGet(2, &obj2)->getNum();
1548 x1A = obj1.arrayGet(3, &obj2)->getNum();
1550 y1A = obj1.arrayGet(4, &obj2)->getNum();
1552 r1A = obj1.arrayGet(5, &obj2)->getNum();
1555 error(-1,
"Missing or invalid Coords in shading dictionary");
1562 if (dict->lookup(
"Domain", &obj1)->isArray() &&
1563 obj1.arrayGetLength() == 2) {
1564 t0A = obj1.arrayGet(0, &obj2)->getNum();
1566 t1A = obj1.arrayGet(1, &obj2)->getNum();
1571 dict->lookup(
"Function", &obj1);
1572 if (obj1.isArray()) {
1573 nFuncsA = obj1.arrayGetLength();
1574 for (i = 0; i < nFuncsA; ++i) {
1575 obj1.arrayGet(i, &obj2);
1576 if (!(funcsA[i] = Function::parse(&obj2))) {
1585 if (!(funcsA[0] = Function::parse(&obj1))) {
1592 extend0A = extend1A = gFalse;
1593 if (dict->lookup(
"Extend", &obj1)->isArray() &&
1594 obj1.arrayGetLength() == 2) {
1595 extend0A = obj1.arrayGet(0, &obj2)->getBool();
1597 extend1A = obj1.arrayGet(1, &obj2)->getBool();
1602 return new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
1603 funcsA, nFuncsA, extend0A, extend1A);
1609void GfxRadialShading::getColor(
double t, GfxColor *color) {
1612 for (i = 0; i < nFuncs; ++i) {
1613 funcs[i]->transform(&t, &color->c[i]);
1621GfxImageColorMap::GfxImageColorMap(
int bitsA, Object *decode,
1622 GfxColorSpace *colorSpaceA) {
1623 GfxIndexedColorSpace *indexedCS;
1624 GfxSeparationColorSpace *sepCS;
1625 int maxPixel, indexHigh;
1626 const Guchar *lookup2;
1627 const Function *sepFunc;
1629 double x[gfxColorMaxComps];
1630 double y[gfxColorMaxComps];
1637 maxPixel = (1 << bits) - 1;
1638 colorSpace = colorSpaceA;
1641 if (decode->isNull()) {
1642 nComps = colorSpace->getNComps();
1643 colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
1644 }
else if (decode->isArray()) {
1645 nComps = decode->arrayGetLength() / 2;
1646 if (nComps != colorSpace->getNComps()) {
1649 for (i = 0; i < nComps; ++i) {
1650 decode->arrayGet(2*i, &obj);
1654 decodeLow[i] = obj.getNum();
1656 decode->arrayGet(2*i+1, &obj);
1660 decodeRange[i] = obj.getNum() - decodeLow[i];
1676 if (colorSpace->getMode() == csIndexed) {
1680 indexedCS = (GfxIndexedColorSpace *)colorSpace;
1681 colorSpace2 = indexedCS->getBase();
1682 indexHigh = indexedCS->getIndexHigh();
1683 nComps2 = colorSpace2->getNComps();
1684 lookup = (
double *)gmalloc((indexHigh + 1) * nComps2 *
sizeof(
double));
1685 lookup2 = indexedCS->getLookup();
1686 colorSpace2->getDefaultRanges(x, y, indexHigh);
1687 for (i = 0; i <= indexHigh; ++i) {
1688 j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
1689 for (k = 0; k < nComps2; ++k) {
1690 lookup[j*nComps2 + k] = x[k] + (lookup2[i*nComps2 + k] / 255.0) * y[k];
1693 }
else if (colorSpace->getMode() == csSeparation) {
1694 sepCS = (GfxSeparationColorSpace *)colorSpace;
1695 colorSpace2 = sepCS->getAlt();
1696 nComps2 = colorSpace2->getNComps();
1697 lookup = (
double *)gmalloc((maxPixel + 1) * nComps2 *
sizeof(
double));
1698 sepFunc = sepCS->getFunc();
1699 for (i = 0; i <= maxPixel; ++i) {
1700 x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
1701 sepFunc->transform(x, y);
1702 for (k = 0; k < nComps2; ++k) {
1703 lookup[i*nComps2 + k] = y[k];
1707 lookup = (
double *)gmalloc((maxPixel + 1) * nComps *
sizeof(
double));
1708 for (i = 0; i <= maxPixel; ++i) {
1709 for (k = 0; k < nComps; ++k) {
1710 lookup[i*nComps + k] = decodeLow[k] +
1711 (i * decodeRange[k]) / maxPixel;
1724GfxImageColorMap::~GfxImageColorMap() {
1729void GfxImageColorMap::getGray(Guchar *x,
double *gray) {
1735 p = &lookup[x[0] * nComps2];
1736 for (i = 0; i < nComps2; ++i) {
1739 colorSpace2->getGray(&color, gray);
1741 for (i = 0; i < nComps; ++i) {
1742 color.c[i] = lookup[x[i] * nComps + i];
1744 colorSpace->getGray(&color, gray);
1748void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
1754 p = &lookup[x[0] * nComps2];
1755 for (i = 0; i < nComps2; ++i) {
1758 colorSpace2->getRGB(&color, rgb);
1760 for (i = 0; i < nComps; ++i) {
1761 color.c[i] = lookup[x[i] * nComps + i];
1763 colorSpace->getRGB(&color, rgb);
1767void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
1773 p = &lookup[x[0] * nComps2];
1774 for (i = 0; i < nComps2; ++i) {
1777 colorSpace2->getCMYK(&color, cmyk);
1779 for (i = 0; i < nComps; ++i) {
1780 color.c[i] = lookup[x[i] * nComps + i];
1782 colorSpace->getCMYK(&color, cmyk);
1790GfxSubpath::GfxSubpath(
double x1,
double y1) {
1792 x = (
double *)gmalloc(size *
sizeof(
double));
1793 y = (
double *)gmalloc(size *
sizeof(
double));
1794 curve = (GBool *)gmalloc(size *
sizeof(GBool));
1802GfxSubpath::~GfxSubpath() {
1809GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
1810 size = subpath->size;
1812 x = (
double *)gmalloc(size *
sizeof(
double));
1813 y = (
double *)gmalloc(size *
sizeof(
double));
1814 curve = (GBool *)gmalloc(size *
sizeof(GBool));
1815 memcpy(x, subpath->x, n *
sizeof(
double));
1816 memcpy(y, subpath->y, n *
sizeof(
double));
1817 memcpy(curve, subpath->curve, n *
sizeof(GBool));
1818 closed = subpath->closed;
1821void GfxSubpath::lineTo(
double x1,
double y1) {
1824 x = (
double *)grealloc(x, size *
sizeof(
double));
1825 y = (
double *)grealloc(y, size *
sizeof(
double));
1826 curve = (GBool *)grealloc(curve, size *
sizeof(GBool));
1834void GfxSubpath::curveTo(
double x1,
double y1,
double x2,
double y2,
1835 double x3,
double y3) {
1838 x = (
double *)grealloc(x, size *
sizeof(
double));
1839 y = (
double *)grealloc(y, size *
sizeof(
double));
1840 curve = (GBool *)grealloc(curve, size *
sizeof(GBool));
1848 curve[n] = curve[n+1] = gTrue;
1849 curve[n+2] = gFalse;
1853void GfxSubpath::close() {
1854 if (x[n-1] != x[0] || y[n-1] != y[0]) {
1864 firstX = firstY = 0;
1865 subpaths = (GfxSubpath **)gmalloc(size *
sizeof(GfxSubpath *));
1868GfxPath::~GfxPath() {
1871 for (i = 0; i < n; ++i)
1877GfxPath::GfxPath(GBool justMoved1,
double firstX1,
double firstY1,
1878 GfxSubpath **subpaths1,
int n1,
int size1) {
1881 justMoved = justMoved1;
1886 subpaths = (GfxSubpath **)gmalloc(size *
sizeof(GfxSubpath *));
1887 for (i = 0; i < n; ++i)
1888 subpaths[i] = subpaths1[i]->copy();
1891void GfxPath::moveTo(
double x,
double y) {
1897void GfxPath::lineTo(
double x,
double y) {
1901 subpaths = (GfxSubpath **)
1902 grealloc(subpaths, size *
sizeof(GfxSubpath *));
1904 subpaths[n] =
new GfxSubpath(firstX, firstY);
1908 subpaths[n-1]->lineTo(x, y);
1911void GfxPath::curveTo(
double x1,
double y1,
double x2,
double y2,
1912 double x3,
double y3) {
1916 subpaths = (GfxSubpath **)
1917 grealloc(subpaths, size *
sizeof(GfxSubpath *));
1919 subpaths[n] =
new GfxSubpath(firstX, firstY);
1923 subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
1926void GfxPath::close() {
1932 subpaths = (GfxSubpath **)
1933 grealloc(subpaths, size *
sizeof(GfxSubpath *));
1935 subpaths[n] =
new GfxSubpath(firstX, firstY);
1939 subpaths[n-1]->close();
1946GfxState::GfxState(
double dpi, PDFRectangle *pageBox,
int rotate,
1957 ctm[1] = upsideDown ? k : -k;
1961 ctm[5] = k * (upsideDown ? -px1 : px2);
1962 pageWidth = k * (py2 - py1);
1963 pageHeight = k * (px2 - px1);
1964 }
else if (rotate == 180) {
1968 ctm[3] = upsideDown ? k : -k;
1970 ctm[5] = k * (upsideDown ? -py1 : py2);
1971 pageWidth = k * (px2 - px1);
1972 pageHeight = k * (py2 - py1);
1973 }
else if (rotate == 270) {
1975 ctm[1] = upsideDown ? -k : k;
1979 ctm[5] = k * (upsideDown ? px2 : -px1);
1980 pageWidth = k * (py2 - py1);
1981 pageHeight = k * (px2 - px1);
1986 ctm[3] = upsideDown ? -k : k;
1988 ctm[5] = k * (upsideDown ? py2 : -py1);
1989 pageWidth = k * (px2 - px1);
1990 pageHeight = k * (py2 - py1);
1993 fillColorSpace =
new GfxDeviceGrayColorSpace();
1994 strokeColorSpace =
new GfxDeviceGrayColorSpace();
1996 strokeColor.c[0] = 0;
1998 strokePattern = NULL;
2013 textMat[0] = 1; textMat[1] = 0;
2014 textMat[2] = 0; textMat[3] = 1;
2015 textMat[4] = 0; textMat[5] = 0;
2023 path =
new GfxPath();
2029 clipXMax = pageWidth;
2030 clipYMax = pageHeight;
2035GfxState::~GfxState() {
2036 if (fillColorSpace) {
2037 delete fillColorSpace;
2039 if (strokeColorSpace) {
2040 delete strokeColorSpace;
2045 if (strokePattern) {
2046 delete strokePattern;
2059GfxState::GfxState(
const GfxState *state) {
2060 memcpy(
this, state,
sizeof(GfxState));
2061 if (fillColorSpace) {
2062 fillColorSpace = state->fillColorSpace->copy();
2064 if (strokeColorSpace) {
2065 strokeColorSpace = state->strokeColorSpace->copy();
2068 fillPattern = state->fillPattern->copy();
2070 if (strokePattern) {
2071 strokePattern = state->strokePattern->copy();
2073 if (lineDashLength > 0) {
2074 lineDash = (
double *)gmalloc(lineDashLength *
sizeof(
double));
2075 memcpy(lineDash, state->lineDash, lineDashLength *
sizeof(
double));
2080void GfxState::getUserClipBBox(
double *xMin,
double *yMin,
2081 double *xMax,
double *yMax)
const {
2083 double xMin1, yMin1, xMax1, yMax1, det, tx, ty;
2086 det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
2087 ictm[0] = ctm[3] * det;
2088 ictm[1] = -ctm[1] * det;
2089 ictm[2] = -ctm[2] * det;
2090 ictm[3] = ctm[0] * det;
2091 ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
2092 ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
2096 xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4];
2097 yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5];
2098 tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4];
2099 ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5];
2102 }
else if (tx > xMax1) {
2107 }
else if (ty > yMax1) {
2110 tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4];
2111 ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5];
2114 }
else if (tx > xMax1) {
2119 }
else if (ty > yMax1) {
2122 tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4];
2123 ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5];
2126 }
else if (tx > xMax1) {
2131 }
else if (ty > yMax1) {
2141double GfxState::transformWidth(
double w) {
2144 x = ctm[0] + ctm[2];
2145 y = ctm[1] + ctm[3];
2146 return w * sqrt(0.5 * (x * x + y * y));
2149double GfxState::getTransformedFontSize() {
2150 double x1, y1, x2, y2;
2152 x1 = textMat[2] * fontSize;
2153 y1 = textMat[3] * fontSize;
2154 x2 = ctm[0] * x1 + ctm[2] * y1;
2155 y2 = ctm[1] * x1 + ctm[3] * y1;
2156 return sqrt(x2 * x2 + y2 * y2);
2159void GfxState::getFontTransMat(
double *m11,
double *m12,
2160 double *m21,
double *m22) {
2161 *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize;
2162 *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize;
2163 *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
2164 *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
2167void GfxState::setCTM(
double a,
double b,
double c,
2168 double d,
double e,
double f) {
2179 for (i = 0; i < 6; ++i) {
2180 if (ctm[i] > 1e10) {
2182 }
else if (ctm[i] < -1e10) {
2188void GfxState::concatCTM(
double a,
double b,
double c,
2189 double d,
double e,
double f) {
2196 ctm[0] = a * a1 + b * c1;
2197 ctm[1] = a * b1 + b * d1;
2198 ctm[2] = c * a1 + d * c1;
2199 ctm[3] = c * b1 + d * d1;
2200 ctm[4] = e * a1 + f * c1 + ctm[4];
2201 ctm[5] = e * b1 + f * d1 + ctm[5];
2204 for (i = 0; i < 6; ++i) {
2205 if (ctm[i] > 1e10) {
2207 }
else if (ctm[i] < -1e10) {
2213void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
2214 if (fillColorSpace) {
2215 delete fillColorSpace;
2217 fillColorSpace = colorSpace;
2220void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
2221 if (strokeColorSpace) {
2222 delete strokeColorSpace;
2224 strokeColorSpace = colorSpace;
2227void GfxState::setFillPattern(GfxPattern *pattern) {
2231 fillPattern = pattern;
2234void GfxState::setStrokePattern(GfxPattern *pattern) {
2235 if (strokePattern) {
2236 delete strokePattern;
2238 strokePattern = pattern;
2241void GfxState::setLineDash(
double *dash,
int length,
double start) {
2245 lineDashLength = length;
2246 lineDashStart = start;
2249void GfxState::clearPath() {
2251 path =
new GfxPath();
2254void GfxState::clip() {
2255 double xMin, yMin, xMax, yMax, x, y;
2256 GfxSubpath *subpath;
2259 xMin = xMax = yMin = yMax = 0;
2260 for (i = 0; i < path->getNumSubpaths(); ++i) {
2261 subpath = path->getSubpath(i);
2262 for (j = 0; j < subpath->getNumPoints(); ++j) {
2263 transform(subpath->getX(j), subpath->getY(j), &x, &y);
2264 if (i == 0 && j == 0) {
2270 }
else if (x > xMax) {
2275 }
else if (y > yMax) {
2281 if (xMin > clipXMin) {
2284 if (yMin > clipYMin) {
2287 if (xMax < clipXMax) {
2290 if (yMax < clipYMax) {
2295void GfxState::textShift(
double tx,
double ty) {
2298 textTransformDelta(tx, ty, &dx, &dy);
2303void GfxState::shift(
double dx,
double dy) {
2308GfxState *GfxState::save() {
2312 newState->saved =
this;
2316GfxState *GfxState::restore() {
2323 oldState->path = path;
2324 oldState->curX = curX;
2325 oldState->curY = curY;
2326 oldState->lineX = lineX;
2327 oldState->lineY = lineY;