Ignore:
Timestamp:
Dec 30, 2009, 7:13:45 PM (12 years ago)
Author:
rbri
Message:

PDF plugin: Poppler library updated to version 0.12.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/poppler/mypoppler/poppler/GfxState.cc

    r261 r277  
    1717// Copyright (C) 2006, 2007 Jeff Muizelaar <jeff@infidigm.net>
    1818// Copyright (C) 2006 Carlos Garcia Campos <carlosgc@gnome.org>
    19 // Copyright (C) 2006-2008 Albert Astals Cid <aacid@kde.org>
     19// Copyright (C) 2006-2009 Albert Astals Cid <aacid@kde.org>
     20// Copyright (C) 2009 Koji Otani <sho@bbr.jp>
     21// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag@alfa.de>
     22// Copyright (C) 2009 Christian Persch <chpe@gnome.org>
    2023//
    2124// To see a description of the changes please see the Changelog file that
     
    3841#include "Array.h"
    3942#include "Page.h"
     43#include "Gfx.h"
    4044#include "GfxState.h"
     45#include "GfxState_helpers.h"
    4146#include "GfxFont.h"
    42 
    43 //------------------------------------------------------------------------
    44 
    45 static inline GfxColorComp clip01(GfxColorComp x) {
    46   return (x < 0) ? 0 : (x > gfxColorComp1) ? gfxColorComp1 : x;
    47 }
    48 
    49 static inline double clip01(double x) {
    50   return (x < 0) ? 0 : (x > 1) ? 1 : x;
    51 }
     47#include "GlobalParams.h"
     48#include "PopplerCache.h"
     49
     50//------------------------------------------------------------------------
    5251
    5352GBool Matrix::invertTo(Matrix *other)
     
    127126#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *)))
    128127
     128#ifdef USE_CMS
     129
     130#include <lcms.h>
     131
     132#define COLOR_PROFILE_DIR "/ColorProfiles/"
     133#define GLOBAL_COLOR_PROFILE_DIR POPPLER_DATADIR COLOR_PROFILE_DIR
     134
     135void GfxColorTransform::doTransform(void *in, void *out, unsigned int size) {
     136  cmsDoTransform(transform, in, out, size);
     137}
     138
     139// transformA should be a cmsHTRANSFORM
     140GfxColorTransform::GfxColorTransform(void *transformA) {
     141  transform = transformA;
     142  refCount = 1;
     143}
     144
     145GfxColorTransform::~GfxColorTransform() {
     146  cmsDeleteTransform(transform);
     147}
     148
     149void GfxColorTransform::ref() {
     150  refCount++;
     151}
     152
     153unsigned int GfxColorTransform::unref() {
     154  return --refCount;
     155}
     156
     157static cmsHPROFILE RGBProfile = NULL;
     158static GooString *displayProfileName = NULL; // display profile file Name
     159static cmsHPROFILE displayProfile = NULL; // display profile
     160static unsigned int displayPixelType = 0;
     161static GfxColorTransform *XYZ2DisplayTransform = NULL;
     162
     163// convert color space signature to cmsColor type
     164static unsigned int getCMSColorSpaceType(icColorSpaceSignature cs);
     165static unsigned int getCMSNChannels(icColorSpaceSignature cs);
     166static cmsHPROFILE loadColorProfile(const char *fileName);
     167
     168void GfxColorSpace::setDisplayProfile(void *displayProfileA) {
     169  displayProfile = displayProfileA;
     170}
     171
     172void GfxColorSpace::setDisplayProfileName(GooString *name) {
     173  displayProfileName = name->copy();
     174}
     175
     176cmsHPROFILE GfxColorSpace::getRGBProfile() {
     177  return RGBProfile;
     178}
     179
     180cmsHPROFILE GfxColorSpace::getDisplayProfile() {
     181  return displayProfile;
     182}
     183
     184#endif
     185
    129186//------------------------------------------------------------------------
    130187// GfxColorSpace
     
    137194}
    138195
    139 GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
     196GfxColorSpace *GfxColorSpace::parse(Object *csObj, Gfx *gfx) {
    140197  GfxColorSpace *cs;
    141198  Object obj1;
     
    169226      cs = GfxLabColorSpace::parse(csObj->getArray());
    170227    } else if (obj1.isName("ICCBased")) {
    171       cs = GfxICCBasedColorSpace::parse(csObj->getArray());
     228      cs = GfxICCBasedColorSpace::parse(csObj->getArray(), gfx);
    172229    } else if (obj1.isName("Indexed") || obj1.isName("I")) {
    173       cs = GfxIndexedColorSpace::parse(csObj->getArray());
     230      cs = GfxIndexedColorSpace::parse(csObj->getArray(), gfx);
    174231    } else if (obj1.isName("Separation")) {
    175       cs = GfxSeparationColorSpace::parse(csObj->getArray());
     232      cs = GfxSeparationColorSpace::parse(csObj->getArray(), gfx);
    176233    } else if (obj1.isName("DeviceN")) {
    177       cs = GfxDeviceNColorSpace::parse(csObj->getArray());
     234      cs = GfxDeviceNColorSpace::parse(csObj->getArray(), gfx);
    178235    } else if (obj1.isName("Pattern")) {
    179       cs = GfxPatternColorSpace::parse(csObj->getArray());
     236      cs = GfxPatternColorSpace::parse(csObj->getArray(), gfx);
    180237    } else {
    181238      error(-1, "Bad color space");
     
    206263}
    207264
    208 void GfxColorSpace::getRGBLine(Guchar *in, unsigned int *out, int length) {
    209   int i, j, n;
    210   GfxColor color;
    211   GfxRGB rgb;
    212 
    213   n = getNComps();
    214   for (i = 0; i < length; i++) {
    215    
    216     for (j = 0; j < n; j++)
    217       color.c[j] = in[i * n + j] * 256;
    218 
    219     getRGB (&color, &rgb);
    220     out[i] =
    221         ((int) colToByte(rgb.r) << 16) |
    222         ((int) colToByte(rgb.g) << 8) |
    223         ((int) colToByte(rgb.b) << 0);
    224   }
    225 }
    226 
    227 void GfxColorSpace::getGrayLine(Guchar *in, unsigned char *out, int length) {
    228   int i, j, n;
    229   GfxColor color;
    230   GfxGray gray;
    231 
    232   n = getNComps();
    233   for (i = 0; i < length; i++) {
    234    
    235     for (j = 0; j < n; j++)
    236       color.c[j] = in[i * n + j] * 256;
    237 
    238     getGray (&color, &gray);
    239     out[i] = colToByte(gray);
    240   }
    241 }
    242 
     265#ifdef USE_CMS
     266cmsHPROFILE loadColorProfile(const char *fileName)
     267{
     268  cmsHPROFILE hp = NULL;
     269  FILE *fp;
     270
     271  if (fileName[0] == '/') {
     272    // full path
     273    // check if open the file
     274    if ((fp = fopen(fileName,"r")) != NULL) {
     275      fclose(fp);
     276      hp = cmsOpenProfileFromFile(fileName,"r");
     277    }
     278    return hp;
     279  }
     280  // try to load from user directory
     281  GooString *path = globalParams->getBaseDir();
     282  path->append(COLOR_PROFILE_DIR);
     283  path->append(fileName);
     284  // check if open the file
     285  if ((fp = fopen(path->getCString(),"r")) != NULL) {
     286    fclose(fp);
     287    hp = cmsOpenProfileFromFile(path->getCString(),"r");
     288  }
     289  delete path;
     290  if (hp == NULL) {
     291    // load from global directory
     292    path = new GooString(GLOBAL_COLOR_PROFILE_DIR);
     293    path->append(fileName);
     294    // check if open the file
     295    if ((fp = fopen(path->getCString(),"r")) != NULL) {
     296      fclose(fp);
     297      hp = cmsOpenProfileFromFile(path->getCString(),"r");
     298    }
     299    delete path;
     300  }
     301  return hp;
     302}
     303
     304static int CMSError(int ecode, const char *msg)
     305{
     306    error(-1, "%s", msg);
     307    return 1;
     308}
     309
     310int GfxColorSpace::setupColorProfiles()
     311{
     312  static GBool initialized = gFalse;
     313  cmsHTRANSFORM transform;
     314  unsigned int nChannels;
     315
     316  // do only once
     317  if (initialized) return 0;
     318  initialized = gTrue;
     319
     320  // set error handlor
     321  cmsSetErrorHandler(CMSError);
     322
     323  if (displayProfile == NULL) {
     324    // load display profile if it was not already loaded.
     325    if (displayProfileName == NULL) {
     326      displayProfile = loadColorProfile("display.icc");
     327    } else if (displayProfileName->getLength() > 0) {
     328      displayProfile = loadColorProfile(displayProfileName->getCString());
     329    }
     330  }
     331  // load RGB profile
     332  RGBProfile = loadColorProfile("RGB.icc");
     333  if (RGBProfile == NULL) {
     334    /* use built in sRGB profile */
     335    RGBProfile = cmsCreate_sRGBProfile();
     336  }
     337  // create transforms
     338  if (displayProfile != NULL) {
     339    displayPixelType = getCMSColorSpaceType(cmsGetColorSpace(displayProfile));
     340    nChannels = getCMSNChannels(cmsGetColorSpace(displayProfile));
     341    // create transform from XYZ
     342    cmsHPROFILE XYZProfile = cmsCreateXYZProfile();
     343    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
     344           displayProfile,
     345           COLORSPACE_SH(displayPixelType) |
     346             CHANNELS_SH(nChannels) | BYTES_SH(1),
     347          INTENT_RELATIVE_COLORIMETRIC,0)) == 0) {
     348      error(-1, "Can't create Lab transform");
     349    } else {
     350      XYZ2DisplayTransform = new GfxColorTransform(transform);
     351    }
     352    cmsCloseProfile(XYZProfile);
     353  }
     354  return 0;
     355}
     356
     357unsigned int getCMSColorSpaceType(icColorSpaceSignature cs)
     358{
     359    switch (cs) {
     360    case icSigXYZData:
     361      return PT_XYZ;
     362      break;
     363    case icSigLabData:
     364      return PT_Lab;
     365      break;
     366    case icSigLuvData:
     367      return PT_YUV;
     368      break;
     369    case icSigYCbCrData:
     370      return PT_YCbCr;
     371      break;
     372    case icSigYxyData:
     373      return PT_Yxy;
     374      break;
     375    case icSigRgbData:
     376      return PT_RGB;
     377      break;
     378    case icSigGrayData:
     379      return PT_GRAY;
     380      break;
     381    case icSigHsvData:
     382      return PT_HSV;
     383      break;
     384    case icSigHlsData:
     385      return PT_HLS;
     386      break;
     387    case icSigCmykData:
     388      return PT_CMYK;
     389      break;
     390    case icSigCmyData:
     391      return PT_CMY;
     392      break;
     393    case icSig2colorData:
     394    case icSig3colorData:
     395    case icSig4colorData:
     396    case icSig5colorData:
     397    case icSig6colorData:
     398    case icSig7colorData:
     399    case icSig8colorData:
     400    case icSig9colorData:
     401    case icSig10colorData:
     402    case icSig11colorData:
     403    case icSig12colorData:
     404    case icSig13colorData:
     405    case icSig14colorData:
     406    case icSig15colorData:
     407    default:
     408      break;
     409    }
     410    return PT_RGB;
     411}
     412
     413unsigned int getCMSNChannels(icColorSpaceSignature cs)
     414{
     415    switch (cs) {
     416    case icSigXYZData:
     417    case icSigLuvData:
     418    case icSigLabData:
     419    case icSigYCbCrData:
     420    case icSigYxyData:
     421    case icSigRgbData:
     422    case icSigHsvData:
     423    case icSigHlsData:
     424    case icSigCmyData:
     425    case icSig3colorData:
     426      return 3;
     427      break;
     428    case icSigGrayData:
     429      return 1;
     430      break;
     431    case icSigCmykData:
     432    case icSig4colorData:
     433      return 4;
     434      break;
     435    case icSig2colorData:
     436      return 2;
     437      break;
     438    case icSig5colorData:
     439      return 5;
     440      break;
     441    case icSig6colorData:
     442      return 6;
     443      break;
     444    case icSig7colorData:
     445      return 7;
     446      break;
     447    case icSig8colorData:
     448      return 8;
     449      break;
     450    case icSig9colorData:
     451      return 9;
     452      break;
     453    case icSig10colorData:
     454      return 10;
     455      break;
     456    case icSig11colorData:
     457      return 11;
     458      break;
     459    case icSig12colorData:
     460      return 12;
     461      break;
     462    case icSig13colorData:
     463      return 13;
     464      break;
     465    case icSig14colorData:
     466      return 14;
     467      break;
     468    case icSig15colorData:
     469      return 15;
     470    default:
     471      break;
     472    }
     473    return 3;
     474}
     475
     476#endif
    243477
    244478//------------------------------------------------------------------------
     
    311545  return cs;
    312546}
     547
     548// This is the inverse of MatrixLMN in Example 4.10 from the PostScript
     549// Language Reference, Third Edition.
     550static const double xyzrgb[3][3] = {
     551  {  3.240449, -1.537136, -0.498531 },
     552  { -0.969265,  1.876011,  0.041556 },
     553  {  0.055643, -0.204026,  1.057229 }
     554};
    313555
    314556GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
     
    354596  obj2.free();
    355597  obj1.free();
     598
     599  cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
     600                xyzrgb[0][1] * cs->whiteY +
     601                xyzrgb[0][2] * cs->whiteZ);
     602  cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
     603                xyzrgb[1][1] * cs->whiteY +
     604                xyzrgb[1][2] * cs->whiteZ);
     605  cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
     606                xyzrgb[2][1] * cs->whiteY +
     607                xyzrgb[2][2] * cs->whiteZ);
     608
    356609  return cs;
    357610}
    358611
     612// convert CalGray to media XYZ color space
     613// (not multiply by the white point)
     614void GfxCalGrayColorSpace::getXYZ(GfxColor *color,
     615  double *pX, double *pY, double *pZ) {
     616  double A;
     617
     618  A = colToDbl(color->c[0]);
     619  *pX = pow(A,gamma);
     620  *pY = pow(A,gamma);
     621  *pZ = pow(A,gamma);
     622}
     623
    359624void GfxCalGrayColorSpace::getGray(GfxColor *color, GfxGray *gray) {
    360   *gray = clip01(color->c[0]);
    361 }
    362 
    363 void GfxCalGrayColorSpace::getGrayLine(Guchar *in, Guchar *out, int length) {
    364   memcpy (out, in, length);
     625  GfxRGB rgb;
     626
     627#ifdef USE_CMS
     628  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_GRAY) {
     629    Guchar out[gfxColorMaxComps];
     630    double in[gfxColorMaxComps];
     631    double X, Y, Z;
     632   
     633    getXYZ(color,&X,&Y,&Z);
     634    in[0] = clip01(X);
     635    in[1] = clip01(Y);
     636    in[2] = clip01(Z);
     637    XYZ2DisplayTransform->doTransform(in,out,1);
     638    *gray = byteToCol(out[0]);
     639    return;
     640  }
     641#endif
     642  getRGB(color, &rgb);
     643  *gray = clip01((GfxColorComp)(0.299 * rgb.r +
     644                                0.587 * rgb.g +
     645                                0.114 * rgb.b + 0.5));
    365646}
    366647
    367648void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
     649  double X, Y, Z;
     650  double r, g, b;
     651
     652  getXYZ(color,&X,&Y,&Z);
     653#ifdef USE_CMS
     654  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_RGB) {
     655    Guchar out[gfxColorMaxComps];
     656    double in[gfxColorMaxComps];
     657   
     658    in[0] = clip01(X);
     659    in[1] = clip01(Y);
     660    in[2] = clip01(Z);
     661    XYZ2DisplayTransform->doTransform(in,out,1);
     662    rgb->r = byteToCol(out[0]);
     663    rgb->g = byteToCol(out[1]);
     664    rgb->b = byteToCol(out[2]);
     665    return;
     666  }
     667#endif
     668  X *= whiteX;
     669  Y *= whiteY;
     670  Z *= whiteZ;
     671  // convert XYZ to RGB, including gamut mapping and gamma correction
     672  r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
     673  g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
     674  b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
     675  rgb->r = dblToCol(pow(clip01(r * kr), 0.5));
     676  rgb->g = dblToCol(pow(clip01(g * kg), 0.5));
     677  rgb->b = dblToCol(pow(clip01(b * kb), 0.5));
    368678  rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
    369679}
    370680
    371 void GfxCalGrayColorSpace::getRGBLine(Guchar *in, unsigned int *out,
    372                                       int length) {
    373   int i;
    374 
    375   for (i = 0; i < length; i++)
    376     out[i] = (in[i] << 16) | (in[i] << 8) | (in[i] << 0);
    377 }
    378 
    379681void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
    380   cmyk->c = cmyk->m = cmyk->y = 0;
    381   cmyk->k = clip01(gfxColorComp1 - color->c[0]);
     682  GfxRGB rgb;
     683  GfxColorComp c, m, y, k;
     684
     685#ifdef USE_CMS
     686  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_CMYK) {
     687    double in[gfxColorMaxComps];
     688    Guchar out[gfxColorMaxComps];
     689    double X, Y, Z;
     690   
     691    getXYZ(color,&X,&Y,&Z);
     692    in[0] = clip01(X);
     693    in[1] = clip01(Y);
     694    in[2] = clip01(Z);
     695   
     696    XYZ2DisplayTransform->doTransform(in,out,1);
     697    cmyk->c = byteToCol(out[0]);
     698    cmyk->m = byteToCol(out[1]);
     699    cmyk->y = byteToCol(out[2]);
     700    cmyk->k = byteToCol(out[3]);
     701    return;
     702  }
     703#endif
     704  getRGB(color, &rgb);
     705  c = clip01(gfxColorComp1 - rgb.r);
     706  m = clip01(gfxColorComp1 - rgb.g);
     707  y = clip01(gfxColorComp1 - rgb.b);
     708  k = c;
     709  if (m < k) {
     710    k = m;
     711  }
     712  if (y < k) {
     713    k = y;
     714  }
     715  cmyk->c = c - k;
     716  cmyk->m = m - k;
     717  cmyk->y = y - k;
     718  cmyk->k = k;
    382719}
    383720
     
    554891  obj2.free();
    555892  obj1.free();
     893
     894  cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
     895                xyzrgb[0][1] * cs->whiteY +
     896                xyzrgb[0][2] * cs->whiteZ);
     897  cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
     898                xyzrgb[1][1] * cs->whiteY +
     899                xyzrgb[1][2] * cs->whiteZ);
     900  cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
     901                xyzrgb[2][1] * cs->whiteY +
     902                xyzrgb[2][2] * cs->whiteZ);
     903
    556904  return cs;
    557905}
    558906
     907// convert CalRGB to XYZ color space
     908void GfxCalRGBColorSpace::getXYZ(GfxColor *color,
     909  double *pX, double *pY, double *pZ) {
     910  double A, B, C;
     911
     912  A = colToDbl(color->c[0]);
     913  B = colToDbl(color->c[1]);
     914  C = colToDbl(color->c[2]);
     915  *pX = mat[0]*pow(A,gammaR)+mat[3]*pow(B,gammaG)+mat[6]*pow(C,gammaB);
     916  *pY = mat[1]*pow(A,gammaR)+mat[4]*pow(B,gammaG)+mat[7]*pow(C,gammaB);
     917  *pZ = mat[2]*pow(A,gammaR)+mat[5]*pow(B,gammaG)+mat[8]*pow(C,gammaB);
     918}
     919
    559920void GfxCalRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) {
    560   *gray = clip01((GfxColorComp)(0.299 * color->c[0] +
    561                  0.587 * color->c[1] +
    562                  0.114 * color->c[2] + 0.5));
    563 }
    564 
    565 void GfxCalRGBColorSpace::getGrayLine(Guchar *in, Guchar *out, int length) {
    566   int i;
    567 
    568   for (i = 0; i < length; i++) {
    569     out[i] =
    570       (in[i * 3 + 0] * 19595 +
    571        in[i * 3 + 1] * 38469 +
    572        in[i * 3 + 2] * 7472) / 65536;
    573   }
     921  GfxRGB rgb;
     922
     923#ifdef USE_CMS
     924  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_GRAY) {
     925    Guchar out[gfxColorMaxComps];
     926    double in[gfxColorMaxComps];
     927    double X, Y, Z;
     928   
     929    getXYZ(color,&X,&Y,&Z);
     930    in[0] = clip01(X);
     931    in[1] = clip01(Y);
     932    in[2] = clip01(Z);
     933    XYZ2DisplayTransform->doTransform(in,out,1);
     934    *gray = byteToCol(out[0]);
     935    return;
     936  }
     937#endif
     938  getRGB(color, &rgb);
     939  *gray = clip01((GfxColorComp)(0.299 * rgb.r +
     940                                0.587 * rgb.g +
     941                                0.114 * rgb.b + 0.5));
    574942}
    575943
    576944void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
    577   rgb->r = clip01(color->c[0]);
    578   rgb->g = clip01(color->c[1]);
    579   rgb->b = clip01(color->c[2]);
    580 }
    581 
    582 void GfxCalRGBColorSpace::getRGBLine(Guchar *in, unsigned int *out,
    583                                      int length) {
    584   Guchar *p;
    585   int i;
    586 
    587   for (i = 0, p = in; i < length; i++, p += 3)
    588     out[i] = (p[0] << 16) | (p[1] << 8) | (p[2] << 0);
     945  double X, Y, Z;
     946  double r, g, b;
     947
     948  getXYZ(color,&X,&Y,&Z);
     949#ifdef USE_CMS
     950  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_RGB) {
     951    Guchar out[gfxColorMaxComps];
     952    double in[gfxColorMaxComps];
     953   
     954    in[0] = clip01(X/whiteX);
     955    in[1] = clip01(Y/whiteY);
     956    in[2] = clip01(Z/whiteZ);
     957    XYZ2DisplayTransform->doTransform(in,out,1);
     958    rgb->r = byteToCol(out[0]);
     959    rgb->g = byteToCol(out[1]);
     960    rgb->b = byteToCol(out[2]);
     961    return;
     962  }
     963#endif
     964  // convert XYZ to RGB, including gamut mapping and gamma correction
     965  r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
     966  g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
     967  b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
     968  rgb->r = dblToCol(pow(clip01(r), 0.5));
     969  rgb->g = dblToCol(pow(clip01(g), 0.5));
     970  rgb->b = dblToCol(pow(clip01(b), 0.5));
    589971}
    590972
    591973void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
     974  GfxRGB rgb;
    592975  GfxColorComp c, m, y, k;
    593976
    594   c = clip01(gfxColorComp1 - color->c[0]);
    595   m = clip01(gfxColorComp1 - color->c[1]);
    596   y = clip01(gfxColorComp1 - color->c[2]);
     977#ifdef USE_CMS
     978  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_CMYK) {
     979    double in[gfxColorMaxComps];
     980    Guchar out[gfxColorMaxComps];
     981    double X, Y, Z;
     982   
     983    getXYZ(color,&X,&Y,&Z);
     984    in[0] = clip01(X);
     985    in[1] = clip01(Y);
     986    in[2] = clip01(Z);
     987    XYZ2DisplayTransform->doTransform(in,out,1);
     988    cmyk->c = byteToCol(out[0]);
     989    cmyk->m = byteToCol(out[1]);
     990    cmyk->y = byteToCol(out[2]);
     991    cmyk->k = byteToCol(out[3]);
     992    return;
     993  }
     994#endif
     995  getRGB(color, &rgb);
     996  c = clip01(gfxColorComp1 - rgb.r);
     997  m = clip01(gfxColorComp1 - rgb.g);
     998  y = clip01(gfxColorComp1 - rgb.b);
    597999  k = c;
    5981000  if (m < k) {
     
    6361038
    6371039void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
    638   double c, m, y, k, c1, m1, y1, k1, r, g, b, x;
     1040  double c, m, y, k, c1, m1, y1, k1, r, g, b;
    6391041   
    6401042  c = colToDbl(color->c[0]);
     
    6461048  y1 = 1 - y;
    6471049  k1 = 1 - k;
    648   // this is a matrix multiplication, unrolled for performance
    649   //                        C M Y K
    650   x = c1 * m1 * y1 * k1; // 0 0 0 0
    651   r = g = b = x;
    652   x = c1 * m1 * y1 * k;  // 0 0 0 1
    653   r += 0.1373 * x;
    654   g += 0.1216 * x;
    655   b += 0.1255 * x;
    656   x = c1 * m1 * y  * k1; // 0 0 1 0
    657   r += x;
    658   g += 0.9490 * x;
    659   x = c1 * m1 * y  * k;  // 0 0 1 1
    660   r += 0.1098 * x;
    661   g += 0.1020 * x;
    662   x = c1 * m  * y1 * k1; // 0 1 0 0
    663   r += 0.9255 * x;
    664   b += 0.5490 * x;
    665   x = c1 * m  * y1 * k;  // 0 1 0 1
    666   r += 0.1412 * x;
    667   x = c1 * m  * y  * k1; // 0 1 1 0
    668   r += 0.9294 * x;
    669   g += 0.1098 * x;
    670   b += 0.1412 * x;
    671   x = c1 * m  * y  * k;  // 0 1 1 1
    672   r += 0.1333 * x;
    673   x = c  * m1 * y1 * k1; // 1 0 0 0
    674   g += 0.6784 * x;
    675   b += 0.9373 * x;
    676   x = c  * m1 * y1 * k;  // 1 0 0 1
    677   g += 0.0588 * x;
    678   b += 0.1412 * x;
    679   x = c  * m1 * y  * k1; // 1 0 1 0
    680   g += 0.6510 * x;
    681   b += 0.3137 * x;
    682   x = c  * m1 * y  * k;  // 1 0 1 1
    683   g += 0.0745 * x;
    684   x = c  * m  * y1 * k1; // 1 1 0 0
    685   r += 0.1804 * x;
    686   g += 0.1922 * x;
    687   b += 0.5725 * x;
    688   x = c  * m  * y1 * k;  // 1 1 0 1
    689   b += 0.0078 * x;
    690   x = c  * m  * y  * k1; // 1 1 1 0
    691   r += 0.2118 * x;
    692   g += 0.2119 * x;
    693   b += 0.2235 * x;
     1050  cmykToRGBMatrixMultiplication(c, m, y, k, c1, m1, y1, k1, r, g, b);
    6941051  rgb->r = clip01(dblToCol(r));
    6951052  rgb->g = clip01(dblToCol(g));
     
    7141071// GfxLabColorSpace
    7151072//------------------------------------------------------------------------
    716 
    717 // This is the inverse of MatrixLMN in Example 4.10 from the PostScript
    718 // Language Reference, Third Edition.
    719 static const double xyzrgb[3][3] = {
    720   {  3.240449, -1.537136, -0.498531 },
    721   { -0.969265,  1.876011,  0.041556 },
    722   {  0.055643, -0.204026,  1.057229 }
    723 };
    7241073
    7251074GfxLabColorSpace::GfxLabColorSpace() {
     
    8241173  GfxRGB rgb;
    8251174
     1175#ifdef USE_CMS
     1176  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_GRAY) {
     1177    Guchar out[gfxColorMaxComps];
     1178    double in[gfxColorMaxComps];
     1179   
     1180    getXYZ(color, &in[0], &in[1], &in[2]);
     1181    XYZ2DisplayTransform->doTransform(in,out,1);
     1182    *gray = byteToCol(out[0]);
     1183    return;
     1184  }
     1185#endif
    8261186  getRGB(color, &rgb);
    8271187  *gray = clip01((GfxColorComp)(0.299 * rgb.r +
     
    8301190}
    8311191
    832 void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
     1192// convert L*a*b* to media XYZ color space
     1193// (not multiply by the white point)
     1194void GfxLabColorSpace::getXYZ(GfxColor *color,
     1195  double *pX, double *pY, double *pZ) {
    8331196  double X, Y, Z;
    8341197  double t1, t2;
    835   double r, g, b;
    836 
    837   // convert L*a*b* to CIE 1931 XYZ color space
     1198
    8381199  t1 = (colToDbl(color->c[0]) + 16) / 116;
    8391200  t2 = t1 + colToDbl(color->c[1]) / 500;
     
    8431204    X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
    8441205  }
    845   X *= whiteX;
    8461206  if (t1 >= (6.0 / 29.0)) {
    8471207    Y = t1 * t1 * t1;
     
    8491209    Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
    8501210  }
    851   Y *= whiteY;
    8521211  t2 = t1 - colToDbl(color->c[2]) / 200;
    8531212  if (t2 >= (6.0 / 29.0)) {
     
    8561215    Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
    8571216  }
     1217  *pX = X;
     1218  *pY = Y;
     1219  *pZ = Z;
     1220}
     1221
     1222void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
     1223  double X, Y, Z;
     1224  double r, g, b;
     1225
     1226  getXYZ(color, &X, &Y, &Z);
     1227#ifdef USE_CMS
     1228  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_RGB) {
     1229    Guchar out[gfxColorMaxComps];
     1230    double in[gfxColorMaxComps];
     1231   
     1232    in[0] = clip01(X);
     1233    in[1] = clip01(Y);
     1234    in[2] = clip01(Z);
     1235    XYZ2DisplayTransform->doTransform(in,out,1);
     1236    rgb->r = byteToCol(out[0]);
     1237    rgb->g = byteToCol(out[1]);
     1238    rgb->b = byteToCol(out[2]);
     1239    return;
     1240  }
     1241#endif
     1242  X *= whiteX;
     1243  Y *= whiteY;
    8581244  Z *= whiteZ;
    859 
    8601245  // convert XYZ to RGB, including gamut mapping and gamma correction
    8611246  r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
     
    8711256  GfxColorComp c, m, y, k;
    8721257
     1258#ifdef USE_CMS
     1259  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_CMYK) {
     1260    double in[gfxColorMaxComps];
     1261    Guchar out[gfxColorMaxComps];
     1262   
     1263    getXYZ(color, &in[0], &in[1], &in[2]);
     1264    XYZ2DisplayTransform->doTransform(in,out,1);
     1265    cmyk->c = byteToCol(out[0]);
     1266    cmyk->m = byteToCol(out[1]);
     1267    cmyk->y = byteToCol(out[2]);
     1268    cmyk->k = byteToCol(out[3]);
     1269    return;
     1270  }
     1271#endif
    8731272  getRGB(color, &rgb);
    8741273  c = clip01(gfxColorComp1 - rgb.r);
     
    9201319//------------------------------------------------------------------------
    9211320
     1321class GfxICCBasedColorSpaceKey : public PopplerCacheKey
     1322{
     1323  public:
     1324    GfxICCBasedColorSpaceKey(int numA, int genA) : num(numA), gen(genA)
     1325    {
     1326    }
     1327   
     1328    bool operator==(const PopplerCacheKey &key) const
     1329    {
     1330      const GfxICCBasedColorSpaceKey *k = static_cast<const GfxICCBasedColorSpaceKey*>(&key);
     1331      return k->num == num && k->gen == gen;
     1332    }
     1333   
     1334    int num, gen;
     1335};
     1336
     1337class GfxICCBasedColorSpaceItem : public PopplerCacheItem
     1338{
     1339  public:
     1340    GfxICCBasedColorSpaceItem(GfxICCBasedColorSpace *csA)
     1341    {
     1342      cs = static_cast<GfxICCBasedColorSpace*>(csA->copy());
     1343    }
     1344   
     1345    ~GfxICCBasedColorSpaceItem()
     1346    {
     1347      delete cs;
     1348    }
     1349   
     1350    GfxICCBasedColorSpace *cs;
     1351};
     1352
    9221353GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
    9231354                                             Ref *iccProfileStreamA) {
     
    9271358  rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
    9281359  rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
     1360#ifdef USE_CMS
     1361  transform = NULL;
     1362  lineTransform = NULL;
     1363#endif
    9291364}
    9301365
    9311366GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
    9321367  delete alt;
     1368#ifdef USE_CMS
     1369  if (transform != NULL) {
     1370    if (transform->unref() == 0) delete transform;
     1371  }
     1372  if (lineTransform != NULL) {
     1373    if (lineTransform->unref() == 0) delete lineTransform;
     1374  }
     1375#endif
    9331376}
    9341377
     
    9421385    cs->rangeMax[i] = rangeMax[i];
    9431386  }
     1387#ifdef USE_CMS
     1388  cs->transform = transform;
     1389  if (transform != NULL) transform->ref();
     1390  cs->lineTransform = lineTransform;
     1391  if (lineTransform != NULL) lineTransform->ref();
     1392#endif
    9441393  return cs;
    9451394}
    9461395
    947 GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
     1396GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, Gfx *gfx) {
    9481397  GfxICCBasedColorSpace *cs;
    9491398  Ref iccProfileStreamA;
     
    9621411  }
    9631412  obj1.free();
     1413#ifdef USE_CMS
     1414  // check cache
     1415  if (gfx && iccProfileStreamA.num > 0) {
     1416    GfxICCBasedColorSpaceKey k(iccProfileStreamA.num, iccProfileStreamA.gen);
     1417    GfxICCBasedColorSpaceItem *item = static_cast<GfxICCBasedColorSpaceItem *>(gfx->getIccColorSpaceCache()->lookup(k));
     1418    if (item != NULL)
     1419    {
     1420      cs = static_cast<GfxICCBasedColorSpace*>(item->cs->copy());
     1421      return cs;
     1422    }
     1423  }
     1424#endif
    9641425  arr->get(1, &obj1);
    9651426  if (!obj1.isStream()) {
     
    9831444  }
    9841445  if (dict->lookup("Alternate", &obj2)->isNull() ||
    985       !(altA = GfxColorSpace::parse(&obj2))) {
     1446      !(altA = GfxColorSpace::parse(&obj2, gfx))) {
    9861447    switch (nCompsA) {
    9871448    case 1:
     
    10161477  obj2.free();
    10171478  obj1.free();
     1479
     1480#ifdef USE_CMS
     1481  arr->get(1, &obj1);
     1482  dict = obj1.streamGetDict();
     1483  Guchar *profBuf;
     1484  unsigned int bufSize;
     1485  Stream *iccStream = obj1.getStream();
     1486  int c;
     1487  unsigned int size = 0;
     1488
     1489  bufSize = 65536;
     1490  profBuf = (Guchar *)gmallocn(bufSize,1);
     1491  iccStream->reset();
     1492  while ((c = iccStream->getChar()) != EOF) {
     1493    if (bufSize <= size) {
     1494      bufSize += 65536;
     1495      profBuf = (Guchar *)greallocn(profBuf,bufSize,1);
     1496    }
     1497    profBuf[size++] = c;
     1498  }
     1499  cmsHPROFILE hp = cmsOpenProfileFromMem(profBuf,size);
     1500  gfree(profBuf);
     1501  if (hp == 0) {
     1502    error(-1, "read ICCBased color space profile error");
     1503  } else {
     1504    cmsHPROFILE dhp = displayProfile;
     1505    if (dhp == NULL) dhp = RGBProfile;
     1506    unsigned int cst = getCMSColorSpaceType(cmsGetColorSpace(hp));
     1507    unsigned int dNChannels = getCMSNChannels(cmsGetColorSpace(dhp));
     1508    unsigned int dcst = getCMSColorSpaceType(cmsGetColorSpace(dhp));
     1509    cmsHTRANSFORM transform;
     1510    if ((transform = cmsCreateTransform(hp,
     1511           COLORSPACE_SH(cst) |CHANNELS_SH(nCompsA) | BYTES_SH(1),
     1512           dhp,
     1513           COLORSPACE_SH(dcst) |
     1514             CHANNELS_SH(dNChannels) | BYTES_SH(1),
     1515          INTENT_RELATIVE_COLORIMETRIC,0)) == 0) {
     1516      error(-1, "Can't create transform");
     1517      cs->transform = NULL;
     1518    } else {
     1519      cs->transform = new GfxColorTransform(transform);
     1520    }
     1521    if (dcst == PT_RGB) {
     1522       // create line transform only when the display is RGB type color space
     1523      if ((transform = cmsCreateTransform(hp,
     1524            CHANNELS_SH(nCompsA) | BYTES_SH(1),dhp,
     1525            TYPE_RGB_8,INTENT_RELATIVE_COLORIMETRIC,0)) == 0) {
     1526        error(-1, "Can't create transform");
     1527        cs->lineTransform = NULL;
     1528      } else {
     1529        cs->lineTransform = new GfxColorTransform(transform);
     1530      }
     1531    }
     1532    cmsCloseProfile(hp);
     1533  }
     1534  obj1.free();
     1535  // put this colorSpace into cache
     1536  if (gfx && iccProfileStreamA.num > 0) {
     1537    GfxICCBasedColorSpaceKey *k = new GfxICCBasedColorSpaceKey(iccProfileStreamA.num, iccProfileStreamA.gen);
     1538    GfxICCBasedColorSpaceItem *item = new GfxICCBasedColorSpaceItem(cs);
     1539    gfx->getIccColorSpaceCache()->put(k, item);
     1540  }
     1541#endif
    10181542  return cs;
    10191543}
    10201544
    10211545void GfxICCBasedColorSpace::getGray(GfxColor *color, GfxGray *gray) {
     1546#ifdef USE_CMS
     1547  if (transform != 0 && displayPixelType == PT_GRAY) {
     1548    Guchar in[gfxColorMaxComps];
     1549    Guchar out[gfxColorMaxComps];
     1550   
     1551    for (int i = 0;i < nComps;i++) {
     1552        in[i] = colToByte(color->c[i]);
     1553    }
     1554    transform->doTransform(in,out,1);
     1555    *gray = byteToCol(out[0]);
     1556  } else {
     1557    GfxRGB rgb;
     1558    getRGB(color,&rgb);
     1559    *gray = clip01((GfxColorComp)(0.3 * rgb.r +
     1560                   0.59 * rgb.g +
     1561                   0.11 * rgb.b + 0.5));
     1562  }
     1563#else
    10221564  alt->getGray(color, gray);
     1565#endif
    10231566}
    10241567
    10251568void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
     1569#ifdef USE_CMS
     1570  if (transform != 0
     1571       && (displayProfile == NULL || displayPixelType == PT_RGB)) {
     1572    Guchar in[gfxColorMaxComps];
     1573    Guchar out[gfxColorMaxComps];
     1574   
     1575    for (int i = 0;i < nComps;i++) {
     1576        in[i] = colToByte(color->c[i]);
     1577    }
     1578    transform->doTransform(in,out,1);
     1579    rgb->r = byteToCol(out[0]);
     1580    rgb->g = byteToCol(out[1]);
     1581    rgb->b = byteToCol(out[2]);
     1582  } else {
     1583    alt->getRGB(color, rgb);
     1584  }
     1585#else
    10261586  alt->getRGB(color, rgb);
     1587#endif
    10271588}
    10281589
    10291590void GfxICCBasedColorSpace::getRGBLine(Guchar *in, unsigned int *out,
    10301591                                       int length) {
     1592#ifdef USE_CMS
     1593  if (lineTransform != 0) {
     1594    for (int i = 0;i < length;i++) {
     1595        Guchar tmp[gfxColorMaxComps];
     1596
     1597        lineTransform->doTransform(in,tmp,1);
     1598        in += nComps;
     1599        out[i] = (tmp[0] << 16) | (tmp[1] << 8) | tmp[2];
     1600    }
     1601  } else {
     1602    alt->getRGBLine(in, out, length);
     1603  }
     1604#else
    10311605  alt->getRGBLine(in, out, length);
     1606#endif
    10321607}
    10331608
    10341609void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
     1610#ifdef USE_CMS
     1611  if (transform != NULL && displayPixelType == PT_CMYK) {
     1612    Guchar in[gfxColorMaxComps];
     1613    Guchar out[gfxColorMaxComps];
     1614   
     1615    for (int i = 0;i < nComps;i++) {
     1616        in[i] = colToByte(color->c[i]);
     1617    }
     1618    transform->doTransform(in,out,1);
     1619    cmyk->c = byteToCol(out[0]);
     1620    cmyk->m = byteToCol(out[1]);
     1621    cmyk->y = byteToCol(out[2]);
     1622    cmyk->k = byteToCol(out[3]);
     1623  } else {
     1624    GfxRGB rgb;
     1625    GfxColorComp c, m, y, k;
     1626
     1627    getRGB(color,&rgb);
     1628    c = clip01(gfxColorComp1 - rgb.r);
     1629    m = clip01(gfxColorComp1 - rgb.g);
     1630    y = clip01(gfxColorComp1 - rgb.b);
     1631    k = c;
     1632    if (m < k) {
     1633      k = m;
     1634    }
     1635    if (y < k) {
     1636      k = y;
     1637    }
     1638    cmyk->c = c - k;
     1639    cmyk->m = m - k;
     1640    cmyk->y = y - k;
     1641    cmyk->k = k;
     1642  }
     1643#else
    10351644  alt->getCMYK(color, cmyk);
     1645#endif
     1646}
     1647
     1648GBool GfxICCBasedColorSpace::useGetRGBLine() {
     1649#ifdef USE_CMS
     1650  return lineTransform != NULL || alt->useGetRGBLine();
     1651#else
     1652  return alt->useGetRGBLine();
     1653#endif
    10361654}
    10371655
     
    10931711}
    10941712
    1095 GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
     1713GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, Gfx *gfx) {
    10961714  GfxIndexedColorSpace *cs;
    10971715  GfxColorSpace *baseA;
     
    11071725  }
    11081726  arr->get(1, &obj1);
    1109   if (!(baseA = GfxColorSpace::parse(&obj1))) {
     1727  if (!(baseA = GfxColorSpace::parse(&obj1, gfx))) {
    11101728    error(-1, "Bad Indexed color space (base color space)");
    11111729    goto err2;
     
    12021820
    12031821  n = base->getNComps();
    1204   line = (Guchar *) gmalloc (length * n);
     1822  line = (Guchar *) gmallocn (length, n);
    12051823  for (i = 0; i < length; i++)
    12061824    for (j = 0; j < n; j++)
     
    12531871
    12541872//~ handle the 'All' and 'None' colorants
    1255 GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
     1873GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, Gfx *gfx) {
    12561874  GfxSeparationColorSpace *cs;
    12571875  GooString *nameA;
     
    12711889  obj1.free();
    12721890  arr->get(2, &obj1);
    1273   if (!(altA = GfxColorSpace::parse(&obj1))) {
     1891  if (!(altA = GfxColorSpace::parse(&obj1, gfx))) {
    12741892    error(-1, "Bad Separation color space (alternate color space)");
    12751893    goto err3;
     
    13761994
    13771995//~ handle the 'None' colorant
    1378 GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
     1996GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, Gfx *gfx) {
    13791997  GfxDeviceNColorSpace *cs;
    13801998  int nCompsA;
     
    14102028  obj1.free();
    14112029  arr->get(2, &obj1);
    1412   if (!(altA = GfxColorSpace::parse(&obj1))) {
     2030  if (!(altA = GfxColorSpace::parse(&obj1, gfx))) {
    14132031    error(-1, "Bad DeviceN color space (alternate color space)");
    14142032    goto err3;
     
    15142132}
    15152133
    1516 GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
     2134GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, Gfx *gfx) {
    15172135  GfxPatternColorSpace *cs;
    15182136  GfxColorSpace *underA;
     
    15262144  if (arr->getLength() == 2) {
    15272145    arr->get(1, &obj1);
    1528     if (!(underA = GfxColorSpace::parse(&obj1))) {
     2146    if (!(underA = GfxColorSpace::parse(&obj1, gfx))) {
    15292147      error(-1, "Bad Pattern color space (underlying color space)");
    15302148      obj1.free();
     
    15652183}
    15662184
    1567 GfxPattern *GfxPattern::parse(Object *obj) {
     2185GfxPattern *GfxPattern::parse(Object *obj, Gfx *gfx) {
    15682186  GfxPattern *pattern;
    15692187  Object obj1;
     
    15802198    pattern = GfxTilingPattern::parse(obj);
    15812199  } else if (obj1.isInt() && obj1.getInt() == 2) {
    1582     pattern = GfxShadingPattern::parse(obj);
     2200    pattern = GfxShadingPattern::parse(obj, gfx);
    15832201  }
    15842202  obj1.free();
     
    17082326//------------------------------------------------------------------------
    17092327
    1710 GfxShadingPattern *GfxShadingPattern::parse(Object *patObj) {
     2328GfxShadingPattern *GfxShadingPattern::parse(Object *patObj, Gfx *gfx) {
    17112329  Dict *dict;
    17122330  GfxShading *shadingA;
     
    17212339
    17222340  dict->lookup("Shading", &obj1);
    1723   shadingA = GfxShading::parse(&obj1);
     2341  shadingA = GfxShading::parse(&obj1, gfx);
    17242342  obj1.free();
    17252343  if (!shadingA) {
     
    17942412}
    17952413
    1796 GfxShading *GfxShading::parse(Object *obj) {
     2414GfxShading *GfxShading::parse(Object *obj, Gfx *gfx) {
    17972415  GfxShading *shading;
    17982416  Dict *dict;
     
    18182436  switch (typeA) {
    18192437  case 1:
    1820     shading = GfxFunctionShading::parse(dict);
     2438    shading = GfxFunctionShading::parse(dict, gfx);
    18212439    break;
    18222440  case 2:
    1823     shading = GfxAxialShading::parse(dict);
     2441    shading = GfxAxialShading::parse(dict, gfx);
    18242442    break;
    18252443  case 3:
    1826     shading = GfxRadialShading::parse(dict);
     2444    shading = GfxRadialShading::parse(dict, gfx);
    18272445    break;
    18282446  case 4:
    18292447    if (obj->isStream()) {
    1830       shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream());
     2448      shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream(), gfx);
    18312449    } else {
    18322450      error(-1, "Invalid Type 4 shading object");
     
    18362454  case 5:
    18372455    if (obj->isStream()) {
    1838       shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream());
     2456      shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream(), gfx);
    18392457    } else {
    18402458      error(-1, "Invalid Type 5 shading object");
     
    18442462  case 6:
    18452463    if (obj->isStream()) {
    1846       shading = GfxPatchMeshShading::parse(6, dict, obj->getStream());
     2464      shading = GfxPatchMeshShading::parse(6, dict, obj->getStream(), gfx);
    18472465    } else {
    18482466      error(-1, "Invalid Type 6 shading object");
     
    18522470  case 7:
    18532471    if (obj->isStream()) {
    1854       shading = GfxPatchMeshShading::parse(7, dict, obj->getStream());
     2472      shading = GfxPatchMeshShading::parse(7, dict, obj->getStream(), gfx);
    18552473    } else {
    18562474      error(-1, "Invalid Type 7 shading object");
     
    18692487}
    18702488
    1871 GBool GfxShading::init(Dict *dict) {
     2489GBool GfxShading::init(Dict *dict, Gfx *gfx) {
    18722490  Object obj1, obj2;
    18732491  int i;
    18742492
    18752493  dict->lookup("ColorSpace", &obj1);
    1876   if (!(colorSpace = GfxColorSpace::parse(&obj1))) {
     2494  if (!(colorSpace = GfxColorSpace::parse(&obj1, gfx))) {
    18772495    error(-1, "Bad color space in shading dictionary");
    18782496    obj1.free();
     
    19712589}
    19722590
    1973 GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) {
     2591GfxFunctionShading *GfxFunctionShading::parse(Dict *dict, Gfx *gfx) {
    19742592  GfxFunctionShading *shading;
    19752593  double x0A, y0A, x1A, y1A;
     
    20392657  shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA,
    20402658                                   funcsA, nFuncsA);
    2041   if (!shading->init(dict)) {
     2659  if (!shading->init(dict, gfx)) {
    20422660    delete shading;
    20432661    return NULL;
     
    21292747}
    21302748
    2131 GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
     2749GfxAxialShading *GfxAxialShading::parse(Dict *dict, Gfx *gfx) {
    21322750  GfxAxialShading *shading;
    21332751  double x0A, y0A, x1A, y1A;
     
    22042822  shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
    22052823                                funcsA, nFuncsA, extend0A, extend1A);
    2206   if (!shading->init(dict)) {
     2824  if (!shading->init(dict, gfx)) {
    22072825    delete shading;
    22082826    return NULL;
     
    22932911}
    22942912
    2295 GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
     2913GfxRadialShading *GfxRadialShading::parse(Dict *dict, Gfx *gfx) {
    22962914  GfxRadialShading *shading;
    22972915  double x0A, y0A, r0A, x1A, y1A, r1A;
     
    23722990  shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
    23732991                                 funcsA, nFuncsA, extend0A, extend1A);
    2374   if (!shading->init(dict)) {
     2992  if (!shading->init(dict, gfx)) {
    23752993    delete shading;
    23762994    return NULL;
     
    25233141GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
    25243142                                                            Dict *dict,
    2525                                                             Stream *str) {
     3143                                                            Stream *str,
     3144                                                            Gfx *gfx) {
    25263145  GfxGouraudTriangleShading *shading;
    25273146  Function *funcsA[gfxColorMaxComps];
     
    26533272    }
    26543273    if (nVerticesA == vertSize) {
     3274      int oldVertSize = vertSize;
    26553275      vertSize = (vertSize == 0) ? 16 : 2 * vertSize;
    26563276      verticesA = (GfxGouraudVertex *)
    26573277                      greallocn(verticesA, vertSize, sizeof(GfxGouraudVertex));
     3278      memset(verticesA + oldVertSize, 0, (vertSize - oldVertSize) * sizeof(GfxGouraudVertex));
    26583279    }
    26593280    verticesA[nVerticesA].x = xMin + xMul * (double)x;
     
    27173338                                          trianglesA, nTrianglesA,
    27183339                                          funcsA, nFuncsA);
    2719   if (!shading->init(dict)) {
     3340  if (!shading->init(dict, gfx)) {
    27203341    delete shading;
    27213342    return NULL;
     
    28293450
    28303451GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
    2831                                                 Stream *str) {
     3452                                                Stream *str, Gfx *gfx) {
    28323453  GfxPatchMeshShading *shading;
    28333454  Function *funcsA[gfxColorMaxComps];
     
    29753596    }
    29763597    if (nPatchesA == patchesSize) {
     3598      int oldPatchesSize = patchesSize;
    29773599      patchesSize = (patchesSize == 0) ? 16 : 2 * patchesSize;
    29783600      patchesA = (GfxPatch *)greallocn(patchesA,
    29793601                                       patchesSize, sizeof(GfxPatch));
     3602      memset(patchesA + oldPatchesSize, 0, (patchesSize - oldPatchesSize) * sizeof(GfxPatch));
    29803603    }
    29813604    p = &patchesA[nPatchesA];
     
    33283951  shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA,
    33293952                                    funcsA, nFuncsA);
    3330   if (!shading->init(dict)) {
     3953  if (!shading->init(dict, gfx)) {
    33313954    delete shading;
    33323955    return NULL;
     
    33583981  double x[gfxColorMaxComps];
    33593982  double y[gfxColorMaxComps];
    3360   int i, j, k, byte;
     3983  int i, j, k;
    33613984  double mapped;
     3985  GBool useByteLookup;
    33623986
    33633987  ok = gTrue;
     
    33784002    lookup[k] = NULL;
    33794003  }
     4004  byte_lookup = NULL;
    33804005
    33814006  // get decode map
     
    34154040  colorSpace2 = NULL;
    34164041  nComps2 = 0;
    3417   if (colorSpace->getMode() == csIndexed) {
     4042  useByteLookup = gFalse;
     4043  switch (colorSpace->getMode()) {
     4044  case csIndexed:
    34184045    // Note that indexHigh may not be the same as maxPixel --
    34194046    // Distiller will remove unused palette entries, resulting in
     
    34254052    lookup2 = indexedCS->getLookup();
    34264053    colorSpace2->getDefaultRanges(x, y, indexHigh);
    3427     byte_lookup = (Guchar *)gmalloc ((maxPixel + 1) * nComps2);
     4054    if (colorSpace2->useGetGrayLine() || colorSpace2->useGetRGBLine()) {
     4055      byte_lookup = (Guchar *)gmallocn ((maxPixel + 1), nComps2);
     4056      useByteLookup = gTrue;
     4057    }
    34284058    for (k = 0; k < nComps2; ++k) {
    34294059      lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
     
    34394069        mapped = x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k];
    34404070        lookup[k][i] = dblToCol(mapped);
    3441         byte_lookup[i * nComps2 + k] = (Guchar) (mapped * 255);
     4071        if (useByteLookup)
     4072          byte_lookup[i * nComps2 + k] = (Guchar) (mapped * 255);
    34424073      }
    34434074    }
    3444   } else if (colorSpace->getMode() == csSeparation) {
     4075    break;
     4076  case csSeparation:
    34454077    sepCS = (GfxSeparationColorSpace *)colorSpace;
    34464078    colorSpace2 = sepCS->getAlt();
    34474079    nComps2 = colorSpace2->getNComps();
    34484080    sepFunc = sepCS->getFunc();
    3449     byte_lookup = (Guchar *)gmallocn ((maxPixel + 1), nComps2);
     4081    if (colorSpace2->useGetGrayLine() || colorSpace2->useGetRGBLine()) {
     4082      byte_lookup = (Guchar *)gmallocn ((maxPixel + 1), nComps2);
     4083      useByteLookup = gTrue;
     4084    }
    34504085    for (k = 0; k < nComps2; ++k) {
    34514086      lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
     
    34554090        sepFunc->transform(x, y);
    34564091        lookup[k][i] = dblToCol(y[k]);
    3457         byte_lookup[i*nComps2 + k] = (Guchar) (y[k] * 255);
     4092        if (useByteLookup)
     4093          byte_lookup[i*nComps2 + k] = (Guchar) (y[k] * 255);
    34584094      }
    34594095    }
    3460   } else {
    3461     byte_lookup = (Guchar *)gmallocn ((maxPixel + 1), nComps);
     4096    break;
     4097  default:
     4098    if (colorSpace->useGetGrayLine() || colorSpace->useGetRGBLine()) {
     4099      byte_lookup = (Guchar *)gmallocn ((maxPixel + 1), nComps);
     4100      useByteLookup = gTrue;
     4101    }
    34624102    for (k = 0; k < nComps; ++k) {
    34634103      lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
     
    34664106        mapped = decodeLow[k] + (i * decodeRange[k]) / maxPixel;
    34674107        lookup[k][i] = dblToCol(mapped);
    3468         byte = (int) (mapped * 255.0 + 0.5);
    3469         if (byte < 0) 
    3470           byte = 0; 
    3471         else if (byte > 255) 
    3472           byte = 255; 
    3473         byte_lookup[i * nComps + k] = byte;     
     4108        if (useByteLookup) {
     4109          int byte;
     4110
     4111          byte = (int) (mapped * 255.0 + 0.5);
     4112          if (byte < 0)
     4113            byte = 0;
     4114          else if (byte > 255)
     4115            byte = 255;
     4116          byte_lookup[i * nComps + k] = byte;
     4117        }
    34744118      }
    34754119    }
     
    34824126 err1:
    34834127  ok = gFalse;
    3484   byte_lookup = NULL;
    34854128}
    34864129
     
    35154158    }
    35164159  }
     4160  if (colorMap->byte_lookup) {
     4161    int nc = colorSpace2 ? nComps2 : nComps;
     4162
     4163    byte_lookup = (Guchar *)gmallocn (n, nc);
     4164    memcpy(byte_lookup, colorMap->byte_lookup, n * nc);
     4165  }
    35174166  for (i = 0; i < nComps; ++i) {
    35184167    decodeLow[i] = colorMap->decodeLow[i];
     
    35704219  Guchar *inp, *tmp_line;
    35714220
     4221  if ((colorSpace2 && !colorSpace2->useGetGrayLine ()) ||
     4222      (!colorSpace2 && !colorSpace->useGetGrayLine ())) {
     4223    GfxGray gray;
     4224
     4225    inp = in;
     4226    for (i = 0; i < length; i++) {
     4227      getGray (inp, &gray);
     4228      out[i] = colToByte(gray);
     4229      inp += nComps;
     4230    }
     4231    return;
     4232  }
     4233
    35724234  switch (colorSpace->getMode()) {
    35734235  case csIndexed:
    35744236  case csSeparation:
    3575     tmp_line = (Guchar *) gmalloc (length * nComps2);
     4237    tmp_line = (Guchar *) gmallocn (length, nComps2);
    35764238    for (i = 0; i < length; i++) {
    35774239      for (j = 0; j < nComps2; j++) {
     
    36004262  Guchar *inp, *tmp_line;
    36014263
     4264  if ((colorSpace2 && !colorSpace2->useGetRGBLine ()) ||
     4265      (!colorSpace2 && !colorSpace->useGetRGBLine ())) {
     4266    GfxRGB rgb;
     4267
     4268    inp = in;
     4269    for (i = 0; i < length; i++) {
     4270      getRGB (inp, &rgb);
     4271      out[i] =
     4272          ((int) colToByte(rgb.r) << 16) |
     4273          ((int) colToByte(rgb.g) << 8) |
     4274          ((int) colToByte(rgb.b) << 0);
     4275      inp += nComps;
     4276    }
     4277    return;
     4278  }
     4279
    36024280  switch (colorSpace->getMode()) {
    36034281  case csIndexed:
    36044282  case csSeparation:
    3605     tmp_line = (Guchar *) gmalloc (length * nComps2);
     4283    tmp_line = (Guchar *) gmallocn (length, nComps2);
    36064284    for (i = 0; i < length; i++) {
    36074285      for (j = 0; j < nComps2; j++) {
     
    39394617
    39404618  saved = NULL;
     4619#ifdef USE_CMS
     4620  GfxColorSpace::setupColorProfiles();
     4621#endif
    39414622}
    39424623
Note: See TracChangeset for help on using the changeset viewer.