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