00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <aconf.h>
00010
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014
00015 #include <stddef.h>
00016 #include <math.h>
00017 #include <string.h>
00018 #include "gmem.h"
00019 #include "Error.h"
00020 #include "Object.h"
00021 #include "Array.h"
00022 #include "Page.h"
00023 #include "GfxState.h"
00024
00025
00026
00027 static inline double clip01(double x) {
00028 return (x < 0) ? 0 : ((x > 1) ? 1 : x);
00029 }
00030
00031
00032
00033
00034
00035 GfxColorSpace::GfxColorSpace() {
00036 }
00037
00038 GfxColorSpace::~GfxColorSpace() {
00039 }
00040
00041 GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
00042 GfxColorSpace *cs;
00043 Object obj1;
00044
00045 cs = NULL;
00046 if (csObj->isName()) {
00047 if (csObj->isName("DeviceGray") || csObj->isName("G")) {
00048 cs = new GfxDeviceGrayColorSpace();
00049 } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
00050 cs = new GfxDeviceRGBColorSpace();
00051 } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
00052 cs = new GfxDeviceCMYKColorSpace();
00053 } else if (csObj->isName("Pattern")) {
00054 cs = new GfxPatternColorSpace(NULL);
00055 } else {
00056 error(-1, "Bad color space '%s'", csObj->getName());
00057 }
00058 } else if (csObj->isArray()) {
00059 csObj->arrayGet(0, &obj1);
00060 if (obj1.isName("DeviceGray") || obj1.isName("G")) {
00061 cs = new GfxDeviceGrayColorSpace();
00062 } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
00063 cs = new GfxDeviceRGBColorSpace();
00064 } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
00065 cs = new GfxDeviceCMYKColorSpace();
00066 } else if (obj1.isName("CalGray")) {
00067 cs = GfxCalGrayColorSpace::parse(csObj->getArray());
00068 } else if (obj1.isName("CalRGB")) {
00069 cs = GfxCalRGBColorSpace::parse(csObj->getArray());
00070 } else if (obj1.isName("Lab")) {
00071 cs = GfxLabColorSpace::parse(csObj->getArray());
00072 } else if (obj1.isName("ICCBased")) {
00073 cs = GfxICCBasedColorSpace::parse(csObj->getArray());
00074 } else if (obj1.isName("Indexed") || obj1.isName("I")) {
00075 cs = GfxIndexedColorSpace::parse(csObj->getArray());
00076 } else if (obj1.isName("Separation")) {
00077 cs = GfxSeparationColorSpace::parse(csObj->getArray());
00078 } else if (obj1.isName("DeviceN")) {
00079 cs = GfxDeviceNColorSpace::parse(csObj->getArray());
00080 } else if (obj1.isName("Pattern")) {
00081 cs = GfxPatternColorSpace::parse(csObj->getArray());
00082 } else {
00083 error(-1, "Bad color space '%s'", csObj->getName());
00084 }
00085 obj1.free();
00086 } else {
00087 error(-1, "Bad color space - expected name or array");
00088 }
00089 return cs;
00090 }
00091
00092 void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
00093 int ) const {
00094 int i;
00095
00096 for (i = 0; i < getNComps(); ++i) {
00097 decodeLow[i] = 0;
00098 decodeRange[i] = 1;
00099 }
00100 }
00101
00102
00103
00104
00105
00106 GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() {
00107 }
00108
00109 GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() {
00110 }
00111
00112 GfxColorSpace *GfxDeviceGrayColorSpace::copy() const {
00113 return new GfxDeviceGrayColorSpace();
00114 }
00115
00116 void GfxDeviceGrayColorSpace::getGray(const GfxColor *color, double *gray) const {
00117 *gray = clip01(color->c[0]);
00118 }
00119
00120 void GfxDeviceGrayColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
00121 rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
00122 }
00123
00124 void GfxDeviceGrayColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
00125 cmyk->c = cmyk->m = cmyk->y = 0;
00126 cmyk->k = clip01(1 - color->c[0]);
00127 }
00128
00129
00130
00131
00132
00133 GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
00134 whiteX = whiteY = whiteZ = 1;
00135 blackX = blackY = blackZ = 0;
00136 gamma = 1;
00137 }
00138
00139 GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
00140 }
00141
00142 GfxColorSpace *GfxCalGrayColorSpace::copy() const {
00143 GfxCalGrayColorSpace *cs;
00144
00145 cs = new GfxCalGrayColorSpace();
00146 cs->whiteX = whiteX;
00147 cs->whiteY = whiteY;
00148 cs->whiteZ = whiteZ;
00149 cs->blackX = blackX;
00150 cs->blackY = blackY;
00151 cs->blackZ = blackZ;
00152 cs->gamma = gamma;
00153 return cs;
00154 }
00155
00156 GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
00157 GfxCalGrayColorSpace *cs;
00158 Object obj1, obj2, obj3;
00159
00160 arr->get(1, &obj1);
00161 if (!obj1.isDict()) {
00162 error(-1, "Bad CalGray color space");
00163 obj1.free();
00164 return NULL;
00165 }
00166 cs = new GfxCalGrayColorSpace();
00167 if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
00168 obj2.arrayGetLength() == 3) {
00169 obj2.arrayGet(0, &obj3);
00170 cs->whiteX = obj3.getNum();
00171 obj3.free();
00172 obj2.arrayGet(1, &obj3);
00173 cs->whiteY = obj3.getNum();
00174 obj3.free();
00175 obj2.arrayGet(2, &obj3);
00176 cs->whiteZ = obj3.getNum();
00177 obj3.free();
00178 }
00179 obj2.free();
00180 if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
00181 obj2.arrayGetLength() == 3) {
00182 obj2.arrayGet(0, &obj3);
00183 cs->blackX = obj3.getNum();
00184 obj3.free();
00185 obj2.arrayGet(1, &obj3);
00186 cs->blackY = obj3.getNum();
00187 obj3.free();
00188 obj2.arrayGet(2, &obj3);
00189 cs->blackZ = obj3.getNum();
00190 obj3.free();
00191 }
00192 obj2.free();
00193 if (obj1.dictLookup("Gamma", &obj2)->isNum()) {
00194 cs->gamma = obj2.getNum();
00195 }
00196 obj2.free();
00197 obj1.free();
00198 return cs;
00199 }
00200
00201 void GfxCalGrayColorSpace::getGray(const GfxColor *color, double *gray) const {
00202 *gray = clip01(color->c[0]);
00203 }
00204
00205 void GfxCalGrayColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
00206 rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
00207 }
00208
00209 void GfxCalGrayColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
00210 cmyk->c = cmyk->m = cmyk->y = 0;
00211 cmyk->k = clip01(1 - color->c[0]);
00212 }
00213
00214
00215
00216
00217
00218 GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() {
00219 }
00220
00221 GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() {
00222 }
00223
00224 GfxColorSpace *GfxDeviceRGBColorSpace::copy() const {
00225 return new GfxDeviceRGBColorSpace();
00226 }
00227
00228 void GfxDeviceRGBColorSpace::getGray(const GfxColor *color, double *gray) const {
00229 *gray = clip01(0.299 * color->c[0] +
00230 0.587 * color->c[1] +
00231 0.114 * color->c[2]);
00232 }
00233
00234 void GfxDeviceRGBColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
00235 rgb->r = clip01(color->c[0]);
00236 rgb->g = clip01(color->c[1]);
00237 rgb->b = clip01(color->c[2]);
00238 }
00239
00240 void GfxDeviceRGBColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
00241 double c, m, y, k;
00242
00243 c = clip01(1 - color->c[0]);
00244 m = clip01(1 - color->c[1]);
00245 y = clip01(1 - color->c[2]);
00246 k = c;
00247 if (m < k) {
00248 k = m;
00249 }
00250 if (y < k) {
00251 k = y;
00252 }
00253 cmyk->c = c - k;
00254 cmyk->m = m - k;
00255 cmyk->y = y - k;
00256 cmyk->k = k;
00257 }
00258
00259
00260
00261
00262
00263 GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
00264 whiteX = whiteY = whiteZ = 1;
00265 blackX = blackY = blackZ = 0;
00266 gammaR = gammaG = gammaB = 1;
00267 mat[0] = 1; mat[1] = 0; mat[2] = 0;
00268 mat[3] = 0; mat[4] = 1; mat[5] = 0;
00269 mat[6] = 0; mat[7] = 0; mat[8] = 1;
00270 }
00271
00272 GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
00273 }
00274
00275 GfxColorSpace *GfxCalRGBColorSpace::copy() const {
00276 GfxCalRGBColorSpace *cs;
00277 int i;
00278
00279 cs = new GfxCalRGBColorSpace();
00280 cs->whiteX = whiteX;
00281 cs->whiteY = whiteY;
00282 cs->whiteZ = whiteZ;
00283 cs->blackX = blackX;
00284 cs->blackY = blackY;
00285 cs->blackZ = blackZ;
00286 cs->gammaR = gammaR;
00287 cs->gammaG = gammaG;
00288 cs->gammaB = gammaB;
00289 for (i = 0; i < 9; ++i) {
00290 cs->mat[i] = mat[i];
00291 }
00292 return cs;
00293 }
00294
00295 GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
00296 GfxCalRGBColorSpace *cs;
00297 Object obj1, obj2, obj3;
00298 int i;
00299
00300 arr->get(1, &obj1);
00301 if (!obj1.isDict()) {
00302 error(-1, "Bad CalRGB color space");
00303 obj1.free();
00304 return NULL;
00305 }
00306 cs = new GfxCalRGBColorSpace();
00307 if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
00308 obj2.arrayGetLength() == 3) {
00309 obj2.arrayGet(0, &obj3);
00310 cs->whiteX = obj3.getNum();
00311 obj3.free();
00312 obj2.arrayGet(1, &obj3);
00313 cs->whiteY = obj3.getNum();
00314 obj3.free();
00315 obj2.arrayGet(2, &obj3);
00316 cs->whiteZ = obj3.getNum();
00317 obj3.free();
00318 }
00319 obj2.free();
00320 if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
00321 obj2.arrayGetLength() == 3) {
00322 obj2.arrayGet(0, &obj3);
00323 cs->blackX = obj3.getNum();
00324 obj3.free();
00325 obj2.arrayGet(1, &obj3);
00326 cs->blackY = obj3.getNum();
00327 obj3.free();
00328 obj2.arrayGet(2, &obj3);
00329 cs->blackZ = obj3.getNum();
00330 obj3.free();
00331 }
00332 obj2.free();
00333 if (obj1.dictLookup("Gamma", &obj2)->isArray() &&
00334 obj2.arrayGetLength() == 3) {
00335 obj2.arrayGet(0, &obj3);
00336 cs->gammaR = obj3.getNum();
00337 obj3.free();
00338 obj2.arrayGet(1, &obj3);
00339 cs->gammaG = obj3.getNum();
00340 obj3.free();
00341 obj2.arrayGet(2, &obj3);
00342 cs->gammaB = obj3.getNum();
00343 obj3.free();
00344 }
00345 obj2.free();
00346 if (obj1.dictLookup("Matrix", &obj2)->isArray() &&
00347 obj2.arrayGetLength() == 9) {
00348 for (i = 0; i < 9; ++i) {
00349 obj2.arrayGet(i, &obj3);
00350 cs->mat[i] = obj3.getNum();
00351 obj3.free();
00352 }
00353 }
00354 obj2.free();
00355 obj1.free();
00356 return cs;
00357 }
00358
00359 void GfxCalRGBColorSpace::getGray(const GfxColor *color, double *gray) const {
00360 *gray = clip01(0.299 * color->c[0] +
00361 0.587 * color->c[1] +
00362 0.114 * color->c[2]);
00363 }
00364
00365 void GfxCalRGBColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
00366 rgb->r = clip01(color->c[0]);
00367 rgb->g = clip01(color->c[1]);
00368 rgb->b = clip01(color->c[2]);
00369 }
00370
00371 void GfxCalRGBColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
00372 double c, m, y, k;
00373
00374 c = clip01(1 - color->c[0]);
00375 m = clip01(1 - color->c[1]);
00376 y = clip01(1 - color->c[2]);
00377 k = c;
00378 if (m < k) {
00379 k = m;
00380 }
00381 if (y < k) {
00382 k = y;
00383 }
00384 cmyk->c = c - k;
00385 cmyk->m = m - k;
00386 cmyk->y = y - k;
00387 cmyk->k = k;
00388 }
00389
00390
00391
00392
00393
00394 GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
00395 }
00396
00397 GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
00398 }
00399
00400 GfxColorSpace *GfxDeviceCMYKColorSpace::copy() const {
00401 return new GfxDeviceCMYKColorSpace();
00402 }
00403
00404 void GfxDeviceCMYKColorSpace::getGray(const GfxColor *color, double *gray) const {
00405 *gray = clip01(1 - color->c[3]
00406 - 0.299 * color->c[0]
00407 - 0.587 * color->c[1]
00408 - 0.114 * color->c[2]);
00409 }
00410
00411 void GfxDeviceCMYKColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
00412 double c, m, y, aw, ac, am, ay, ar, ag, ab;
00413
00414 c = clip01(color->c[0] + color->c[3]);
00415 m = clip01(color->c[1] + color->c[3]);
00416 y = clip01(color->c[2] + color->c[3]);
00417 aw = (1-c) * (1-m) * (1-y);
00418 ac = c * (1-m) * (1-y);
00419 am = (1-c) * m * (1-y);
00420 ay = (1-c) * (1-m) * y;
00421 ar = (1-c) * m * y;
00422 ag = c * (1-m) * y;
00423 ab = c * m * (1-y);
00424 rgb->r = clip01(aw + 0.9137*am + 0.9961*ay + 0.9882*ar);
00425 rgb->g = clip01(aw + 0.6196*ac + ay + 0.5176*ag);
00426 rgb->b = clip01(aw + 0.7804*ac + 0.5412*am + 0.0667*ar + 0.2118*ag +
00427 0.4863*ab);
00428 }
00429
00430 void GfxDeviceCMYKColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
00431 cmyk->c = clip01(color->c[0]);
00432 cmyk->m = clip01(color->c[1]);
00433 cmyk->y = clip01(color->c[2]);
00434 cmyk->k = clip01(color->c[3]);
00435 }
00436
00437
00438
00439
00440
00441
00442
00443 static double xyzrgb[3][3] = {
00444 { 3.240449, -1.537136, -0.498531 },
00445 { -0.969265, 1.876011, 0.041556 },
00446 { 0.055643, -0.204026, 1.057229 }
00447 };
00448
00449 GfxLabColorSpace::GfxLabColorSpace() {
00450 whiteX = whiteY = whiteZ = 1;
00451 blackX = blackY = blackZ = 0;
00452 aMin = bMin = -100;
00453 aMax = bMax = 100;
00454 }
00455
00456 GfxLabColorSpace::~GfxLabColorSpace() {
00457 }
00458
00459 GfxColorSpace *GfxLabColorSpace::copy() const {
00460 GfxLabColorSpace *cs;
00461
00462 cs = new GfxLabColorSpace();
00463 cs->whiteX = whiteX;
00464 cs->whiteY = whiteY;
00465 cs->whiteZ = whiteZ;
00466 cs->blackX = blackX;
00467 cs->blackY = blackY;
00468 cs->blackZ = blackZ;
00469 cs->aMin = aMin;
00470 cs->aMax = aMax;
00471 cs->bMin = bMin;
00472 cs->bMax = bMax;
00473 cs->kr = kr;
00474 cs->kg = kg;
00475 cs->kb = kb;
00476 return cs;
00477 }
00478
00479 GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
00480 GfxLabColorSpace *cs;
00481 Object obj1, obj2, obj3;
00482
00483 arr->get(1, &obj1);
00484 if (!obj1.isDict()) {
00485 error(-1, "Bad Lab color space");
00486 obj1.free();
00487 return NULL;
00488 }
00489 cs = new GfxLabColorSpace();
00490 if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
00491 obj2.arrayGetLength() == 3) {
00492 obj2.arrayGet(0, &obj3);
00493 cs->whiteX = obj3.getNum();
00494 obj3.free();
00495 obj2.arrayGet(1, &obj3);
00496 cs->whiteY = obj3.getNum();
00497 obj3.free();
00498 obj2.arrayGet(2, &obj3);
00499 cs->whiteZ = obj3.getNum();
00500 obj3.free();
00501 }
00502 obj2.free();
00503 if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
00504 obj2.arrayGetLength() == 3) {
00505 obj2.arrayGet(0, &obj3);
00506 cs->blackX = obj3.getNum();
00507 obj3.free();
00508 obj2.arrayGet(1, &obj3);
00509 cs->blackY = obj3.getNum();
00510 obj3.free();
00511 obj2.arrayGet(2, &obj3);
00512 cs->blackZ = obj3.getNum();
00513 obj3.free();
00514 }
00515 obj2.free();
00516 if (obj1.dictLookup("Range", &obj2)->isArray() &&
00517 obj2.arrayGetLength() == 4) {
00518 obj2.arrayGet(0, &obj3);
00519 cs->aMin = obj3.getNum();
00520 obj3.free();
00521 obj2.arrayGet(1, &obj3);
00522 cs->aMax = obj3.getNum();
00523 obj3.free();
00524 obj2.arrayGet(2, &obj3);
00525 cs->bMin = obj3.getNum();
00526 obj3.free();
00527 obj2.arrayGet(3, &obj3);
00528 cs->bMax = obj3.getNum();
00529 obj3.free();
00530 }
00531 obj2.free();
00532 obj1.free();
00533
00534 cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
00535 xyzrgb[0][1] * cs->whiteY +
00536 xyzrgb[0][2] * cs->whiteZ);
00537 cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
00538 xyzrgb[1][1] * cs->whiteY +
00539 xyzrgb[1][2] * cs->whiteZ);
00540 cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
00541 xyzrgb[2][1] * cs->whiteY +
00542 xyzrgb[2][2] * cs->whiteZ);
00543
00544 return cs;
00545 }
00546
00547 void GfxLabColorSpace::getGray(const GfxColor *color, double *gray) const {
00548 GfxRGB rgb;
00549
00550 getRGB(color, &rgb);
00551 *gray = clip01(0.299 * rgb.r +
00552 0.587 * rgb.g +
00553 0.114 * rgb.b);
00554 }
00555
00556 void GfxLabColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
00557 double X, Y, Z;
00558 double t1, t2;
00559 double r, g, b;
00560
00561
00562 t1 = (color->c[0] + 16) / 116;
00563 t2 = t1 + color->c[1] / 500;
00564 if (t2 >= (6.0 / 29.0)) {
00565 X = t2 * t2 * t2;
00566 } else {
00567 X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
00568 }
00569 X *= whiteX;
00570 if (t1 >= (6.0 / 29.0)) {
00571 Y = t1 * t1 * t1;
00572 } else {
00573 Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
00574 }
00575 Y *= whiteY;
00576 t2 = t1 - color->c[2] / 200;
00577 if (t2 >= (6.0 / 29.0)) {
00578 Z = t2 * t2 * t2;
00579 } else {
00580 Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
00581 }
00582 Z *= whiteZ;
00583
00584
00585 r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
00586 g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
00587 b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
00588 rgb->r = pow(clip01(r * kr), 0.5);
00589 rgb->g = pow(clip01(g * kg), 0.5);
00590 rgb->b = pow(clip01(b * kb), 0.5);
00591 }
00592
00593 void GfxLabColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
00594 GfxRGB rgb;
00595 double c, m, y, k;
00596
00597 getRGB(color, &rgb);
00598 c = clip01(1 - rgb.r);
00599 m = clip01(1 - rgb.g);
00600 y = clip01(1 - rgb.b);
00601 k = c;
00602 if (m < k) {
00603 k = m;
00604 }
00605 if (y < k) {
00606 k = y;
00607 }
00608 cmyk->c = c - k;
00609 cmyk->m = m - k;
00610 cmyk->y = y - k;
00611 cmyk->k = k;
00612 }
00613
00614 void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
00615 int ) const {
00616 decodeLow[0] = 0;
00617 decodeRange[0] = 100;
00618 decodeLow[1] = aMin;
00619 decodeRange[1] = aMax - aMin;
00620 decodeLow[2] = bMin;
00621 decodeRange[2] = bMax - bMin;
00622 }
00623
00624
00625
00626
00627
00628 GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
00629 const Ref *iccProfileStreamA) {
00630 nComps = nCompsA;
00631 alt = altA;
00632 iccProfileStream = *iccProfileStreamA;
00633 rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
00634 rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
00635 }
00636
00637 GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
00638 delete alt;
00639 }
00640
00641 GfxColorSpace *GfxICCBasedColorSpace::copy() const {
00642 GfxICCBasedColorSpace *cs;
00643 int i;
00644
00645 cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
00646 for (i = 0; i < 4; ++i) {
00647 cs->rangeMin[i] = rangeMin[i];
00648 cs->rangeMax[i] = rangeMax[i];
00649 }
00650 return cs;
00651 }
00652
00653 GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
00654 GfxICCBasedColorSpace *cs;
00655 Ref iccProfileStreamA;
00656 int nCompsA;
00657 GfxColorSpace *altA;
00658 Dict *dict;
00659 Object obj1, obj2, obj3;
00660 int i;
00661
00662 arr->getNF(1, &obj1);
00663 if (obj1.isRef()) {
00664 iccProfileStreamA = obj1.getRef();
00665 } else {
00666 iccProfileStreamA.num = 0;
00667 iccProfileStreamA.gen = 0;
00668 }
00669 obj1.free();
00670 arr->get(1, &obj1);
00671 if (!obj1.isStream()) {
00672 error(-1, "Bad ICCBased color space (stream)");
00673 obj1.free();
00674 return NULL;
00675 }
00676 dict = obj1.streamGetDict();
00677 if (!dict->lookup("N", &obj2)->isInt()) {
00678 error(-1, "Bad ICCBased color space (N)");
00679 obj2.free();
00680 obj1.free();
00681 return NULL;
00682 }
00683 nCompsA = obj2.getInt();
00684 obj2.free();
00685 if (nCompsA > gfxColorMaxComps) {
00686 error(-1, "ICCBased color space with too many (%d > %d) components",
00687 nCompsA, gfxColorMaxComps);
00688 nCompsA = gfxColorMaxComps;
00689 }
00690 if (dict->lookup("Alternate", &obj2)->isNull() ||
00691 !(altA = GfxColorSpace::parse(&obj2))) {
00692 switch (nCompsA) {
00693 case 1:
00694 altA = new GfxDeviceGrayColorSpace();
00695 break;
00696 case 3:
00697 altA = new GfxDeviceRGBColorSpace();
00698 break;
00699 case 4:
00700 altA = new GfxDeviceCMYKColorSpace();
00701 break;
00702 default:
00703 error(-1, "Bad ICCBased color space - invalid N");
00704 obj2.free();
00705 obj1.free();
00706 return NULL;
00707 }
00708 }
00709 obj2.free();
00710 cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA);
00711 if (dict->lookup("Range", &obj2)->isArray() &&
00712 obj2.arrayGetLength() == 2 * nCompsA) {
00713 for (i = 0; i < nCompsA; ++i) {
00714 obj2.arrayGet(2*i, &obj3);
00715 cs->rangeMin[i] = obj3.getNum();
00716 obj3.free();
00717 obj2.arrayGet(2*i+1, &obj3);
00718 cs->rangeMax[i] = obj3.getNum();
00719 obj3.free();
00720 }
00721 }
00722 obj2.free();
00723 obj1.free();
00724 return cs;
00725 }
00726
00727 void GfxICCBasedColorSpace::getGray(const GfxColor *color, double *gray) const {
00728 alt->getGray(color, gray);
00729 }
00730
00731 void GfxICCBasedColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
00732 alt->getRGB(color, rgb);
00733 }
00734
00735 void GfxICCBasedColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
00736 alt->getCMYK(color, cmyk);
00737 }
00738
00739 void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
00740 double *decodeRange,
00741 int ) const {
00742 int i;
00743
00744 for (i = 0; i < nComps; ++i) {
00745 decodeLow[i] = rangeMin[i];
00746 decodeRange[i] = rangeMax[i] - rangeMin[i];
00747 }
00748 }
00749
00750
00751
00752
00753
00754 GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA,
00755 int indexHighA) {
00756 base = baseA;
00757 indexHigh = indexHighA;
00758 lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
00759 sizeof(Guchar));
00760 }
00761
00762 GfxIndexedColorSpace::~GfxIndexedColorSpace() {
00763 delete base;
00764 gfree(lookup);
00765 }
00766
00767 GfxColorSpace *GfxIndexedColorSpace::copy() const {
00768 GfxIndexedColorSpace *cs;
00769
00770 cs = new GfxIndexedColorSpace(base->copy(), indexHigh);
00771 memcpy(cs->lookup, lookup,
00772 (indexHigh + 1) * base->getNComps() * sizeof(Guchar));
00773 return cs;
00774 }
00775
00776 GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
00777 GfxIndexedColorSpace *cs;
00778 GfxColorSpace *baseA;
00779 int indexHighA;
00780 Object obj1;
00781 int x;
00782 char *s;
00783 int n, i, j;
00784
00785 if (arr->getLength() != 4) {
00786 error(-1, "Bad Indexed color space");
00787 goto err1;
00788 }
00789 arr->get(1, &obj1);
00790 if (!(baseA = GfxColorSpace::parse(&obj1))) {
00791 error(-1, "Bad Indexed color space (base color space)");
00792 goto err2;
00793 }
00794 obj1.free();
00795 if (!arr->get(2, &obj1)->isInt()) {
00796 error(-1, "Bad Indexed color space (hival)");
00797 goto err2;
00798 }
00799 indexHighA = obj1.getInt();
00800 obj1.free();
00801 cs = new GfxIndexedColorSpace(baseA, indexHighA);
00802 arr->get(3, &obj1);
00803 n = baseA->getNComps();
00804 if (obj1.isStream()) {
00805 obj1.streamReset();
00806 for (i = 0; i <= indexHighA; ++i) {
00807 for (j = 0; j < n; ++j) {
00808 if ((x = obj1.streamGetChar()) == EOF) {
00809 error(-1, "Bad Indexed color space (lookup table stream too short)");
00810 goto err3;
00811 }
00812 cs->lookup[i*n + j] = (Guchar)x;
00813 }
00814 }
00815 obj1.streamClose();
00816 } else if (obj1.isString()) {
00817 if (obj1.getString()->getLength() < (indexHighA + 1) * n) {
00818 error(-1, "Bad Indexed color space (lookup table string too short)");
00819 goto err3;
00820 }
00821 s = obj1.getString()->getCString();
00822 for (i = 0; i <= indexHighA; ++i) {
00823 for (j = 0; j < n; ++j) {
00824 cs->lookup[i*n + j] = (Guchar)*s++;
00825 }
00826 }
00827 } else {
00828 error(-1, "Bad Indexed color space (lookup table)");
00829 goto err3;
00830 }
00831 obj1.free();
00832 return cs;
00833
00834 err3:
00835 delete cs;
00836 err2:
00837 obj1.free();
00838 err1:
00839 return NULL;
00840 }
00841
00842 void GfxIndexedColorSpace::getGray(const GfxColor *color, double *gray) const {
00843 Guchar *p;
00844 GfxColor color2;
00845 double low[gfxColorMaxComps], range[gfxColorMaxComps];
00846 int n, i;
00847
00848 n = base->getNComps();
00849 base->getDefaultRanges(low, range, indexHigh);
00850 p = &lookup[(int)(color->c[0] + 0.5) * n];
00851 for (i = 0; i < n; ++i) {
00852 color2.c[i] = low[i] + (p[i] / 255.0) * range[i];
00853 }
00854 base->getGray(&color2, gray);
00855 }
00856
00857 void GfxIndexedColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
00858 Guchar *p;
00859 GfxColor color2;
00860 double low[gfxColorMaxComps], range[gfxColorMaxComps];
00861 int n, i;
00862
00863 n = base->getNComps();
00864 base->getDefaultRanges(low, range, indexHigh);
00865 p = &lookup[(int)(color->c[0] + 0.5) * n];
00866 for (i = 0; i < n; ++i) {
00867 color2.c[i] = low[i] + (p[i] / 255.0) * range[i];
00868 }
00869 base->getRGB(&color2, rgb);
00870 }
00871
00872 void GfxIndexedColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
00873 Guchar *p;
00874 GfxColor color2;
00875 double low[gfxColorMaxComps], range[gfxColorMaxComps];
00876 int n, i;
00877
00878 n = base->getNComps();
00879 base->getDefaultRanges(low, range, indexHigh);
00880 p = &lookup[(int)(color->c[0] + 0.5) * n];
00881 for (i = 0; i < n; ++i) {
00882 color2.c[i] = low[i] + (p[i] / 255.0) * range[i];
00883 }
00884 base->getCMYK(&color2, cmyk);
00885 }
00886
00887 void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
00888 double *decodeRange,
00889 int maxImgPixel) const {
00890 decodeLow[0] = 0;
00891 decodeRange[0] = maxImgPixel;
00892 }
00893
00894
00895
00896
00897
00898 GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
00899 GfxColorSpace *altA,
00900 Function *funcA) {
00901 name = nameA;
00902 alt = altA;
00903 func = funcA;
00904 }
00905
00906 GfxSeparationColorSpace::~GfxSeparationColorSpace() {
00907 delete name;
00908 delete alt;
00909 delete func;
00910 }
00911
00912 GfxColorSpace *GfxSeparationColorSpace::copy() const {
00913 return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
00914 }
00915
00916
00917 GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
00918 GfxSeparationColorSpace *cs;
00919 GString *nameA;
00920 GfxColorSpace *altA;
00921 Function *funcA;
00922 Object obj1;
00923
00924 if (arr->getLength() != 4) {
00925 error(-1, "Bad Separation color space");
00926 goto err1;
00927 }
00928 if (!arr->get(1, &obj1)->isName()) {
00929 error(-1, "Bad Separation color space (name)");
00930 goto err2;
00931 }
00932 nameA = new GString(obj1.getName());
00933 obj1.free();
00934 arr->get(2, &obj1);
00935 if (!(altA = GfxColorSpace::parse(&obj1))) {
00936 error(-1, "Bad Separation color space (alternate color space)");
00937 goto err3;
00938 }
00939 obj1.free();
00940 arr->get(3, &obj1);
00941 if (!(funcA = Function::parse(&obj1))) {
00942 goto err4;
00943 }
00944 obj1.free();
00945 cs = new GfxSeparationColorSpace(nameA, altA, funcA);
00946 return cs;
00947
00948 err4:
00949 delete altA;
00950 err3:
00951 delete nameA;
00952 err2:
00953 obj1.free();
00954 err1:
00955 return NULL;
00956 }
00957
00958 void GfxSeparationColorSpace::getGray(const GfxColor *color, double *gray) const {
00959 GfxColor color2;
00960
00961 func->transform(color->c, color2.c);
00962 alt->getGray(&color2, gray);
00963 }
00964
00965 void GfxSeparationColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
00966 GfxColor color2;
00967
00968 func->transform(color->c, color2.c);
00969 alt->getRGB(&color2, rgb);
00970 }
00971
00972 void GfxSeparationColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
00973 GfxColor color2;
00974
00975 func->transform(color->c, color2.c);
00976 alt->getCMYK(&color2, cmyk);
00977 }
00978
00979
00980
00981
00982
00983 GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
00984 GfxColorSpace *altA,
00985 Function *funcA) {
00986 nComps = nCompsA;
00987 alt = altA;
00988 func = funcA;
00989 }
00990
00991 GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
00992 int i;
00993
00994 for (i = 0; i < nComps; ++i) {
00995 delete names[i];
00996 }
00997 delete alt;
00998 delete func;
00999 }
01000
01001 GfxColorSpace *GfxDeviceNColorSpace::copy() const {
01002 GfxDeviceNColorSpace *cs;
01003 int i;
01004
01005 cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
01006 for (i = 0; i < nComps; ++i) {
01007 cs->names[i] = names[i]->copy();
01008 }
01009 return cs;
01010 }
01011
01012
01013 GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
01014 GfxDeviceNColorSpace *cs;
01015 int nCompsA;
01016 GString *namesA[gfxColorMaxComps];
01017 GfxColorSpace *altA;
01018 Function *funcA;
01019 Object obj1, obj2;
01020 int i;
01021
01022 if (arr->getLength() != 4 && arr->getLength() != 5) {
01023 error(-1, "Bad DeviceN color space");
01024 goto err1;
01025 }
01026 if (!arr->get(1, &obj1)->isArray()) {
01027 error(-1, "Bad DeviceN color space (names)");
01028 goto err2;
01029 }
01030 nCompsA = obj1.arrayGetLength();
01031 if (nCompsA > gfxColorMaxComps) {
01032 error(-1, "DeviceN color space with too many (%d > %d) components",
01033 nCompsA, gfxColorMaxComps);
01034 nCompsA = gfxColorMaxComps;
01035 }
01036 for (i = 0; i < nCompsA; ++i) {
01037 if (!obj1.arrayGet(i, &obj2)->isName()) {
01038 error(-1, "Bad DeviceN color space (names)");
01039 obj2.free();
01040 goto err2;
01041 }
01042 namesA[i] = new GString(obj2.getName());
01043 obj2.free();
01044 }
01045 obj1.free();
01046 arr->get(2, &obj1);
01047 if (!(altA = GfxColorSpace::parse(&obj1))) {
01048 error(-1, "Bad DeviceN color space (alternate color space)");
01049 goto err3;
01050 }
01051 obj1.free();
01052 arr->get(3, &obj1);
01053 if (!(funcA = Function::parse(&obj1))) {
01054 goto err4;
01055 }
01056 obj1.free();
01057 cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
01058 for (i = 0; i < nCompsA; ++i) {
01059 cs->names[i] = namesA[i];
01060 }
01061 return cs;
01062
01063 err4:
01064 delete altA;
01065 err3:
01066 for (i = 0; i < nCompsA; ++i) {
01067 delete namesA[i];
01068 }
01069 err2:
01070 obj1.free();
01071 err1:
01072 return NULL;
01073 }
01074
01075 void GfxDeviceNColorSpace::getGray(const GfxColor *color, double *gray) const {
01076 GfxColor color2;
01077
01078 func->transform(color->c, color2.c);
01079 alt->getGray(&color2, gray);
01080 }
01081
01082 void GfxDeviceNColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
01083 GfxColor color2;
01084
01085 func->transform(color->c, color2.c);
01086 alt->getRGB(&color2, rgb);
01087 }
01088
01089 void GfxDeviceNColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
01090 GfxColor color2;
01091
01092 func->transform(color->c, color2.c);
01093 alt->getCMYK(&color2, cmyk);
01094 }
01095
01096
01097
01098
01099
01100 GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) {
01101 under = underA;
01102 }
01103
01104 GfxPatternColorSpace::~GfxPatternColorSpace() {
01105 if (under) {
01106 delete under;
01107 }
01108 }
01109
01110 GfxColorSpace *GfxPatternColorSpace::copy() const {
01111 return new GfxPatternColorSpace(under ? under->copy() :
01112 (GfxColorSpace *)NULL);
01113 }
01114
01115 GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
01116 GfxPatternColorSpace *cs;
01117 GfxColorSpace *underA;
01118 Object obj1;
01119
01120 if (arr->getLength() != 1 && arr->getLength() != 2) {
01121 error(-1, "Bad Pattern color space");
01122 return NULL;
01123 }
01124 underA = NULL;
01125 if (arr->getLength() == 2) {
01126 arr->get(1, &obj1);
01127 if (!(underA = GfxColorSpace::parse(&obj1))) {
01128 error(-1, "Bad Pattern color space (underlying color space)");
01129 obj1.free();
01130 return NULL;
01131 }
01132 obj1.free();
01133 }
01134 cs = new GfxPatternColorSpace(underA);
01135 return cs;
01136 }
01137
01138 void GfxPatternColorSpace::getGray(const GfxColor *, double *gray) const {
01139 *gray = 0;
01140 }
01141
01142 void GfxPatternColorSpace::getRGB(const GfxColor *, GfxRGB *rgb) const {
01143 rgb->r = rgb->g = rgb->b = 0;
01144 }
01145
01146 void GfxPatternColorSpace::getCMYK(const GfxColor *, GfxCMYK *cmyk) const {
01147 cmyk->c = cmyk->m = cmyk->y = 0;
01148 cmyk->k = 1;
01149 }
01150
01151
01152
01153
01154
01155 GfxPattern::GfxPattern(int typeA) {
01156 type = typeA;
01157 }
01158
01159 GfxPattern::~GfxPattern() {
01160 }
01161
01162 GfxPattern *GfxPattern::parse(Object *obj) {
01163 GfxPattern *pattern;
01164 Dict *dict;
01165 Object obj1;
01166
01167 pattern = NULL;
01168 if (obj->isStream()) {
01169 dict = obj->streamGetDict();
01170 dict->lookup("PatternType", &obj1);
01171 if (obj1.isInt() && obj1.getInt() == 1) {
01172 pattern = new GfxTilingPattern(dict, obj);
01173 }
01174 obj1.free();
01175 }
01176 return pattern;
01177 }
01178
01179
01180
01181
01182
01183 GfxTilingPattern::GfxTilingPattern(Dict *streamDict, Object *stream):
01184 GfxPattern(1)
01185 {
01186 Object obj1, obj2;
01187 int i;
01188
01189 if (streamDict->lookup("PaintType", &obj1)->isInt()) {
01190 paintType = obj1.getInt();
01191 } else {
01192 paintType = 1;
01193 error(-1, "Invalid or missing PaintType in pattern");
01194 }
01195 obj1.free();
01196 if (streamDict->lookup("TilingType", &obj1)->isInt()) {
01197 tilingType = obj1.getInt();
01198 } else {
01199 tilingType = 1;
01200 error(-1, "Invalid or missing TilingType in pattern");
01201 }
01202 obj1.free();
01203 bbox[0] = bbox[1] = 0;
01204 bbox[2] = bbox[3] = 1;
01205 if (streamDict->lookup("BBox", &obj1)->isArray() &&
01206 obj1.arrayGetLength() == 4) {
01207 for (i = 0; i < 4; ++i) {
01208 if (obj1.arrayGet(i, &obj2)->isNum()) {
01209 bbox[i] = obj2.getNum();
01210 }
01211 obj2.free();
01212 }
01213 } else {
01214 error(-1, "Invalid or missing BBox in pattern");
01215 }
01216 obj1.free();
01217 if (streamDict->lookup("XStep", &obj1)->isNum()) {
01218 xStep = obj1.getNum();
01219 } else {
01220 xStep = 1;
01221 error(-1, "Invalid or missing XStep in pattern");
01222 }
01223 obj1.free();
01224 if (streamDict->lookup("YStep", &obj1)->isNum()) {
01225 yStep = obj1.getNum();
01226 } else {
01227 yStep = 1;
01228 error(-1, "Invalid or missing YStep in pattern");
01229 }
01230 obj1.free();
01231 if (!streamDict->lookup("Resources", &resDict)->isDict()) {
01232 resDict.free();
01233 resDict.initNull();
01234 error(-1, "Invalid or missing Resources in pattern");
01235 }
01236 matrix[0] = 1; matrix[1] = 0;
01237 matrix[2] = 0; matrix[3] = 1;
01238 matrix[4] = 0; matrix[5] = 0;
01239 if (streamDict->lookup("Matrix", &obj1)->isArray() &&
01240 obj1.arrayGetLength() == 6) {
01241 for (i = 0; i < 6; ++i) {
01242 if (obj1.arrayGet(i, &obj2)->isNum()) {
01243 matrix[i] = obj2.getNum();
01244 }
01245 obj2.free();
01246 }
01247 }
01248 obj1.free();
01249 stream->copy(&contentStream);
01250 }
01251
01252 GfxTilingPattern::~GfxTilingPattern() {
01253 resDict.free();
01254 contentStream.free();
01255 }
01256
01257 GfxPattern *GfxTilingPattern::copy() {
01258 return new GfxTilingPattern(this);
01259 }
01260
01261 GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
01262 GfxPattern(1)
01263 {
01264 memcpy(this, pat, sizeof(GfxTilingPattern));
01265 pat->resDict.copy(&resDict);
01266 pat->contentStream.copy(&contentStream);
01267 }
01268
01269
01270
01271
01272
01273 GfxShading::GfxShading() {
01274 }
01275
01276 GfxShading::~GfxShading() {
01277 delete colorSpace;
01278 }
01279
01280 GfxShading *GfxShading::parse(Object *obj) {
01281 GfxShading *shading;
01282 int typeA;
01283 GfxColorSpace *colorSpaceA;
01284 GfxColor backgroundA;
01285 GBool hasBackgroundA;
01286 double xMinA, yMinA, xMaxA, yMaxA;
01287 GBool hasBBoxA;
01288 Object obj1, obj2;
01289 int i;
01290
01291 shading = NULL;
01292 if (obj->isDict()) {
01293
01294 if (!obj->dictLookup("ShadingType", &obj1)->isInt()) {
01295 error(-1, "Invalid ShadingType in shading dictionary");
01296 obj1.free();
01297 goto err1;
01298 }
01299 typeA = obj1.getInt();
01300 obj1.free();
01301
01302 obj->dictLookup("ColorSpace", &obj1);
01303 if (!(colorSpaceA = GfxColorSpace::parse(&obj1))) {
01304 error(-1, "Bad color space in shading dictionary");
01305 obj1.free();
01306 goto err1;
01307 }
01308 obj1.free();
01309
01310 for (i = 0; i < gfxColorMaxComps; ++i) {
01311 backgroundA.c[i] = 0;
01312 }
01313 hasBackgroundA = gFalse;
01314 if (obj->dictLookup("Background", &obj1)->isArray()) {
01315 if (obj1.arrayGetLength() == colorSpaceA->getNComps()) {
01316 hasBackgroundA = gTrue;
01317 for (i = 0; i < colorSpaceA->getNComps(); ++i) {
01318 backgroundA.c[i] = obj1.arrayGet(i, &obj2)->getNum();
01319 obj2.free();
01320 }
01321 } else {
01322 error(-1, "Bad Background in shading dictionary");
01323 }
01324 }
01325 obj1.free();
01326
01327 xMinA = yMinA = xMaxA = yMaxA = 0;
01328 hasBBoxA = gFalse;
01329 if (obj->dictLookup("BBox", &obj1)->isArray()) {
01330 if (obj1.arrayGetLength() == 4) {
01331 hasBBoxA = gTrue;
01332 xMinA = obj1.arrayGet(0, &obj2)->getNum();
01333 obj2.free();
01334 yMinA = obj1.arrayGet(1, &obj2)->getNum();
01335 obj2.free();
01336 xMaxA = obj1.arrayGet(2, &obj2)->getNum();
01337 obj2.free();
01338 yMaxA = obj1.arrayGet(3, &obj2)->getNum();
01339 obj2.free();
01340 } else {
01341 error(-1, "Bad BBox in shading dictionary");
01342 }
01343 }
01344 obj1.free();
01345
01346 switch (typeA) {
01347 case 2:
01348 shading = GfxAxialShading::parse(obj->getDict());
01349 break;
01350 case 3:
01351 shading = GfxRadialShading::parse(obj->getDict());
01352 break;
01353 default:
01354 error(-1, "Unimplemented shading type %d", typeA);
01355 goto err1;
01356 }
01357
01358 if (shading) {
01359 shading->type = typeA;
01360 shading->colorSpace = colorSpaceA;
01361 shading->background = backgroundA;
01362 shading->hasBackground = hasBackgroundA;
01363 shading->xMin = xMinA;
01364 shading->yMin = yMinA;
01365 shading->xMax = xMaxA;
01366 shading->yMax = yMaxA;
01367 shading->hasBBox = hasBBoxA;
01368 } else {
01369 delete colorSpaceA;
01370 }
01371 }
01372
01373 return shading;
01374
01375 err1:
01376 return NULL;
01377 }
01378
01379
01380
01381
01382
01383 GfxAxialShading::GfxAxialShading(double x0A, double y0A,
01384 double x1A, double y1A,
01385 double t0A, double t1A,
01386 Function **funcsA, int nFuncsA,
01387 GBool extend0A, GBool extend1A) {
01388 int i;
01389
01390 x0 = x0A;
01391 y0 = y0A;
01392 x1 = x1A;
01393 y1 = y1A;
01394 t0 = t0A;
01395 t1 = t1A;
01396 nFuncs = nFuncsA;
01397 for (i = 0; i < nFuncs; ++i) {
01398 funcs[i] = funcsA[i];
01399 }
01400 extend0 = extend0A;
01401 extend1 = extend1A;
01402 }
01403
01404 GfxAxialShading::~GfxAxialShading() {
01405 int i;
01406
01407 for (i = 0; i < nFuncs; ++i) {
01408 delete funcs[i];
01409 }
01410 }
01411
01412 GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
01413 double x0A, y0A, x1A, y1A;
01414 double t0A, t1A;
01415 Function *funcsA[gfxColorMaxComps];
01416 int nFuncsA;
01417 GBool extend0A, extend1A;
01418 Object obj1, obj2;
01419 int i;
01420
01421 x0A = y0A = x1A = y1A = 0;
01422 if (dict->lookup("Coords", &obj1)->isArray() &&
01423 obj1.arrayGetLength() == 4) {
01424 x0A = obj1.arrayGet(0, &obj2)->getNum();
01425 obj2.free();
01426 y0A = obj1.arrayGet(1, &obj2)->getNum();
01427 obj2.free();
01428 x1A = obj1.arrayGet(2, &obj2)->getNum();
01429 obj2.free();
01430 y1A = obj1.arrayGet(3, &obj2)->getNum();
01431 obj2.free();
01432 } else {
01433 error(-1, "Missing or invalid Coords in shading dictionary");
01434 goto err1;
01435 }
01436 obj1.free();
01437
01438 t0A = 0;
01439 t1A = 1;
01440 if (dict->lookup("Domain", &obj1)->isArray() &&
01441 obj1.arrayGetLength() == 2) {
01442 t0A = obj1.arrayGet(0, &obj2)->getNum();
01443 obj2.free();
01444 t1A = obj1.arrayGet(1, &obj2)->getNum();
01445 obj2.free();
01446 }
01447 obj1.free();
01448
01449 dict->lookup("Function", &obj1);
01450 if (obj1.isArray()) {
01451 nFuncsA = obj1.arrayGetLength();
01452 for (i = 0; i < nFuncsA; ++i) {
01453 obj1.arrayGet(i, &obj2);
01454 if (!(funcsA[i] = Function::parse(&obj2))) {
01455 obj1.free();
01456 obj2.free();
01457 goto err1;
01458 }
01459 obj2.free();
01460 }
01461 } else {
01462 nFuncsA = 1;
01463 if (!(funcsA[0] = Function::parse(&obj1))) {
01464 obj1.free();
01465 goto err1;
01466 }
01467 }
01468 obj1.free();
01469
01470 extend0A = extend1A = gFalse;
01471 if (dict->lookup("Extend", &obj1)->isArray() &&
01472 obj1.arrayGetLength() == 2) {
01473 extend0A = obj1.arrayGet(0, &obj2)->getBool();
01474 obj2.free();
01475 extend1A = obj1.arrayGet(1, &obj2)->getBool();
01476 obj2.free();
01477 }
01478 obj1.free();
01479
01480 return new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
01481 funcsA, nFuncsA, extend0A, extend1A);
01482
01483 err1:
01484 return NULL;
01485 }
01486
01487 void GfxAxialShading::getColor(double t, GfxColor *color) {
01488 int i;
01489
01490 for (i = 0; i < nFuncs; ++i) {
01491 funcs[i]->transform(&t, &color->c[i]);
01492 }
01493 }
01494
01495
01496
01497
01498
01499 GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A,
01500 double x1A, double y1A, double r1A,
01501 double t0A, double t1A,
01502 Function **funcsA, int nFuncsA,
01503 GBool extend0A, GBool extend1A) {
01504 int i;
01505
01506 x0 = x0A;
01507 y0 = y0A;
01508 r0 = r0A;
01509 x1 = x1A;
01510 y1 = y1A;
01511 r1 = r1A;
01512 t0 = t0A;
01513 t1 = t1A;
01514 nFuncs = nFuncsA;
01515 for (i = 0; i < nFuncs; ++i) {
01516 funcs[i] = funcsA[i];
01517 }
01518 extend0 = extend0A;
01519 extend1 = extend1A;
01520 }
01521
01522 GfxRadialShading::~GfxRadialShading() {
01523 int i;
01524
01525 for (i = 0; i < nFuncs; ++i) {
01526 delete funcs[i];
01527 }
01528 }
01529
01530 GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
01531 double x0A, y0A, r0A, x1A, y1A, r1A;
01532 double t0A, t1A;
01533 Function *funcsA[gfxColorMaxComps];
01534 int nFuncsA;
01535 GBool extend0A, extend1A;
01536 Object obj1, obj2;
01537 int i;
01538
01539 x0A = y0A = r0A = x1A = y1A = r1A = 0;
01540 if (dict->lookup("Coords", &obj1)->isArray() &&
01541 obj1.arrayGetLength() == 6) {
01542 x0A = obj1.arrayGet(0, &obj2)->getNum();
01543 obj2.free();
01544 y0A = obj1.arrayGet(1, &obj2)->getNum();
01545 obj2.free();
01546 r0A = obj1.arrayGet(2, &obj2)->getNum();
01547 obj2.free();
01548 x1A = obj1.arrayGet(3, &obj2)->getNum();
01549 obj2.free();
01550 y1A = obj1.arrayGet(4, &obj2)->getNum();
01551 obj2.free();
01552 r1A = obj1.arrayGet(5, &obj2)->getNum();
01553 obj2.free();
01554 } else {
01555 error(-1, "Missing or invalid Coords in shading dictionary");
01556 goto err1;
01557 }
01558 obj1.free();
01559
01560 t0A = 0;
01561 t1A = 1;
01562 if (dict->lookup("Domain", &obj1)->isArray() &&
01563 obj1.arrayGetLength() == 2) {
01564 t0A = obj1.arrayGet(0, &obj2)->getNum();
01565 obj2.free();
01566 t1A = obj1.arrayGet(1, &obj2)->getNum();
01567 obj2.free();
01568 }
01569 obj1.free();
01570
01571 dict->lookup("Function", &obj1);
01572 if (obj1.isArray()) {
01573 nFuncsA = obj1.arrayGetLength();
01574 for (i = 0; i < nFuncsA; ++i) {
01575 obj1.arrayGet(i, &obj2);
01576 if (!(funcsA[i] = Function::parse(&obj2))) {
01577 obj1.free();
01578 obj2.free();
01579 goto err1;
01580 }
01581 obj2.free();
01582 }
01583 } else {
01584 nFuncsA = 1;
01585 if (!(funcsA[0] = Function::parse(&obj1))) {
01586 obj1.free();
01587 goto err1;
01588 }
01589 }
01590 obj1.free();
01591
01592 extend0A = extend1A = gFalse;
01593 if (dict->lookup("Extend", &obj1)->isArray() &&
01594 obj1.arrayGetLength() == 2) {
01595 extend0A = obj1.arrayGet(0, &obj2)->getBool();
01596 obj2.free();
01597 extend1A = obj1.arrayGet(1, &obj2)->getBool();
01598 obj2.free();
01599 }
01600 obj1.free();
01601
01602 return new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
01603 funcsA, nFuncsA, extend0A, extend1A);
01604
01605 err1:
01606 return NULL;
01607 }
01608
01609 void GfxRadialShading::getColor(double t, GfxColor *color) {
01610 int i;
01611
01612 for (i = 0; i < nFuncs; ++i) {
01613 funcs[i]->transform(&t, &color->c[i]);
01614 }
01615 }
01616
01617
01618
01619
01620
01621 GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
01622 GfxColorSpace *colorSpaceA) {
01623 GfxIndexedColorSpace *indexedCS;
01624 GfxSeparationColorSpace *sepCS;
01625 int maxPixel, indexHigh;
01626 const Guchar *lookup2;
01627 const Function *sepFunc;
01628 Object obj;
01629 double x[gfxColorMaxComps];
01630 double y[gfxColorMaxComps];
01631 int i, j, k;
01632
01633 ok = gTrue;
01634
01635
01636 bits = bitsA;
01637 maxPixel = (1 << bits) - 1;
01638 colorSpace = colorSpaceA;
01639
01640
01641 if (decode->isNull()) {
01642 nComps = colorSpace->getNComps();
01643 colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
01644 } else if (decode->isArray()) {
01645 nComps = decode->arrayGetLength() / 2;
01646 if (nComps != colorSpace->getNComps()) {
01647 goto err1;
01648 }
01649 for (i = 0; i < nComps; ++i) {
01650 decode->arrayGet(2*i, &obj);
01651 if (!obj.isNum()) {
01652 goto err2;
01653 }
01654 decodeLow[i] = obj.getNum();
01655 obj.free();
01656 decode->arrayGet(2*i+1, &obj);
01657 if (!obj.isNum()) {
01658 goto err2;
01659 }
01660 decodeRange[i] = obj.getNum() - decodeLow[i];
01661 obj.free();
01662 }
01663 } else {
01664 goto err1;
01665 }
01666
01667
01668
01669
01670
01671
01672
01673
01674 colorSpace2 = NULL;
01675 nComps2 = 0;
01676 if (colorSpace->getMode() == csIndexed) {
01677
01678
01679
01680 indexedCS = (GfxIndexedColorSpace *)colorSpace;
01681 colorSpace2 = indexedCS->getBase();
01682 indexHigh = indexedCS->getIndexHigh();
01683 nComps2 = colorSpace2->getNComps();
01684 lookup = (double *)gmalloc((indexHigh + 1) * nComps2 * sizeof(double));
01685 lookup2 = indexedCS->getLookup();
01686 colorSpace2->getDefaultRanges(x, y, indexHigh);
01687 for (i = 0; i <= indexHigh; ++i) {
01688 j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
01689 for (k = 0; k < nComps2; ++k) {
01690 lookup[j*nComps2 + k] = x[k] + (lookup2[i*nComps2 + k] / 255.0) * y[k];
01691 }
01692 }
01693 } else if (colorSpace->getMode() == csSeparation) {
01694 sepCS = (GfxSeparationColorSpace *)colorSpace;
01695 colorSpace2 = sepCS->getAlt();
01696 nComps2 = colorSpace2->getNComps();
01697 lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
01698 sepFunc = sepCS->getFunc();
01699 for (i = 0; i <= maxPixel; ++i) {
01700 x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
01701 sepFunc->transform(x, y);
01702 for (k = 0; k < nComps2; ++k) {
01703 lookup[i*nComps2 + k] = y[k];
01704 }
01705 }
01706 } else {
01707 lookup = (double *)gmalloc((maxPixel + 1) * nComps * sizeof(double));
01708 for (i = 0; i <= maxPixel; ++i) {
01709 for (k = 0; k < nComps; ++k) {
01710 lookup[i*nComps + k] = decodeLow[k] +
01711 (i * decodeRange[k]) / maxPixel;
01712 }
01713 }
01714 }
01715
01716 return;
01717
01718 err2:
01719 obj.free();
01720 err1:
01721 ok = gFalse;
01722 }
01723
01724 GfxImageColorMap::~GfxImageColorMap() {
01725 delete colorSpace;
01726 gfree(lookup);
01727 }
01728
01729 void GfxImageColorMap::getGray(Guchar *x, double *gray) {
01730 GfxColor color;
01731 double *p;
01732 int i;
01733
01734 if (colorSpace2) {
01735 p = &lookup[x[0] * nComps2];
01736 for (i = 0; i < nComps2; ++i) {
01737 color.c[i] = *p++;
01738 }
01739 colorSpace2->getGray(&color, gray);
01740 } else {
01741 for (i = 0; i < nComps; ++i) {
01742 color.c[i] = lookup[x[i] * nComps + i];
01743 }
01744 colorSpace->getGray(&color, gray);
01745 }
01746 }
01747
01748 void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
01749 GfxColor color;
01750 double *p;
01751 int i;
01752
01753 if (colorSpace2) {
01754 p = &lookup[x[0] * nComps2];
01755 for (i = 0; i < nComps2; ++i) {
01756 color.c[i] = *p++;
01757 }
01758 colorSpace2->getRGB(&color, rgb);
01759 } else {
01760 for (i = 0; i < nComps; ++i) {
01761 color.c[i] = lookup[x[i] * nComps + i];
01762 }
01763 colorSpace->getRGB(&color, rgb);
01764 }
01765 }
01766
01767 void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
01768 GfxColor color;
01769 double *p;
01770 int i;
01771
01772 if (colorSpace2) {
01773 p = &lookup[x[0] * nComps2];
01774 for (i = 0; i < nComps2; ++i) {
01775 color.c[i] = *p++;
01776 }
01777 colorSpace2->getCMYK(&color, cmyk);
01778 } else {
01779 for (i = 0; i < nComps; ++i) {
01780 color.c[i] = lookup[x[i] * nComps + i];
01781 }
01782 colorSpace->getCMYK(&color, cmyk);
01783 }
01784 }
01785
01786
01787
01788
01789
01790 GfxSubpath::GfxSubpath(double x1, double y1) {
01791 size = 16;
01792 x = (double *)gmalloc(size * sizeof(double));
01793 y = (double *)gmalloc(size * sizeof(double));
01794 curve = (GBool *)gmalloc(size * sizeof(GBool));
01795 n = 1;
01796 x[0] = x1;
01797 y[0] = y1;
01798 curve[0] = gFalse;
01799 closed = gFalse;
01800 }
01801
01802 GfxSubpath::~GfxSubpath() {
01803 gfree(x);
01804 gfree(y);
01805 gfree(curve);
01806 }
01807
01808
01809 GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
01810 size = subpath->size;
01811 n = subpath->n;
01812 x = (double *)gmalloc(size * sizeof(double));
01813 y = (double *)gmalloc(size * sizeof(double));
01814 curve = (GBool *)gmalloc(size * sizeof(GBool));
01815 memcpy(x, subpath->x, n * sizeof(double));
01816 memcpy(y, subpath->y, n * sizeof(double));
01817 memcpy(curve, subpath->curve, n * sizeof(GBool));
01818 closed = subpath->closed;
01819 }
01820
01821 void GfxSubpath::lineTo(double x1, double y1) {
01822 if (n >= size) {
01823 size += 16;
01824 x = (double *)grealloc(x, size * sizeof(double));
01825 y = (double *)grealloc(y, size * sizeof(double));
01826 curve = (GBool *)grealloc(curve, size * sizeof(GBool));
01827 }
01828 x[n] = x1;
01829 y[n] = y1;
01830 curve[n] = gFalse;
01831 ++n;
01832 }
01833
01834 void GfxSubpath::curveTo(double x1, double y1, double x2, double y2,
01835 double x3, double y3) {
01836 if (n+3 > size) {
01837 size += 16;
01838 x = (double *)grealloc(x, size * sizeof(double));
01839 y = (double *)grealloc(y, size * sizeof(double));
01840 curve = (GBool *)grealloc(curve, size * sizeof(GBool));
01841 }
01842 x[n] = x1;
01843 y[n] = y1;
01844 x[n+1] = x2;
01845 y[n+1] = y2;
01846 x[n+2] = x3;
01847 y[n+2] = y3;
01848 curve[n] = curve[n+1] = gTrue;
01849 curve[n+2] = gFalse;
01850 n += 3;
01851 }
01852
01853 void GfxSubpath::close() {
01854 if (x[n-1] != x[0] || y[n-1] != y[0]) {
01855 lineTo(x[0], y[0]);
01856 }
01857 closed = gTrue;
01858 }
01859
01860 GfxPath::GfxPath() {
01861 justMoved = gFalse;
01862 size = 16;
01863 n = 0;
01864 firstX = firstY = 0;
01865 subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
01866 }
01867
01868 GfxPath::~GfxPath() {
01869 int i;
01870
01871 for (i = 0; i < n; ++i)
01872 delete subpaths[i];
01873 gfree(subpaths);
01874 }
01875
01876
01877 GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1,
01878 GfxSubpath **subpaths1, int n1, int size1) {
01879 int i;
01880
01881 justMoved = justMoved1;
01882 firstX = firstX1;
01883 firstY = firstY1;
01884 size = size1;
01885 n = n1;
01886 subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
01887 for (i = 0; i < n; ++i)
01888 subpaths[i] = subpaths1[i]->copy();
01889 }
01890
01891 void GfxPath::moveTo(double x, double y) {
01892 justMoved = gTrue;
01893 firstX = x;
01894 firstY = y;
01895 }
01896
01897 void GfxPath::lineTo(double x, double y) {
01898 if (justMoved) {
01899 if (n >= size) {
01900 size += 16;
01901 subpaths = (GfxSubpath **)
01902 grealloc(subpaths, size * sizeof(GfxSubpath *));
01903 }
01904 subpaths[n] = new GfxSubpath(firstX, firstY);
01905 ++n;
01906 justMoved = gFalse;
01907 }
01908 subpaths[n-1]->lineTo(x, y);
01909 }
01910
01911 void GfxPath::curveTo(double x1, double y1, double x2, double y2,
01912 double x3, double y3) {
01913 if (justMoved) {
01914 if (n >= size) {
01915 size += 16;
01916 subpaths = (GfxSubpath **)
01917 grealloc(subpaths, size * sizeof(GfxSubpath *));
01918 }
01919 subpaths[n] = new GfxSubpath(firstX, firstY);
01920 ++n;
01921 justMoved = gFalse;
01922 }
01923 subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
01924 }
01925
01926 void GfxPath::close() {
01927
01928
01929 if (justMoved) {
01930 if (n >= size) {
01931 size += 16;
01932 subpaths = (GfxSubpath **)
01933 grealloc(subpaths, size * sizeof(GfxSubpath *));
01934 }
01935 subpaths[n] = new GfxSubpath(firstX, firstY);
01936 ++n;
01937 justMoved = gFalse;
01938 }
01939 subpaths[n-1]->close();
01940 }
01941
01942
01943
01944
01945
01946 GfxState::GfxState(double dpi, PDFRectangle *pageBox, int rotate,
01947 GBool upsideDown) {
01948 double k;
01949
01950 px1 = pageBox->x1;
01951 py1 = pageBox->y1;
01952 px2 = pageBox->x2;
01953 py2 = pageBox->y2;
01954 k = dpi / 72.0;
01955 if (rotate == 90) {
01956 ctm[0] = 0;
01957 ctm[1] = upsideDown ? k : -k;
01958 ctm[2] = k;
01959 ctm[3] = 0;
01960 ctm[4] = -k * py1;
01961 ctm[5] = k * (upsideDown ? -px1 : px2);
01962 pageWidth = k * (py2 - py1);
01963 pageHeight = k * (px2 - px1);
01964 } else if (rotate == 180) {
01965 ctm[0] = -k;
01966 ctm[1] = 0;
01967 ctm[2] = 0;
01968 ctm[3] = upsideDown ? k : -k;
01969 ctm[4] = k * px2;
01970 ctm[5] = k * (upsideDown ? -py1 : py2);
01971 pageWidth = k * (px2 - px1);
01972 pageHeight = k * (py2 - py1);
01973 } else if (rotate == 270) {
01974 ctm[0] = 0;
01975 ctm[1] = upsideDown ? -k : k;
01976 ctm[2] = -k;
01977 ctm[3] = 0;
01978 ctm[4] = k * py2;
01979 ctm[5] = k * (upsideDown ? px2 : -px1);
01980 pageWidth = k * (py2 - py1);
01981 pageHeight = k * (px2 - px1);
01982 } else {
01983 ctm[0] = k;
01984 ctm[1] = 0;
01985 ctm[2] = 0;
01986 ctm[3] = upsideDown ? -k : k;
01987 ctm[4] = -k * px1;
01988 ctm[5] = k * (upsideDown ? py2 : -py1);
01989 pageWidth = k * (px2 - px1);
01990 pageHeight = k * (py2 - py1);
01991 }
01992
01993 fillColorSpace = new GfxDeviceGrayColorSpace();
01994 strokeColorSpace = new GfxDeviceGrayColorSpace();
01995 fillColor.c[0] = 0;
01996 strokeColor.c[0] = 0;
01997 fillPattern = NULL;
01998 strokePattern = NULL;
01999 fillOpacity = 1;
02000 strokeOpacity = 1;
02001
02002 lineWidth = 1;
02003 lineDash = NULL;
02004 lineDashLength = 0;
02005 lineDashStart = 0;
02006 flatness = 0;
02007 lineJoin = 0;
02008 lineCap = 0;
02009 miterLimit = 10;
02010
02011 font = NULL;
02012 fontSize = 0;
02013 textMat[0] = 1; textMat[1] = 0;
02014 textMat[2] = 0; textMat[3] = 1;
02015 textMat[4] = 0; textMat[5] = 0;
02016 charSpace = 0;
02017 wordSpace = 0;
02018 horizScaling = 1;
02019 leading = 0;
02020 rise = 0;
02021 render = 0;
02022
02023 path = new GfxPath();
02024 curX = curY = 0;
02025 lineX = lineY = 0;
02026
02027 clipXMin = 0;
02028 clipYMin = 0;
02029 clipXMax = pageWidth;
02030 clipYMax = pageHeight;
02031
02032 saved = NULL;
02033 }
02034
02035 GfxState::~GfxState() {
02036 if (fillColorSpace) {
02037 delete fillColorSpace;
02038 }
02039 if (strokeColorSpace) {
02040 delete strokeColorSpace;
02041 }
02042 if (fillPattern) {
02043 delete fillPattern;
02044 }
02045 if (strokePattern) {
02046 delete strokePattern;
02047 }
02048 gfree(lineDash);
02049 if (path) {
02050
02051 delete path;
02052 }
02053 if (saved) {
02054 delete saved;
02055 }
02056 }
02057
02058
02059 GfxState::GfxState(const GfxState *state) {
02060 memcpy(this, state, sizeof(GfxState));
02061 if (fillColorSpace) {
02062 fillColorSpace = state->fillColorSpace->copy();
02063 }
02064 if (strokeColorSpace) {
02065 strokeColorSpace = state->strokeColorSpace->copy();
02066 }
02067 if (fillPattern) {
02068 fillPattern = state->fillPattern->copy();
02069 }
02070 if (strokePattern) {
02071 strokePattern = state->strokePattern->copy();
02072 }
02073 if (lineDashLength > 0) {
02074 lineDash = (double *)gmalloc(lineDashLength * sizeof(double));
02075 memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
02076 }
02077 saved = NULL;
02078 }
02079
02080 void GfxState::getUserClipBBox(double *xMin, double *yMin,
02081 double *xMax, double *yMax) const {
02082 double ictm[6];
02083 double xMin1, yMin1, xMax1, yMax1, det, tx, ty;
02084
02085
02086 det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
02087 ictm[0] = ctm[3] * det;
02088 ictm[1] = -ctm[1] * det;
02089 ictm[2] = -ctm[2] * det;
02090 ictm[3] = ctm[0] * det;
02091 ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
02092 ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
02093
02094
02095
02096 xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4];
02097 yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5];
02098 tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4];
02099 ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5];
02100 if (tx < xMin1) {
02101 xMin1 = tx;
02102 } else if (tx > xMax1) {
02103 xMax1 = tx;
02104 }
02105 if (ty < yMin1) {
02106 yMin1 = ty;
02107 } else if (ty > yMax1) {
02108 yMax1 = ty;
02109 }
02110 tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4];
02111 ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5];
02112 if (tx < xMin1) {
02113 xMin1 = tx;
02114 } else if (tx > xMax1) {
02115 xMax1 = tx;
02116 }
02117 if (ty < yMin1) {
02118 yMin1 = ty;
02119 } else if (ty > yMax1) {
02120 yMax1 = ty;
02121 }
02122 tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4];
02123 ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5];
02124 if (tx < xMin1) {
02125 xMin1 = tx;
02126 } else if (tx > xMax1) {
02127 xMax1 = tx;
02128 }
02129 if (ty < yMin1) {
02130 yMin1 = ty;
02131 } else if (ty > yMax1) {
02132 yMax1 = ty;
02133 }
02134
02135 *xMin = xMin1;
02136 *yMin = yMin1;
02137 *xMax = xMax1;
02138 *yMax = yMax1;
02139 }
02140
02141 double GfxState::transformWidth(double w) {
02142 double x, y;
02143
02144 x = ctm[0] + ctm[2];
02145 y = ctm[1] + ctm[3];
02146 return w * sqrt(0.5 * (x * x + y * y));
02147 }
02148
02149 double GfxState::getTransformedFontSize() {
02150 double x1, y1, x2, y2;
02151
02152 x1 = textMat[2] * fontSize;
02153 y1 = textMat[3] * fontSize;
02154 x2 = ctm[0] * x1 + ctm[2] * y1;
02155 y2 = ctm[1] * x1 + ctm[3] * y1;
02156 return sqrt(x2 * x2 + y2 * y2);
02157 }
02158
02159 void GfxState::getFontTransMat(double *m11, double *m12,
02160 double *m21, double *m22) {
02161 *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize;
02162 *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize;
02163 *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
02164 *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
02165 }
02166
02167 void GfxState::setCTM(double a, double b, double c,
02168 double d, double e, double f) {
02169 int i;
02170
02171 ctm[0] = a;
02172 ctm[1] = b;
02173 ctm[2] = c;
02174 ctm[3] = d;
02175 ctm[4] = e;
02176 ctm[5] = f;
02177
02178
02179 for (i = 0; i < 6; ++i) {
02180 if (ctm[i] > 1e10) {
02181 ctm[i] = 1e10;
02182 } else if (ctm[i] < -1e10) {
02183 ctm[i] = -1e10;
02184 }
02185 }
02186 }
02187
02188 void GfxState::concatCTM(double a, double b, double c,
02189 double d, double e, double f) {
02190 double a1 = ctm[0];
02191 double b1 = ctm[1];
02192 double c1 = ctm[2];
02193 double d1 = ctm[3];
02194 int i;
02195
02196 ctm[0] = a * a1 + b * c1;
02197 ctm[1] = a * b1 + b * d1;
02198 ctm[2] = c * a1 + d * c1;
02199 ctm[3] = c * b1 + d * d1;
02200 ctm[4] = e * a1 + f * c1 + ctm[4];
02201 ctm[5] = e * b1 + f * d1 + ctm[5];
02202
02203
02204 for (i = 0; i < 6; ++i) {
02205 if (ctm[i] > 1e10) {
02206 ctm[i] = 1e10;
02207 } else if (ctm[i] < -1e10) {
02208 ctm[i] = -1e10;
02209 }
02210 }
02211 }
02212
02213 void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
02214 if (fillColorSpace) {
02215 delete fillColorSpace;
02216 }
02217 fillColorSpace = colorSpace;
02218 }
02219
02220 void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
02221 if (strokeColorSpace) {
02222 delete strokeColorSpace;
02223 }
02224 strokeColorSpace = colorSpace;
02225 }
02226
02227 void GfxState::setFillPattern(GfxPattern *pattern) {
02228 if (fillPattern) {
02229 delete fillPattern;
02230 }
02231 fillPattern = pattern;
02232 }
02233
02234 void GfxState::setStrokePattern(GfxPattern *pattern) {
02235 if (strokePattern) {
02236 delete strokePattern;
02237 }
02238 strokePattern = pattern;
02239 }
02240
02241 void GfxState::setLineDash(double *dash, int length, double start) {
02242 if (lineDash)
02243 gfree(lineDash);
02244 lineDash = dash;
02245 lineDashLength = length;
02246 lineDashStart = start;
02247 }
02248
02249 void GfxState::clearPath() {
02250 delete path;
02251 path = new GfxPath();
02252 }
02253
02254 void GfxState::clip() {
02255 double xMin, yMin, xMax, yMax, x, y;
02256 GfxSubpath *subpath;
02257 int i, j;
02258
02259 xMin = xMax = yMin = yMax = 0;
02260 for (i = 0; i < path->getNumSubpaths(); ++i) {
02261 subpath = path->getSubpath(i);
02262 for (j = 0; j < subpath->getNumPoints(); ++j) {
02263 transform(subpath->getX(j), subpath->getY(j), &x, &y);
02264 if (i == 0 && j == 0) {
02265 xMin = xMax = x;
02266 yMin = yMax = y;
02267 } else {
02268 if (x < xMin) {
02269 xMin = x;
02270 } else if (x > xMax) {
02271 xMax = x;
02272 }
02273 if (y < yMin) {
02274 yMin = y;
02275 } else if (y > yMax) {
02276 yMax = y;
02277 }
02278 }
02279 }
02280 }
02281 if (xMin > clipXMin) {
02282 clipXMin = xMin;
02283 }
02284 if (yMin > clipYMin) {
02285 clipYMin = yMin;
02286 }
02287 if (xMax < clipXMax) {
02288 clipXMax = xMax;
02289 }
02290 if (yMax < clipYMax) {
02291 clipYMax = yMax;
02292 }
02293 }
02294
02295 void GfxState::textShift(double tx, double ty) {
02296 double dx, dy;
02297
02298 textTransformDelta(tx, ty, &dx, &dy);
02299 curX += dx;
02300 curY += dy;
02301 }
02302
02303 void GfxState::shift(double dx, double dy) {
02304 curX += dx;
02305 curY += dy;
02306 }
02307
02308 GfxState *GfxState::save() {
02309 GfxState *newState;
02310
02311 newState = copy();
02312 newState->saved = this;
02313 return newState;
02314 }
02315
02316 GfxState *GfxState::restore() {
02317 GfxState *oldState;
02318
02319 if (saved) {
02320 oldState = saved;
02321
02322
02323 oldState->path = path;
02324 oldState->curX = curX;
02325 oldState->curY = curY;
02326 oldState->lineX = lineX;
02327 oldState->lineY = lineY;
02328
02329 path = NULL;
02330 saved = NULL;
02331 delete this;
02332
02333 } else {
02334 oldState = this;
02335 }
02336
02337 return oldState;
02338 }