Ignore:
Timestamp:
Jun 30, 2008, 10:13:07 AM (13 years ago)
Author:
Eugene Romanenko
Message:

PDF plugin: poppler library updated to version 0.8.3

File:
1 edited

Legend:

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

    r134 r250  
    3838#include "SplashOutputDev.h"
    3939
     40#ifdef VMS
     41#if (__VMS_VER < 70000000)
     42extern "C" int unlink(char *filename);
     43#endif
     44#endif
     45
     46//------------------------------------------------------------------------
     47
     48// Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result.
     49static inline Guchar div255(int x) {
     50  return (Guchar)((x + (x >> 8) + 0x80) >> 8);
     51}
     52
    4053//------------------------------------------------------------------------
    4154// Blend functions
     
    4760
    4861  for (i = 0; i < splashColorModeNComps[cm]; ++i) {
    49     // note: floor(x / 255) = x >> 8 (for 16-bit x)
    50     blend[i] = (dest[i] * src[i]) >> 8;
     62    blend[i] = (dest[i] * src[i]) / 255;
    5163  }
    5264}
     
    5769
    5870  for (i = 0; i < splashColorModeNComps[cm]; ++i) {
    59     // note: floor(x / 255) = x >> 8 (for 16-bit x)
    60     blend[i] = dest[i] + src[i] - ((dest[i] * src[i]) >> 8);
     71    blend[i] = dest[i] + src[i] - (dest[i] * src[i]) / 255;
    6172  }
    6273}
     
    6677  int i;
    6778
    68   //~ not sure if this is right
    6979  for (i = 0; i < splashColorModeNComps[cm]; ++i) {
    70     // note: floor(x / 255) = x >> 8 (for 16-bit x)
    71     blend[i] = dest[i] < 0x80 ? ((dest[i] * src[i]) >> 8)
    72                               : dest[i] + src[i] - ((dest[i] * src[i]) >> 8);
     80    blend[i] = dest[i] < 0x80
     81                 ? (src[i] * 2 * dest[i]) / 255
     82                 : 255 - 2 * ((255 - src[i]) * (255 - dest[i])) / 255;
    7383  }
    7484}
     
    98108
    99109  for (i = 0; i < splashColorModeNComps[cm]; ++i) {
    100     x = dest[i] + src[i];
    101     blend[i] = x <= 255 ? x : 255;
     110    if (src[i] == 255) {
     111      blend[i] = 255;
     112    } else {
     113      x = (dest[i] * 255) / (255 - src[i]);
     114      blend[i] = x <= 255 ? x : 255;
     115    }
    102116  }
    103117}
     
    108122
    109123  for (i = 0; i < splashColorModeNComps[cm]; ++i) {
    110     x = dest[i] - (255 - src[i]);
    111     blend[i] = x >= 0 ? x : 0;
     124    if (src[i] == 0) {
     125      blend[i] = 0;
     126    } else {
     127      x = ((255 - dest[i]) * 255) / src[i];
     128      blend[i] = x <= 255 ? 255 - x : 0;
     129    }
    112130  }
    113131}
     
    117135  int i;
    118136
    119   //~ not sure if this is right
    120137  for (i = 0; i < splashColorModeNComps[cm]; ++i) {
    121     // note: floor(x / 255) = x >> 8 (for 16-bit x)
    122138    blend[i] = src[i] < 0x80
    123                  ? ((dest[i] * (src[i] * 2)) >> 8)
    124                  : 0xff - (((0xff - dest[i]) * (0x1ff - src[i] * 2)) >> 8);
     139                 ? (dest[i] * 2 * src[i]) / 255
     140                 : 255 - 2 * ((255 - dest[i]) * (255 - src[i])) / 255;
    125141  }
    126142}
     
    130146  int i, x;
    131147
    132   //~ not sure if this is right
    133148  for (i = 0; i < splashColorModeNComps[cm]; ++i) {
    134149    if (src[i] < 0x80) {
    135       x = dest[i] - (0x80 - src[i]);
    136       blend[i] = x >= 0 ? x : 0;
     150      blend[i] = dest[i] - (255 - 2 * src[i]) * dest[i] * (255 - dest[i]) /
     151                 (255 * 255);
    137152    } else {
    138       x = dest[i] + (src[i] - 0x80);
    139       blend[i] = x <= 255 ? x : 255;
     153      if (dest[i] < 0x40) {
     154        x = (((((16 * dest[i] - 12 * 255) * dest[i]) / 255)
     155              + 4 * 255) * dest[i]) / 255;
     156      } else {
     157        x = (int)sqrt(255.0 * dest[i]);
     158      }
     159      blend[i] = dest[i] + (2 * src[i] - 255) * (x - dest[i]) / 255;
    140160    }
    141161  }
     
    156176  int i;
    157177
    158   //~ not sure what this is supposed to do
    159178  for (i = 0; i < splashColorModeNComps[cm]; ++i) {
    160     blend[i] = dest[i] < src[i] ? src[i] - dest[i] : dest[i] - src[i];
     179    blend[i] = dest[i] + src[i] - (2 * dest[i] * src[i]) / 255;
    161180  }
    162181}
     
    198217    cmax = v;
    199218    if (x & 1) {
    200       cmid = (v * 255 - ((s * f) / 60)) >> 8;
     219      cmid = div255(v * 255 - ((s * f) / 60));
    201220    } else {
    202       cmid = (v * (255 - ((s * (60 - f)) / 60))) >> 8;
    203     }
    204     // note: floor(x / 255) = x >> 8 (for 16-bit x)
    205     cmin = (v * (255 - s)) >> 8;
     221      cmid = div255(v * (255 - ((s * (60 - f)) / 60)));
     222    }
     223    cmin = div255(v * (255 - s));
    206224    switch (x) {
    207225    case 0: *r = cmax; *g = cmid; *b = cmin; break;
     
    227245    blend[0] = dest[0];
    228246    break;
     247  case splashModeXBGR8:
     248    src[3] = 255;
    229249  case splashModeRGB8:
    230   case splashModeRGB8Qt:
     250  case splashModeBGR8:
    231251    cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
    232252    cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
    233253    cvtHSVToRGB(hs, sd, vd, &blend[0], &blend[1], &blend[2]);
    234     break;
    235   case splashModeBGR8:
    236     cvtRGBToHSV(src[2], src[1], src[0], &hs, &ss, &vs);
    237     cvtRGBToHSV(dest[2], dest[1], dest[0], &hd, &sd, &vd);
    238     cvtHSVToRGB(hs, sd, vd, &blend[2], &blend[1], &blend[0]);
    239254    break;
    240255#if SPLASH_CMYK
     
    250265    //~ should do black generation
    251266    blend[0] = 0xff - r;
    252     blend[0] = 0xff - g;
    253     blend[0] = 0xff - b;
     267    blend[1] = 0xff - g;
     268    blend[2] = 0xff - b;
    254269    blend[3] = 0;
    255270    break;
    256271#endif
    257   default:
    258     //~ unimplemented
    259     break;
    260272  }
    261273}
     
    274286    blend[0] = dest[0];
    275287    break;
     288  case splashModeXBGR8:
     289    src[3] = 255;
    276290  case splashModeRGB8:
    277   case splashModeRGB8Qt:
     291  case splashModeBGR8:
    278292    cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
    279293    cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
    280294    cvtHSVToRGB(hd, ss, vd, &blend[0], &blend[1], &blend[2]);
    281     break;
    282   case splashModeBGR8:
    283     cvtRGBToHSV(src[2], src[1], src[0], &hs, &ss, &vs);
    284     cvtRGBToHSV(dest[2], dest[1], dest[0], &hd, &sd, &vd);
    285     cvtHSVToRGB(hd, ss, vd, &blend[2], &blend[1], &blend[0]);
    286295    break;
    287296#if SPLASH_CMYK
     
    297306    //~ should do black generation
    298307    blend[0] = 0xff - r;
    299     blend[0] = 0xff - g;
    300     blend[0] = 0xff - b;
     308    blend[1] = 0xff - g;
     309    blend[2] = 0xff - b;
    301310    blend[3] = 0;
    302311    break;
    303312#endif
    304   default:
    305     //~ unimplemented
    306     break;
    307313  }
    308314}
     
    320326    blend[0] = dest[0];
    321327    break;
     328  case splashModeXBGR8:
     329    src[3] = 255;
    322330  case splashModeRGB8:
    323   case splashModeRGB8Qt:
     331  case splashModeBGR8:
    324332    cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
    325333    cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
    326334    cvtHSVToRGB(hs, ss, vd, &blend[0], &blend[1], &blend[2]);
    327     break;
    328   case splashModeBGR8:
    329     cvtRGBToHSV(src[2], src[1], src[0], &hs, &ss, &vs);
    330     cvtRGBToHSV(dest[2], dest[1], dest[0], &hd, &sd, &vd);
    331     cvtHSVToRGB(hs, ss, vd, &blend[2], &blend[1], &blend[0]);
    332335    break;
    333336#if SPLASH_CMYK
     
    343346    //~ should do black generation
    344347    blend[0] = 0xff - r;
    345     blend[0] = 0xff - g;
    346     blend[0] = 0xff - b;
     348    blend[1] = 0xff - g;
     349    blend[2] = 0xff - b;
    347350    blend[3] = 0;
    348351    break;
    349352#endif
    350   default:
    351     //~ unimplemented
    352     break;
    353353  }
    354354}
     
    367367    blend[0] = dest[0];
    368368    break;
     369  case splashModeXBGR8:
     370    src[3] = 255;
    369371  case splashModeRGB8:
    370   case splashModeRGB8Qt:
     372  case splashModeBGR8:
    371373    cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
    372374    cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
    373375    cvtHSVToRGB(hd, sd, vs, &blend[0], &blend[1], &blend[2]);
    374     break;
    375   case splashModeBGR8:
    376     cvtRGBToHSV(src[2], src[1], src[0], &hs, &ss, &vs);
    377     cvtRGBToHSV(dest[2], dest[1], dest[0], &hd, &sd, &vd);
    378     cvtHSVToRGB(hd, sd, vs, &blend[2], &blend[1], &blend[0]);
    379376    break;
    380377#if SPLASH_CMYK
     
    390387    //~ should do black generation
    391388    blend[0] = 0xff - r;
    392     blend[0] = 0xff - g;
    393     blend[0] = 0xff - b;
     389    blend[1] = 0xff - g;
     390    blend[2] = 0xff - b;
    394391    blend[3] = 0;
    395392    break;
    396393#endif
    397   default:
    398     //~ unimplemented
    399     break;
    400394  }
    401395}
     
    457451              double m21A, double m22A,
    458452              int glyphXA, int glyphYA, int glyphWA, int glyphHA,
    459               GBool aa);
     453              GBool aa, GBool validBBoxA);
    460454  ~T3FontCache();
    461455  GBool matches(Ref *idA, double m11A, double m12A,
     
    468462  int glyphX, glyphY;           // pixel offset of glyph bitmaps
    469463  int glyphW, glyphH;           // size of glyph bitmaps, in pixels
     464  GBool validBBox;              // false if the bbox was [0 0 0 0]
    470465  int glyphSize;                // size of glyph bitmaps, in bytes
    471466  int cacheSets;                // number of sets in cache
     
    478473                         double m21A, double m22A,
    479474                         int glyphXA, int glyphYA, int glyphWA, int glyphHA,
    480                          GBool aa) {
     475                         GBool validBBoxA, GBool aa) {
    481476  int i;
    482477
     
    490485  glyphW = glyphWA;
    491486  glyphH = glyphHA;
     487  validBBox = validBBoxA;
    492488  if (aa) {
    493489    glyphSize = glyphW * glyphH;
     
    505501    cacheSets = 1;
    506502  }
    507   cacheData = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize);
    508   cacheTags = (T3FontCacheTag *)gmallocn(cacheSets * cacheAssoc,
     503  cacheData = (Guchar *)gmallocn_checkoverflow(cacheSets * cacheAssoc, glyphSize);
     504  if (cacheData != NULL)
     505  {
     506    cacheTags = (T3FontCacheTag *)gmallocn(cacheSets * cacheAssoc,
    509507                                         sizeof(T3FontCacheTag));
    510   for (i = 0; i < cacheSets * cacheAssoc; ++i) {
    511     cacheTags[i].mru = i & (cacheAssoc - 1);
     508    for (i = 0; i < cacheSets * cacheAssoc; ++i) {
     509      cacheTags[i].mru = i & (cacheAssoc - 1);
     510    }
     511  }
     512  else
     513  {
     514    cacheTags = NULL;
    512515  }
    513516}
     
    520523struct T3GlyphStack {
    521524  Gushort code;                 // character code
    522   double x, y;                  // position to draw the glyph
    523525
    524526  //----- cache info
     
    533535
    534536  T3GlyphStack *next;           // next object on stack
     537};
     538
     539//------------------------------------------------------------------------
     540// SplashTransparencyGroup
     541//------------------------------------------------------------------------
     542
     543struct SplashTransparencyGroup {
     544  int tx, ty;                   // translation coordinates
     545  SplashBitmap *tBitmap;        // bitmap for transparency group
     546  GfxColorSpace *blendingColorSpace;
     547  GBool isolated;
     548
     549  //----- saved state
     550  SplashBitmap *origBitmap;
     551  Splash *origSplash;
     552
     553  SplashTransparencyGroup *next;
    535554};
    536555
     
    549568  bitmapTopDown = bitmapTopDownA;
    550569  allowAntialias = allowAntialiasA;
     570  vectorAntialias = allowAntialias &&
     571                      globalParams->getVectorAntialias() &&
     572                      colorMode != splashModeMono1;
     573  setupScreenParams(72.0, 72.0);
    551574  reverseVideo = reverseVideoA;
    552575  splashColorCopy(paperColor, paperColorA);
     
    554577  xref = NULL;
    555578
    556   bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode, bitmapTopDown);
    557   splash = new Splash(bitmap);
    558   splash->clear(paperColor);
     579  bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode,
     580                            colorMode != splashModeMono1, bitmapTopDown);
     581  splash = new Splash(bitmap, vectorAntialias, &screenParams);
     582  splash->clear(paperColor, 0);
    559583
    560584  fontEngine = NULL;
     
    566590  needFontUpdate = gFalse;
    567591  textClipPath = NULL;
     592
     593  transpGroupStack = NULL;
     594}
     595
     596void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) {
     597  screenParams.size = globalParams->getScreenSize();
     598  screenParams.dotRadius = globalParams->getScreenDotRadius();
     599  screenParams.gamma = (SplashCoord)globalParams->getScreenGamma();
     600  screenParams.blackThreshold =
     601      (SplashCoord)globalParams->getScreenBlackThreshold();
     602  screenParams.whiteThreshold =
     603      (SplashCoord)globalParams->getScreenWhiteThreshold();
     604  switch (globalParams->getScreenType()) {
     605  case screenDispersed:
     606    screenParams.type = splashScreenDispersed;
     607    if (screenParams.size < 0) {
     608      screenParams.size = 4;
     609    }
     610    break;
     611  case screenClustered:
     612    screenParams.type = splashScreenClustered;
     613    if (screenParams.size < 0) {
     614      screenParams.size = 10;
     615    }
     616    break;
     617  case screenStochasticClustered:
     618    screenParams.type = splashScreenStochasticClustered;
     619    if (screenParams.size < 0) {
     620      screenParams.size = 100;
     621    }
     622    if (screenParams.dotRadius < 0) {
     623      screenParams.dotRadius = 2;
     624    }
     625    break;
     626  case screenUnset:
     627  default:
     628    // use clustered dithering for resolution >= 300 dpi
     629    // (compare to 299.9 to avoid floating point issues)
     630    if (hDPI > 299.9 && vDPI > 299.9) {
     631      screenParams.type = splashScreenStochasticClustered;
     632      if (screenParams.size < 0) {
     633        screenParams.size = 100;
     634      }
     635      if (screenParams.dotRadius < 0) {
     636        screenParams.dotRadius = 2;
     637      }
     638    } else {
     639      screenParams.type = splashScreenDispersed;
     640      if (screenParams.size < 0) {
     641        screenParams.size = 4;
     642      }
     643    }
     644  }
    568645}
    569646
     
    610687void SplashOutputDev::startPage(int pageNum, GfxState *state) {
    611688  int w, h;
     689  double *ctm;
     690  SplashCoord mat[6];
    612691  SplashColor color;
    613692
    614   w = state ? (int)(state->getPageWidth() + 0.5) : 1;
    615   h = state ? (int)(state->getPageHeight() + 0.5) : 1;
     693  if (state) {
     694    setupScreenParams(state->getHDPI(), state->getVDPI());
     695    w = (int)(state->getPageWidth() + 0.5);
     696    if (w <= 0) {
     697      w = 1;
     698    }
     699    h = (int)(state->getPageHeight() + 0.5);
     700    if (h <= 0) {
     701      h = 1;
     702    }
     703  } else {
     704    w = h = 1;
     705  }
    616706  if (splash) {
    617707    delete splash;
     
    621711      delete bitmap;
    622712    }
    623     bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, bitmapTopDown);
    624   }
    625   splash = new Splash(bitmap);
     713    bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode,
     714                              colorMode != splashModeMono1, bitmapTopDown);
     715  }
     716  splash = new Splash(bitmap, vectorAntialias, &screenParams);
     717  if (state) {
     718    ctm = state->getCTM();
     719    mat[0] = (SplashCoord)ctm[0];
     720    mat[1] = (SplashCoord)ctm[1];
     721    mat[2] = (SplashCoord)ctm[2];
     722    mat[3] = (SplashCoord)ctm[3];
     723    mat[4] = (SplashCoord)ctm[4];
     724    mat[5] = (SplashCoord)ctm[5];
     725    splash->setMatrix(mat);
     726  }
    626727  switch (colorMode) {
    627728  case splashModeMono1:
     
    629730    color[0] = 0;
    630731    break;
     732  case splashModeXBGR8:
     733    color[3] = 255;
    631734  case splashModeRGB8:
    632735  case splashModeBGR8:
    633   case splashModeRGB8Qt:
    634736    color[0] = color[1] = color[2] = 0;
    635737    break;
    636   case splashModeAMono8:
    637     color[0] = 0xff;
    638     color[1] = 0;
    639     break;
    640   case splashModeARGB8:
    641     color[0] = 255;
    642     color[1] = color[2] = color[3] = 0;
    643     break;
    644   case splashModeBGRA8:
    645     color[0] = color[1] = color[2] = 0;
    646     color[3] = 255;
    647     break;
    648738#if SPLASH_CMYK
    649739  case splashModeCMYK8:
    650740    color[0] = color[1] = color[2] = color[3] = 0;
    651     break;
    652   case splashModeACMYK8:
    653     color[0] = 255;
    654     color[1] = color[2] = color[3] = color[4] = 0;
    655741    break;
    656742#endif
     
    663749  splash->setMiterLimit(10);
    664750  splash->setFlatness(1);
    665   splash->clear(paperColor);
     751  // the SA parameter supposedly defaults to false, but Acrobat
     752  // apparently hardwires it to true
     753  splash->setStrokeAdjust(globalParams->getStrokeAdjust());
     754  splash->clear(paperColor, 0);
    666755}
    667756
    668757void SplashOutputDev::endPage() {
    669 }
    670 
    671 void SplashOutputDev::drawLink(Link *link, Catalog *catalog) {
    672   double x1, y1, x2, y2;
    673   LinkBorderStyle *borderStyle;
    674   double r, g, b;
    675   GfxRGB rgb;
    676   GfxGray gray;
    677 #if SPLASH_CMYK
    678   GfxCMYK cmyk;
    679 #endif
    680   double *dash;
    681   int dashLength;
    682   SplashCoord dashList[20];
    683   SplashPath *path;
    684   int x, y, i;
    685 
    686   link->getRect(&x1, &y1, &x2, &y2);
    687   borderStyle = link->getBorderStyle();
    688   if (borderStyle->getWidth() > 0) {
    689     borderStyle->getColor(&r, &g, &b);
    690     rgb.r = dblToCol(r);
    691     rgb.g = dblToCol(g);
    692     rgb.b = dblToCol(b);
    693     gray = dblToCol(0.299 * r + 0.587 * g + 0.114 * b);
    694     if (gray > gfxColorComp1) {
    695       gray = gfxColorComp1;
    696     }
    697 #if SPLASH_CMYK
    698     cmyk.c = gfxColorComp1 - rgb.r;
    699     cmyk.m = gfxColorComp1 - rgb.g;
    700     cmyk.y = gfxColorComp1 - rgb.b;
    701     cmyk.k = 0;
    702     splash->setStrokePattern(getColor(gray, &rgb, &cmyk));
    703 #else
    704     splash->setStrokePattern(getColor(gray, &rgb));
    705 #endif
    706     splash->setLineWidth((SplashCoord)borderStyle->getWidth());
    707     borderStyle->getDash(&dash, &dashLength);
    708     if (borderStyle->getType() == linkBorderDashed && dashLength > 0) {
    709       if (dashLength > 20) {
    710         dashLength = 20;
    711       }
    712       for (i = 0; i < dashLength; ++i) {
    713         dashList[i] = (SplashCoord)dash[i];
    714       }
    715       splash->setLineDash(dashList, dashLength, 0);
    716     }
    717     path = new SplashPath();
    718     if (borderStyle->getType() == linkBorderUnderlined) {
    719       cvtUserToDev(x1, y1, &x, &y);
    720       path->moveTo((SplashCoord)x, (SplashCoord)y);
    721       cvtUserToDev(x2, y1, &x, &y);
    722       path->lineTo((SplashCoord)x, (SplashCoord)y);
    723     } else {
    724       cvtUserToDev(x1, y1, &x, &y);
    725       path->moveTo((SplashCoord)x, (SplashCoord)y);
    726       cvtUserToDev(x2, y1, &x, &y);
    727       path->lineTo((SplashCoord)x, (SplashCoord)y);
    728       cvtUserToDev(x2, y2, &x, &y);
    729       path->lineTo((SplashCoord)x, (SplashCoord)y);
    730       cvtUserToDev(x1, y2, &x, &y);
    731       path->lineTo((SplashCoord)x, (SplashCoord)y);
    732       path->close();
    733     }
    734     splash->stroke(path);
    735     delete path;
     758  if (colorMode != splashModeMono1) {
     759    splash->compositeBackground(paperColor);
    736760  }
    737761}
     
    753777  updateFlatness(state);
    754778  updateMiterLimit(state);
     779  updateStrokeAdjust(state);
    755780  updateFillColor(state);
    756781  updateStrokeColor(state);
     
    761786                                double m21, double m22,
    762787                                double m31, double m32) {
    763   updateLineDash(state);
    764   updateLineJoin(state);
    765   updateLineCap(state);
    766   updateLineWidth(state);
     788  double *ctm;
     789  SplashCoord mat[6];
     790
     791  ctm = state->getCTM();
     792  mat[0] = (SplashCoord)ctm[0];
     793  mat[1] = (SplashCoord)ctm[1];
     794  mat[2] = (SplashCoord)ctm[2];
     795  mat[3] = (SplashCoord)ctm[3];
     796  mat[4] = (SplashCoord)ctm[4];
     797  mat[5] = (SplashCoord)ctm[5];
     798  splash->setMatrix(mat);
    767799}
    768800
     
    772804  double dashStart;
    773805  SplashCoord dash[20];
    774   SplashCoord phase;
    775806  int i;
    776807
     
    780811  }
    781812  for (i = 0; i < dashLength; ++i) {
    782     dash[i] =  (SplashCoord)state->transformWidth(dashPattern[i]);
    783     if (dash[i] < 1) {
    784       dash[i] = 1;
    785     }
    786   }
    787   phase = (SplashCoord)state->transformWidth(dashStart);
    788   splash->setLineDash(dash, dashLength, phase);
     813    dash[i] = (SplashCoord)dashPattern[i];
     814    if (dash[i] < 0) {
     815      dash[i] = 0;
     816    }
     817  }
     818  splash->setLineDash(dash, dashLength, (SplashCoord)dashStart);
    789819}
    790820
     
    806836
    807837void SplashOutputDev::updateLineWidth(GfxState *state) {
    808   splash->setLineWidth(state->getTransformedLineWidth());
     838  splash->setLineWidth(state->getLineWidth());
     839}
     840
     841void SplashOutputDev::updateStrokeAdjust(GfxState * /*state*/) {
     842#if 0 // the SA parameter supposedly defaults to false, but Acrobat
     843      // apparently hardwires it to true
     844  splash->setStrokeAdjust(state->getStrokeAdjust());
     845#endif
    809846}
    810847
     
    850887#endif
    851888  SplashPattern *pattern;
    852   SplashColor color0, color1;
     889  SplashColor color;
    853890  GfxColorComp r, g, b;
    854891
     
    867904  switch (colorMode) {
    868905  case splashModeMono1:
    869     color0[0] = 0;
    870     color1[0] = 1;
    871     pattern = new SplashHalftone(color0, color1,
    872                                  splash->getScreen()->copy(),
    873                                  (SplashCoord)colToDbl(gray));
     906  case splashModeMono8:
     907    color[0] = colToByte(gray);
     908    pattern = new SplashSolidColor(color);
    874909    break;
    875   case splashModeMono8:
    876     color1[0] = colToByte(gray);
    877     pattern = new SplashSolidColor(color1);
     910  case splashModeXBGR8:
     911    color[3] = 255;
     912  case splashModeRGB8:
     913  case splashModeBGR8:
     914    color[0] = colToByte(r);
     915    color[1] = colToByte(g);
     916    color[2] = colToByte(b);
     917    pattern = new SplashSolidColor(color);
    878918    break;
    879   case splashModeAMono8:
    880     color1[0] = 255;
    881     color1[1] = colToByte(gray);
    882     pattern = new SplashSolidColor(color1);
    883     break;
    884   case splashModeRGB8:
    885   case splashModeRGB8Qt:
    886     color1[0] = colToByte(r);
    887     color1[1] = colToByte(g);
    888     color1[2] = colToByte(b);
    889     pattern = new SplashSolidColor(color1);
    890     break;
    891   case splashModeBGR8:
    892     color1[2] = colToByte(r);
    893     color1[1] = colToByte(g);
    894     color1[0] = colToByte(b);
    895     pattern = new SplashSolidColor(color1);
    896     break;
    897   case splashModeARGB8:
    898     color1[0] = 255;
    899     color1[1] = colToByte(r);
    900     color1[2] = colToByte(g);
    901     color1[3] = colToByte(b);
    902     pattern = new SplashSolidColor(color1);
    903     break;
    904   case splashModeBGRA8:
    905     color1[3] = 255;
    906     color1[2] = colToByte(r);
    907     color1[1] = colToByte(g);
    908     color1[0] = colToByte(b);
    909     pattern = new SplashSolidColor(color1);
    910     break;
    911919#if SPLASH_CMYK
    912920  case splashModeCMYK8:
    913     color1[0] = colToByte(cmyk->c);
    914     color1[1] = colToByte(cmyk->m);
    915     color1[2] = colToByte(cmyk->y);
    916     color1[3] = colToByte(cmyk->k);
    917     pattern = new SplashSolidColor(color1);
    918     break;
    919   case splashModeACMYK8:
    920     color1[0] = 255;
    921     color1[1] = colToByte(cmyk->c);
    922     color1[2] = colToByte(cmyk->m);
    923     color1[3] = colToByte(cmyk->y);
    924     color1[4] = colToByte(cmyk->k);
    925     pattern = new SplashSolidColor(color1);
     921    color[0] = colToByte(cmyk->c);
     922    color[1] = colToByte(cmyk->m);
     923    color[2] = colToByte(cmyk->y);
     924    color[3] = colToByte(cmyk->k);
     925    pattern = new SplashSolidColor(color);
    926926    break;
    927927#endif
     
    943943}
    944944
    945 void SplashOutputDev::updateFont(GfxState *state) {
     945void SplashOutputDev::updateFont(GfxState * /*state*/) {
     946  needFontUpdate = gTrue;
     947}
     948
     949void SplashOutputDev::doUpdateFont(GfxState *state) {
    946950  GfxFont *gfxFont;
    947951  GfxFontType fontType;
     
    952956  Ref embRef;
    953957  Object refObj, strObj;
    954   GooString *fileName, *substName;
     958  GooString *fileName;
    955959  char *tmpBuf;
    956960  int tmpBufLen;
    957961  Gushort *codeToGID;
    958962  DisplayFontParam *dfp;
    959   CharCodeToUnicode *ctu;
    960   double m11, m12, m21, m22, w1, w2;
     963  double *textMat;
     964  double m11, m12, m21, m22, fontSize;
    961965  SplashCoord mat[4];
    962   char *name;
    963   Unicode uBuf[8];
    964   int c, substIdx, n, code, cmap;
     966  int substIdx, n;
    965967  int faceIndex = 0;
     968  GBool recreateFont = gFalse;
    966969
    967970  needFontUpdate = gFalse;
     
    992995      if (! tmpBuf)
    993996        goto err2;
     997
    994998    // if there is an external font file, use it
    995999    } else if (!(fileName = gfxFont->getExtFontFile())) {
     
    10281032    switch (fontType) {
    10291033    case fontType1:
    1030       fontFile = fontEngine->loadType1Font(id, fontsrc,
    1031                                            ((Gfx8BitFont *)gfxFont)->getEncoding());
    1032       if (! fontFile) {
     1034      if (!(fontFile = fontEngine->loadType1Font(
     1035                           id,
     1036                           fontsrc,
     1037                           ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
    10331038        error(-1, "Couldn't create a font for '%s'",
    10341039              gfxFont->getName() ? gfxFont->getName()->getCString()
     
    10381043      break;
    10391044    case fontType1C:
    1040       fontFile = fontEngine->loadType1CFont(id, fontsrc,
    1041                                             ((Gfx8BitFont *)gfxFont)->getEncoding());
    1042       if (! fontFile) {
     1045      if (!(fontFile = fontEngine->loadType1CFont(
     1046                           id,
     1047                           fontsrc,
     1048                           ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
    10431049        error(-1, "Couldn't create a font for '%s'",
    10441050              gfxFont->getName() ? gfxFont->getName()->getCString()
     
    10471053      }
    10481054      break;
     1055    case fontType1COT:
     1056      if (!(fontFile = fontEngine->loadOpenTypeT1CFont(
     1057                           id,
     1058                           fontsrc,
     1059                           ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
     1060        error(-1, "Couldn't create a font for '%s'",
     1061              gfxFont->getName() ? gfxFont->getName()->getCString()
     1062                                 : "(unnamed)");
     1063        goto err2;
     1064      }
     1065      break;
    10491066    case fontTrueType:
     1067    case fontTrueTypeOT:
    10501068        if (fileName)
    10511069         ff = FoFiTrueType::load(fileName->getCString());
    10521070        else
    1053          ff = new FoFiTrueType(tmpBuf, tmpBufLen, gFalse);
    1054         if (ff) {
    1055       codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
     1071        ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
     1072      if (ff) {
     1073        codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
    10561074        n = 256;
    1057       delete ff;
     1075        delete ff;
    10581076      } else {
    10591077        codeToGID = NULL;
     
    10721090    case fontCIDType0:
    10731091    case fontCIDType0C:
    1074       fontFile = fontEngine->loadCIDFont(id, fontsrc);
    1075       if (! fontFile) {
     1092      if (!(fontFile = fontEngine->loadCIDFont(
     1093                           id,
     1094                           fontsrc))) {
    10761095        error(-1, "Couldn't create a font for '%s'",
    10771096              gfxFont->getName() ? gfxFont->getName()->getCString()
     
    10801099      }
    10811100      break;
    1082     case fontCIDType2:
    1083       codeToGID = NULL;
    1084       n = 0;
    1085       if (dfp) {
    1086         // create a CID-to-GID mapping, via Unicode
    1087         if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) {
    1088                 if (fileName)
    1089                  ff = FoFiTrueType::load(fileName->getCString());
    1090                 else
    1091                  ff = new FoFiTrueType(tmpBuf, tmpBufLen, gFalse);
    1092                 if (ff) {
    1093             // look for a Unicode cmap
    1094             for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) {
    1095               if ((ff->getCmapPlatform(cmap) == 3 &&
    1096                    ff->getCmapEncoding(cmap) == 1) ||
    1097                   ff->getCmapPlatform(cmap) == 0) {
    1098                 break;
    1099               }
    1100             }
    1101             if (cmap < ff->getNumCmaps()) {
    1102               // map CID -> Unicode -> GID
    1103               n = ctu->getLength();
    1104               codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
    1105               for (code = 0; code < n; ++code) {
    1106                 if (ctu->mapToUnicode(code, uBuf, 8) > 0) {
    1107                   codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]);
    1108                 } else {
    1109                   codeToGID[code] = 0;
    1110                 }
    1111               }
    1112             }
    1113             delete ff;
    1114           }
    1115           ctu->decRefCnt();
    1116         } else {
    1117           error(-1, "Couldn't find a mapping to Unicode for font '%s'",
    1118                 gfxFont->getName() ? gfxFont->getName()->getCString()
    1119                                    : "(unnamed)");
    1120         }
    1121       } else {
    1122         if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
    1123       n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
    1124         if (n) {
    1125                 codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
    1126                 memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
    1127                         n * sizeof(Gushort));
    1128         } else {
    1129                 if (fileName)
    1130                  ff = FoFiTrueType::load(fileName->getCString());
    1131                 else
    1132                  ff = new FoFiTrueType(tmpBuf, tmpBufLen, gFalse);
    1133                 if (! ff)
    1134                  goto err2;
    1135                 codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n);
    1136                 delete ff;
    1137         }
    1138         }
    1139       }
    1140       if (!(fontFile = fontEngine->loadTrueTypeFont(
     1101    case fontCIDType0COT:
     1102      if (!(fontFile = fontEngine->loadOpenTypeCFFFont(
    11411103                           id,
    1142                            fontsrc,
    1143                            codeToGID,
    1144                            n,
    1145                            faceIndex))) {
     1104                           fontsrc))) {
    11461105        error(-1, "Couldn't create a font for '%s'",
    11471106              gfxFont->getName() ? gfxFont->getName()->getCString()
     
    11501109      }
    11511110      break;
     1111    case fontCIDType2:
     1112    case fontCIDType2OT:
     1113      codeToGID = NULL;
     1114      n = 0;
     1115      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
     1116        n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
     1117        if (n) {
     1118          codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
     1119          memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
     1120                  n * sizeof(Gushort));
     1121        }
     1122      } else {
     1123        if (fileName)
     1124          ff = FoFiTrueType::load(fileName->getCString());
     1125        else
     1126          ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
     1127        if (! ff)
     1128          goto err2;
     1129        codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n);
     1130        delete ff;
     1131      }
     1132      if (!(fontFile = fontEngine->loadTrueTypeFont(
     1133                           id,
     1134                           fontsrc,
     1135                           codeToGID, n, faceIndex))) {
     1136        error(-1, "Couldn't create a font for '%s'",
     1137              gfxFont->getName() ? gfxFont->getName()->getCString()
     1138                                 : "(unnamed)");
     1139        goto err2;
     1140      }
     1141      break;
    11521142    default:
    11531143      // this shouldn't happen
    11541144      goto err2;
    11551145    }
     1146    fontFile->doAdjustMatrix = gTrue;
    11561147  }
    11571148
    11581149  // get the font matrix
    1159   state->getFontTransMat(&m11, &m12, &m21, &m22);
    1160   m11 *= state->getHorizScaling();
    1161   m12 *= state->getHorizScaling();
     1150  textMat = state->getTextMat();
     1151  fontSize = state->getFontSize();
     1152  m11 = textMat[0] * fontSize * state->getHorizScaling();
     1153  m12 = textMat[1] * fontSize * state->getHorizScaling();
     1154  m21 = textMat[2] * fontSize;
     1155  m22 = textMat[3] * fontSize;
    11621156
    11631157  // create the scaled font
    1164   mat[0] = m11;  mat[1] = -m12;
    1165   mat[2] = m21;  mat[3] = -m22;
    1166   if (fabs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.01) {
    1167     // avoid a singular (or close-to-singular) matrix
    1168     mat[0] = 0.01;  mat[1] = 0;
    1169     mat[2] = 0;     mat[3] = 0.01;
    1170   }
    1171   font = fontEngine->getFont(fontFile, mat);
     1158  mat[0] = m11;  mat[1] = m12;
     1159  mat[2] = m21;  mat[3] = m22;
     1160  font = fontEngine->getFont(fontFile, mat, splash->getMatrix());
     1161
     1162  // for substituted fonts: adjust the font matrix -- compare the
     1163  // width of 'm' in the original font and the substituted font
     1164  if (fontFile->doAdjustMatrix && !gfxFont->isCIDFont()) {
     1165    double w1, w2;
     1166    CharCode code;
     1167    char *name;
     1168    for (code = 0; code < 256; ++code) {
     1169      if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
     1170          name[0] == 'm' && name[1] == '\0') {
     1171        break;
     1172      }
     1173    }
     1174    if (code < 256) {
     1175      w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
     1176      w2 = font->getGlyphAdvance(code);
     1177      if (!gfxFont->isSymbolic() && w2 > 0) {
     1178        // if real font is substantially narrower than substituted
     1179        // font, reduce the font size accordingly
     1180        if (w1 > 0.01 && w1 < 0.9 * w2) {
     1181          w1 /= w2;
     1182          m11 *= w1;
     1183          m21 *= w1;
     1184          recreateFont = gTrue;
     1185        }
     1186      }
     1187    }
     1188  }
     1189
     1190  if (recreateFont)
     1191  {
     1192    mat[0] = m11;  mat[1] = m12;
     1193    mat[2] = m21;  mat[3] = m22;
     1194    font = fontEngine->getFont(fontFile, mat, splash->getMatrix());
     1195  }
    11721196
    11731197  if (fontsrc && !fontsrc->isFile)
     
    11861210  SplashPath *path;
    11871211
     1212  if (state->getStrokeColorSpace()->isNonMarking()) {
     1213    return;
     1214  }
    11881215  path = convertPath(state, state->getPath());
    11891216  splash->stroke(path);
     
    11941221  SplashPath *path;
    11951222
     1223  if (state->getFillColorSpace()->isNonMarking()) {
     1224    return;
     1225  }
    11961226  path = convertPath(state, state->getPath());
    11971227  splash->fill(path, gFalse);
     
    12021232  SplashPath *path;
    12031233
     1234  if (state->getFillColorSpace()->isNonMarking()) {
     1235    return;
     1236  }
    12041237  path = convertPath(state, state->getPath());
    12051238  splash->fill(path, gTrue);
     
    12231256}
    12241257
    1225 SplashPath *SplashOutputDev::convertPath(GfxState *state, GfxPath *path) {
     1258void SplashOutputDev::clipToStrokePath(GfxState *state) {
     1259  SplashPath *path, *path2;
     1260
     1261  path = convertPath(state, state->getPath());
     1262  path2 = splash->makeStrokePath(path);
     1263  delete path;
     1264  splash->clipToPath(path2, gFalse);
     1265  delete path2;
     1266}
     1267
     1268SplashPath *SplashOutputDev::convertPath(GfxState * /*state*/, GfxPath *path) {
    12261269  SplashPath *sPath;
    12271270  GfxSubpath *subpath;
    1228   double x1, y1, x2, y2, x3, y3;
    12291271  int i, j;
    12301272
     
    12331275    subpath = path->getSubpath(i);
    12341276    if (subpath->getNumPoints() > 0) {
    1235       state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
    1236       sPath->moveTo((SplashCoord)x1, (SplashCoord)y1);
     1277      sPath->moveTo((SplashCoord)subpath->getX(0),
     1278                    (SplashCoord)subpath->getY(0));
    12371279      j = 1;
    12381280      while (j < subpath->getNumPoints()) {
    12391281        if (subpath->getCurve(j)) {
    1240           state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
    1241           state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
    1242           state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
    1243           sPath->curveTo((SplashCoord)x1, (SplashCoord)y1,
    1244                          (SplashCoord)x2, (SplashCoord)y2,
    1245                          (SplashCoord)x3, (SplashCoord)y3);
     1282          sPath->curveTo((SplashCoord)subpath->getX(j),
     1283                         (SplashCoord)subpath->getY(j),
     1284                         (SplashCoord)subpath->getX(j+1),
     1285                         (SplashCoord)subpath->getY(j+1),
     1286                         (SplashCoord)subpath->getX(j+2),
     1287                         (SplashCoord)subpath->getY(j+2));
    12461288          j += 3;
    12471289        } else {
    1248           state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
    1249           sPath->lineTo((SplashCoord)x1, (SplashCoord)y1);
     1290          sPath->lineTo((SplashCoord)subpath->getX(j),
     1291                        (SplashCoord)subpath->getY(j));
    12501292          ++j;
    12511293        }
     
    12641306                               CharCode code, int nBytes,
    12651307                               Unicode *u, int uLen) {
    1266   double x1, y1;
    12671308  SplashPath *path;
    12681309  int render;
    1269 
    1270   if (needFontUpdate) {
    1271     updateFont(state);
    1272   }
    1273   if (!font) {
    1274     return;
    1275   }
    12761310
    12771311  // check for invisible text -- this is used by Acrobat Capture
     
    12811315  }
    12821316
     1317  if (needFontUpdate) {
     1318    doUpdateFont(state);
     1319  }
     1320  if (!font) {
     1321    return;
     1322  }
     1323
    12831324  x -= originX;
    12841325  y -= originY;
    1285   state->transform(x, y, &x1, &y1);
    12861326
    12871327  // fill
    12881328  if (!(render & 1)) {
    1289     splash->fillChar((SplashCoord)x1, (SplashCoord)y1, code, font);
     1329    if (!state->getFillColorSpace()->isNonMarking()) {
     1330      splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font);
     1331    }
    12901332  }
    12911333
    12921334  // stroke
    12931335  if ((render & 3) == 1 || (render & 3) == 2) {
    1294     if ((path = font->getGlyphPath(code))) {
    1295       path->offset((SplashCoord)x1, (SplashCoord)y1);
    1296       splash->stroke(path);
    1297       delete path;
     1336    if (!state->getStrokeColorSpace()->isNonMarking()) {
     1337      if ((path = font->getGlyphPath(code))) {
     1338        path->offset((SplashCoord)x, (SplashCoord)y);
     1339        splash->stroke(path);
     1340        delete path;
     1341      }
    12981342    }
    12991343  }
     
    13011345  // clip
    13021346  if (render & 4) {
    1303     path = font->getGlyphPath(code);
    1304     path->offset((SplashCoord)x1, (SplashCoord)y1);
    1305     if (textClipPath) {
    1306       textClipPath->append(path);
    1307       delete path;
    1308     } else {
    1309       textClipPath = path;
     1347    if ((path = font->getGlyphPath(code))) {
     1348      path->offset((SplashCoord)x, (SplashCoord)y);
     1349      if (textClipPath) {
     1350        textClipPath->append(path);
     1351        delete path;
     1352      } else {
     1353        textClipPath = path;
     1354      }
    13101355    }
    13111356  }
     
    13201365  T3FontCache *t3Font;
    13211366  T3GlyphStack *t3gs;
     1367  GBool validBBox;
    13221368  double x1, y1, xMin, yMin, xMax, yMax, xt, yt;
    13231369  int i, j;
     
    13581404      bbox = gfxFont->getFontBBox();
    13591405      if (bbox[0] == 0 && bbox[1] == 0 && bbox[2] == 0 && bbox[3] == 0) {
    1360         // broken bounding box -- just take a guess
     1406        // unspecified bounding box -- just take a guess
    13611407        xMin = xt - 5;
    13621408        xMax = xMin + 30;
    13631409        yMax = yt + 15;
    13641410        yMin = yMax - 45;
     1411        validBBox = gFalse;
    13651412      } else {
    13661413        state->transform(bbox[0], bbox[1], &x1, &y1);
     
    14001447          yMax = y1;
    14011448        }
     1449        validBBox = gTrue;
    14021450      }
    14031451      t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[3],
     
    14061454                                       (int)ceil(xMax) - (int)floor(xMin) + 3,
    14071455                                       (int)ceil(yMax) - (int)floor(yMin) + 3,
     1456                                       validBBox,
    14081457                                       colorMode != splashModeMono1);
    14091458    }
     
    14141463  i = (code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc;
    14151464  for (j = 0; j < t3Font->cacheAssoc; ++j) {
    1416     if ((t3Font->cacheTags[i+j].mru & 0x8000) &&
     1465    if (t3Font->cacheTags != NULL) {
     1466      if ((t3Font->cacheTags[i+j].mru & 0x8000) &&
    14171467        t3Font->cacheTags[i+j].code == code) {
    1418       drawType3Glyph(t3Font, &t3Font->cacheTags[i+j],
    1419                      t3Font->cacheData + (i+j) * t3Font->glyphSize,
    1420                      xt, yt);
    1421       return gTrue;
     1468        drawType3Glyph(t3Font, &t3Font->cacheTags[i+j],
     1469                     t3Font->cacheData + (i+j) * t3Font->glyphSize);
     1470        return gTrue;
     1471      }
    14221472    }
    14231473  }
     
    14281478  t3GlyphStack = t3gs;
    14291479  t3GlyphStack->code = code;
    1430   t3GlyphStack->x = xt;
    1431   t3GlyphStack->y = yt;
    14321480  t3GlyphStack->cache = t3Font;
    14331481  t3GlyphStack->cacheTag = NULL;
     
    14511499    state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
    14521500                  t3GlyphStack->origCTM4, t3GlyphStack->origCTM5);
     1501    updateCTM(state, 0, 0, 0, 0, 0, 0);
    14531502    drawType3Glyph(t3GlyphStack->cache,
    1454                    t3GlyphStack->cacheTag, t3GlyphStack->cacheData,
    1455                    t3GlyphStack->x, t3GlyphStack->y);
     1503                   t3GlyphStack->cacheTag, t3GlyphStack->cacheData);
    14561504  }
    14571505  t3gs = t3GlyphStack;
     
    15151563      xMax - xt > t3Font->glyphX + t3Font->glyphW ||
    15161564      yMax - yt > t3Font->glyphY + t3Font->glyphH) {
    1517     error(-1, "Bad bounding box in Type 3 glyph");
     1565    if (t3Font->validBBox) {
     1566      error(-1, "Bad bounding box in Type 3 glyph");
     1567    }
    15181568    return;
    15191569  }
     
    15421592  if (colorMode == splashModeMono1) {
    15431593    bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1,
    1544                               splashModeMono1);
    1545     splash = new Splash(bitmap);
     1594                              splashModeMono1, gFalse);
     1595    splash = new Splash(bitmap, gFalse,
     1596                        t3GlyphStack->origSplash->getScreen());
    15461597    color[0] = 0;
    15471598    splash->clear(color);
     
    15491600  } else {
    15501601    bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1,
    1551                               splashModeMono8);
    1552     splash = new Splash(bitmap);
     1602                              splashModeMono8, gFalse);
     1603    splash = new Splash(bitmap, vectorAntialias,
     1604                        t3GlyphStack->origSplash->getScreen());
    15531605    color[0] = 0x00;
    15541606    splash->clear(color);
     
    15601612  state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
    15611613                -t3Font->glyphX, -t3Font->glyphY);
     1614  updateCTM(state, 0, 0, 0, 0, 0, 0);
    15621615}
    15631616
    15641617void SplashOutputDev::drawType3Glyph(T3FontCache *t3Font,
    1565                                      T3FontCacheTag *tag, Guchar *data,
    1566                                      double x, double y) {
     1618                                     T3FontCacheTag * /*tag*/, Guchar *data) {
    15671619  SplashGlyphBitmap glyph;
    15681620
     
    15741626  glyph.data = data;
    15751627  glyph.freeData = gFalse;
    1576   splash->fillGlyph((SplashCoord)x, (SplashCoord)y, &glyph);
     1628  splash->fillGlyph(0, 0, &glyph);
    15771629}
    15781630
     
    16151667  SplashCoord mat[6];
    16161668  SplashOutImageMaskData imgMaskData;
     1669
     1670  if (state->getFillColorSpace()->isNonMarking()) {
     1671    return;
     1672  }
    16171673
    16181674  ctm = state->getCTM();
     
    16311687  imgMaskData.y = 0;
    16321688
    1633   splash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat);
     1689  splash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat,
     1690                        t3GlyphStack != NULL);
    16341691  if (inlineImg) {
    16351692    while (imgMaskData.y < height) {
     
    16521709};
    16531710
    1654 GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr line) {
     1711GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
     1712                                Guchar * /*alphaLine*/) {
    16551713  SplashOutImageData *imgData = (SplashOutImageData *)data;
    16561714  Guchar *p;
     
    16731731  case splashModeMono1:
    16741732  case splashModeMono8:
    1675       for (x = 0, p = imgData->imgStr->getLine(), q = line;
     1733      for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
    16761734           x < imgData->width;
    16771735           ++x, ++p) {
     
    16801738    break;
    16811739  case splashModeRGB8:
    1682     case splashModeBGR8:
    1683     case splashModeRGB8Qt:
    1684       for (x = 0, p = imgData->imgStr->getLine(), q = line;
     1740  case splashModeBGR8:
     1741      for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
    16851742           x < imgData->width;
    16861743           ++x, ++p) {
     
    16911748      }
    16921749    break;
    1693 #if SPLASH_CMYK
    1694     case splashModeCMYK8:
    1695       for (x = 0, p = imgData->imgStr->getLine(), q = line;
     1750  case splashModeXBGR8:
     1751      for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
    16961752           x < imgData->width;
    16971753           ++x, ++p) {
     
    17031759      }
    17041760      break;
    1705 #endif
    1706     case splashModeAMono8:
    1707     case splashModeARGB8:
    1708     case splashModeBGRA8:
    1709 #if SPLASH_CMYK
    1710     case splashModeACMYK8:
    1711 #endif
    1712       //~ unimplemented
    1713     break;
     1761#if SPLASH_CMYK
     1762    case splashModeCMYK8:
     1763      for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
     1764           x < imgData->width;
     1765           ++x, ++p) {
     1766        col = &imgData->lookup[4 * *p];
     1767        *q++ = col[0];
     1768        *q++ = col[1];
     1769        *q++ = col[2];
     1770        *q++ = col[3];
     1771      }
     1772      break;
     1773#endif
    17141774  }
    17151775  } else {
     
    17171777    case splashModeMono1:
    17181778    case splashModeMono8:
    1719       for (x = 0, p = imgData->imgStr->getLine(), q = line;
     1779      for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
    17201780           x < imgData->width;
    17211781           ++x, p += nComps) {
     
    17241784      }
    17251785        break;
     1786        case splashModeXBGR8:
    17261787    case splashModeRGB8:
    1727     case splashModeRGB8Qt:
    1728       for (x = 0, p = imgData->imgStr->getLine(), q = line;
     1788    case splashModeBGR8:
     1789      for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
    17291790           x < imgData->width;
    17301791           ++x, p += nComps) {
     
    17331794        *q++ = colToByte(rgb.g);
    17341795        *q++ = colToByte(rgb.b);
     1796        if (imgData->colorMode == splashModeXBGR8) *q++ = 255;
    17351797      }
    17361798      break;
    1737     case splashModeBGR8:
    1738       for (x = 0, p = imgData->imgStr->getLine(), q = line;
    1739            x < imgData->width;
    1740            ++x, p += nComps) {
    1741         imgData->colorMap->getRGB(p, &rgb);
    1742         *q++ = colToByte(rgb.b);
    1743         *q++ = colToByte(rgb.g);
    1744         *q++ = colToByte(rgb.r);
    1745       }
    1746       break;
    17471799#if SPLASH_CMYK
    17481800    case splashModeCMYK8:
    1749       for (x = 0, p = imgData->imgStr->getLine(), q = line;
     1801      for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
    17501802           x < imgData->width;
    17511803           ++x, p += nComps) {
     
    17581810      break;
    17591811#endif
    1760     case splashModeAMono8:
    1761     case splashModeARGB8:
    1762     case splashModeBGRA8:
    1763 #if SPLASH_CMYK
    1764     case splashModeACMYK8:
    1765 #endif
    1766       //~ unimplemented
    1767       break;
    17681812    }
    17691813  }
     
    17731817}
    17741818
    1775 GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr line) {
     1819GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
     1820                                     Guchar *alphaLine) {
    17761821  SplashOutImageData *imgData = (SplashOutImageData *)data;
    1777   Guchar *p;
     1822  Guchar *p, *aq;
    17781823  SplashColorPtr q, col;
    17791824  GfxRGB rgb;
     
    17911836  nComps = imgData->colorMap->getNumPixelComps();
    17921837
    1793   for (x = 0, p = imgData->imgStr->getLine(), q = line;
     1838  for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine;
    17941839       x < imgData->width;
    17951840       ++x, p += nComps) {
     
    18061851      case splashModeMono1:
    18071852      case splashModeMono8:
    1808         *q++ = alpha;
    18091853        *q++ = imgData->lookup[*p];
     1854        *aq++ = alpha;
    18101855        break;
    18111856      case splashModeRGB8:
    1812       case splashModeRGB8Qt:
    1813         *q++ = alpha;
    1814         col = &imgData->lookup[3 * *p];
    1815         *q++ = col[0];
    1816         *q++ = col[1];
    1817         *q++ = col[2];
    1818         break;
    18191857      case splashModeBGR8:
    18201858        col = &imgData->lookup[3 * *p];
     
    18221860        *q++ = col[1];
    18231861        *q++ = col[2];
    1824         *q++ = alpha;
     1862        *aq++ = alpha;
    18251863        break;
     1864      case splashModeXBGR8:
     1865        col = &imgData->lookup[4 * *p];
     1866        *q++ = col[0];
     1867        *q++ = col[1];
     1868        *q++ = col[2];
     1869        *q++ = 255;
     1870        *aq++ = alpha;
     1871        break;
    18261872#if SPLASH_CMYK
    18271873      case splashModeCMYK8:
    1828         *q++ = alpha;
    18291874        col = &imgData->lookup[4 * *p];
    18301875        *q++ = col[0];
     
    18321877        *q++ = col[2];
    18331878        *q++ = col[3];
     1879        *aq++ = alpha;
    18341880        break;
    18351881#endif
    1836       case splashModeAMono8:
    1837       case splashModeARGB8:
    1838       case splashModeBGRA8:
    1839 #if SPLASH_CMYK
    1840       case splashModeACMYK8:
    1841 #endif
    1842         //~ unimplemented
    1843         break;
    18441882      }
    18451883    } else {
     
    18481886      case splashModeMono8:
    18491887        imgData->colorMap->getGray(p, &gray);
    1850         *q++ = alpha;
    18511888        *q++ = colToByte(gray);
     1889        *aq++ = alpha;
    18521890        break;
     1891      case splashModeXBGR8:
    18531892      case splashModeRGB8:
    1854       case splashModeRGB8Qt:
     1893      case splashModeBGR8:
    18551894        imgData->colorMap->getRGB(p, &rgb);
    1856         *q++ = alpha;
    18571895        *q++ = colToByte(rgb.r);
    18581896        *q++ = colToByte(rgb.g);
    18591897        *q++ = colToByte(rgb.b);
    1860         break;
    1861       case splashModeBGR8:
    1862         imgData->colorMap->getRGB(p, &rgb);
    1863         *q++ = colToByte(rgb.b);
    1864         *q++ = colToByte(rgb.g);
    1865         *q++ = colToByte(rgb.r);
    1866         *q++ = alpha;
     1898        if (imgData->colorMode == splashModeXBGR8) *q++ = 255;
     1899        *aq++ = alpha;
    18671900        break;
    18681901#if SPLASH_CMYK
    18691902      case splashModeCMYK8:
    18701903        imgData->colorMap->getCMYK(p, &cmyk);
    1871         *q++ = alpha;
    18721904        *q++ = colToByte(cmyk.c);
    18731905        *q++ = colToByte(cmyk.m);
    18741906        *q++ = colToByte(cmyk.y);
    18751907        *q++ = colToByte(cmyk.k);
     1908        *aq++ = alpha;
    18761909        break;
    18771910#endif
    1878       case splashModeAMono8:
    1879       case splashModeARGB8:
    1880       case splashModeBGRA8:
    1881 #if SPLASH_CMYK
    1882       case splashModeACMYK8:
    1883 #endif
    1884         //~ unimplemented
    1885         break;
    18861911      }
    18871912    }
     
    19441969      break;
    19451970    case splashModeRGB8:
    1946     case splashModeRGB8Qt:
     1971    case splashModeBGR8:
    19471972      imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
    19481973      for (i = 0; i < n; ++i) {
     
    19541979      }
    19551980      break;
    1956     case splashModeBGR8:
    1957       imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
     1981    case splashModeXBGR8:
     1982      imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
    19581983      for (i = 0; i < n; ++i) {
    19591984        pix = (Guchar)i;
    19601985        colorMap->getRGB(&pix, &rgb);
    1961         imgData.lookup[3*i] = colToByte(rgb.b);
    1962         imgData.lookup[3*i+1] = colToByte(rgb.g);
    1963         imgData.lookup[3*i+2] = colToByte(rgb.r);
     1986        imgData.lookup[4*i] = colToByte(rgb.r);
     1987        imgData.lookup[4*i+1] = colToByte(rgb.g);
     1988        imgData.lookup[4*i+2] = colToByte(rgb.b);
     1989        imgData.lookup[4*i+3] = 255;
    19641990      }
    19651991      break;
     
    19772003      break;
    19782004#endif
    1979     default:
    1980       //~ unimplemented
    19812005      break;
    19822006    }
    19832007  }
    19842008
    1985   switch (colorMode) {
    1986   case splashModeMono1:
    1987   case splashModeMono8:
    1988     srcMode = maskColors ? splashModeAMono8 : splashModeMono8;
    1989     break;
    1990   case splashModeRGB8:
    1991   case splashModeRGB8Qt:
    1992     srcMode = maskColors ? splashModeARGB8 : splashModeRGB8;
    1993     break;
    1994   case splashModeBGR8:
    1995     srcMode = maskColors ? splashModeBGRA8 : splashModeBGR8;
    1996     break;
    1997 #if SPLASH_CMYK
    1998   case splashModeCMYK8:
    1999     srcMode = maskColors ? splashModeACMYK8 : splashModeCMYK8;
    2000     break;
    2001 #endif
    2002   default:
    2003     //~ unimplemented
    2004     srcMode = splashModeRGB8;
    2005     break;
    2006   } 
     2009  if (colorMode == splashModeMono1) {
     2010    srcMode = splashModeMono8;
     2011  } else {
     2012    srcMode = colorMode;
     2013  }
    20072014  src = maskColors ? &alphaImageSrc : &imageSrc;
    2008   splash->drawImage(src, &imgData, srcMode, width, height, mat);
     2015  splash->drawImage(src, &imgData, srcMode, maskColors ? gTrue : gFalse,
     2016                    width, height, mat);
    20092017  if (inlineImg) {
    20102018    while (imgData.y < height) {
     
    20282036};
    20292037
    2030 GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr line) {
     2038GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
     2039                                      Guchar *alphaLine) {
    20312040  SplashOutMaskedImageData *imgData = (SplashOutMaskedImageData *)data;
    2032   Guchar *p;
     2041  Guchar *p, *aq;
    20332042  SplashColor maskColor;
    20342043  SplashColorPtr q, col;
     
    20472056  nComps = imgData->colorMap->getNumPixelComps();
    20482057
    2049   for (x = 0, p = imgData->imgStr->getLine(), q = line;
     2058  for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine;
    20502059       x < imgData->width;
    20512060       ++x, p += nComps) {
     
    20562065      case splashModeMono1:
    20572066      case splashModeMono8:
    2058         *q++ = alpha;
    20592067        *q++ = imgData->lookup[*p];
     2068        *aq++ = alpha;
    20602069        break;
    20612070      case splashModeRGB8:
    2062       case splashModeRGB8Qt:
    2063         *q++ = alpha;
    2064         col = &imgData->lookup[3 * *p];
    2065         *q++ = col[0];
    2066         *q++ = col[1];
    2067         *q++ = col[2];
    2068         break;
    20692071      case splashModeBGR8:
    20702072        col = &imgData->lookup[3 * *p];
     
    20722074        *q++ = col[1];
    20732075        *q++ = col[2];
    2074         *q++ = alpha;
     2076        *aq++ = alpha;
    20752077        break;
     2078      case splashModeXBGR8:
     2079        col = &imgData->lookup[4 * *p];
     2080        *q++ = col[0];
     2081        *q++ = col[1];
     2082        *q++ = col[2];
     2083        *q++ = 255;
     2084        *aq++ = alpha;
     2085        break;
    20762086#if SPLASH_CMYK
    20772087      case splashModeCMYK8:
    2078         *q++ = alpha;
    20792088        col = &imgData->lookup[4 * *p];
    20802089        *q++ = col[0];
     
    20822091        *q++ = col[2];
    20832092        *q++ = col[3];
     2093        *aq++ = alpha;
    20842094        break;
    20852095#endif
    2086       case splashModeAMono8:
    2087       case splashModeARGB8:
    2088       case splashModeBGRA8:
    2089 #if SPLASH_CMYK
    2090       case splashModeACMYK8:
    2091 #endif
    2092         //~ unimplemented
    2093         break;
    20942096      }
    20952097    } else {
     
    20982100      case splashModeMono8:
    20992101        imgData->colorMap->getGray(p, &gray);
    2100         *q++ = alpha;
    21012102        *q++ = colToByte(gray);
     2103        *aq++ = alpha;
    21022104        break;
     2105      case splashModeXBGR8:
    21032106      case splashModeRGB8:
    2104       case splashModeRGB8Qt:
     2107      case splashModeBGR8:
    21052108        imgData->colorMap->getRGB(p, &rgb);
    2106         *q++ = alpha;
    21072109        *q++ = colToByte(rgb.r);
    21082110        *q++ = colToByte(rgb.g);
    21092111        *q++ = colToByte(rgb.b);
    2110         break;
    2111       case splashModeBGR8:
    2112         imgData->colorMap->getRGB(p, &rgb);
    2113         *q++ = colToByte(rgb.b);
    2114         *q++ = colToByte(rgb.g);
    2115         *q++ = colToByte(rgb.r);
    2116         *q++ = alpha;
     2112        if (imgData->colorMode == splashModeXBGR8) *q++ = 255;
     2113        *aq++ = alpha;
    21172114        break;
    21182115#if SPLASH_CMYK
    21192116      case splashModeCMYK8:
    21202117        imgData->colorMap->getCMYK(p, &cmyk);
    2121         *q++ = alpha;
    21222118        *q++ = colToByte(cmyk.c);
    21232119        *q++ = colToByte(cmyk.m);
    21242120        *q++ = colToByte(cmyk.y);
    21252121        *q++ = colToByte(cmyk.k);
     2122        *aq++ = alpha;
    21262123        break;
    21272124#endif
    2128       case splashModeAMono8:
    2129       case splashModeARGB8:
    2130       case splashModeBGRA8:
    2131 #if SPLASH_CMYK
    2132       case splashModeACMYK8:
    2133 #endif
    2134         //~ unimplemented
    2135         break;
    21362125      }
    21372126    }
     
    21472136                                      Stream *maskStr, int maskWidth,
    21482137                                      int maskHeight, GBool maskInvert) {
     2138  GfxImageColorMap *maskColorMap;
     2139  Object maskDecode, decodeLow, decodeHigh;
    21492140  double *ctm;
    21502141  SplashCoord mat[6];
     
    21632154  int n, i;
    21642155
    2165   //----- scale the mask image to the same size as the source image
    2166 
    2167   mat[0] = (SplashCoord)width;
    2168   mat[1] = 0;
    2169   mat[2] = 0;
    2170   mat[3] = (SplashCoord)height;
    2171   mat[4] = 0;
    2172   mat[5] = 0;
    2173   imgMaskData.imgStr = new ImageStream(maskStr, maskWidth, 1, 1);
    2174   imgMaskData.imgStr->reset();
    2175   imgMaskData.invert = maskInvert ? 0 : 1;
    2176   imgMaskData.width = maskWidth;
    2177   imgMaskData.height = maskHeight;
    2178   imgMaskData.y = 0;
    2179   maskBitmap = new SplashBitmap(width, height, 1, splashModeMono1);
    2180   maskSplash = new Splash(maskBitmap);
    2181   maskColor[0] = 0;
    2182   maskSplash->clear(maskColor);
    2183   maskColor[0] = 1;
    2184   maskSplash->setFillPattern(new SplashSolidColor(maskColor));
    2185   maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData,
    2186                             maskWidth, maskHeight, mat);
    2187   delete imgMaskData.imgStr;
    2188   maskStr->close();
    2189   delete maskSplash;
    2190 
    2191   //----- draw the source image
    2192 
    2193   ctm = state->getCTM();
    2194   mat[0] = ctm[0];
    2195   mat[1] = ctm[1];
    2196   mat[2] = -ctm[2];
    2197   mat[3] = -ctm[3];
    2198   mat[4] = ctm[2] + ctm[4];
    2199   mat[5] = ctm[3] + ctm[5];
    2200 
    2201   imgData.imgStr = new ImageStream(str, width,
    2202                                    colorMap->getNumPixelComps(),
    2203                                    colorMap->getBits());
    2204   imgData.imgStr->reset();
    2205   imgData.colorMap = colorMap;
    2206   imgData.mask = maskBitmap;
    2207   imgData.colorMode = colorMode;
    2208   imgData.width = width;
    2209   imgData.height = height;
    2210   imgData.y = 0;
    2211 
    2212   // special case for one-channel (monochrome/gray/separation) images:
    2213   // build a lookup table here
    2214   imgData.lookup = NULL;
    2215   if (colorMap->getNumPixelComps() == 1) {
    2216     n = 1 << colorMap->getBits();
    2217     switch (colorMode) {
    2218     case splashModeMono1:
    2219     case splashModeMono8:
    2220       imgData.lookup = (SplashColorPtr)gmalloc(n);
    2221       for (i = 0; i < n; ++i) {
    2222         pix = (Guchar)i;
    2223         colorMap->getGray(&pix, &gray);
    2224         imgData.lookup[i] = colToByte(gray);
    2225       }
    2226       break;
    2227     case splashModeRGB8:
    2228     case splashModeRGB8Qt:
    2229       imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
    2230       for (i = 0; i < n; ++i) {
    2231         pix = (Guchar)i;
    2232         colorMap->getRGB(&pix, &rgb);
    2233         imgData.lookup[3*i] = colToByte(rgb.r);
    2234         imgData.lookup[3*i+1] = colToByte(rgb.g);
    2235         imgData.lookup[3*i+2] = colToByte(rgb.b);
    2236       }
    2237       break;
    2238     case splashModeBGR8:
    2239       imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
    2240       for (i = 0; i < n; ++i) {
    2241         pix = (Guchar)i;
    2242         colorMap->getRGB(&pix, &rgb);
    2243         imgData.lookup[3*i] = colToByte(rgb.b);
    2244         imgData.lookup[3*i+1] = colToByte(rgb.g);
    2245         imgData.lookup[3*i+2] = colToByte(rgb.r);
    2246       }
    2247       break;
    2248 #if SPLASH_CMYK
    2249     case splashModeCMYK8:
    2250       imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
    2251       for (i = 0; i < n; ++i) {
    2252         pix = (Guchar)i;
    2253         colorMap->getCMYK(&pix, &cmyk);
    2254         imgData.lookup[4*i] = colToByte(cmyk.c);
    2255         imgData.lookup[4*i+1] = colToByte(cmyk.m);
    2256         imgData.lookup[4*i+2] = colToByte(cmyk.y);
    2257         imgData.lookup[4*i+3] = colToByte(cmyk.k);
    2258       }
    2259       break;
    2260 #endif
    2261     default:
    2262       //~ unimplemented
    2263       break;
    2264     }
    2265   }
    2266 
    2267   switch (colorMode) {
    2268   case splashModeMono1:
    2269   case splashModeMono8:
    2270     srcMode = splashModeAMono8;
    2271     break;
    2272   case splashModeRGB8:
    2273   case splashModeRGB8Qt:
    2274     srcMode = splashModeARGB8;
    2275     break;
    2276   case splashModeBGR8:
    2277     srcMode = splashModeBGRA8;
    2278     break;
    2279 #if SPLASH_CMYK
    2280   case splashModeCMYK8:
    2281     srcMode = splashModeACMYK8;
    2282     break;
    2283 #endif
    2284   default:
    2285     //~ unimplemented
    2286     srcMode = splashModeARGB8;
    2287     break;
    2288   } 
    2289   splash->drawImage(&maskedImageSrc, &imgData, srcMode, width, height, mat);
    2290 
    2291   delete maskBitmap;
    2292   gfree(imgData.lookup);
    2293   delete imgData.imgStr;
    2294   str->close();
     2156  // If the mask is higher resolution than the image, use
     2157  // drawSoftMaskedImage() instead.
     2158  if (maskWidth > width || maskHeight > height) {
     2159    decodeLow.initInt(maskInvert ? 0 : 1);
     2160    decodeHigh.initInt(maskInvert ? 1 : 0);
     2161    maskDecode.initArray(xref);
     2162    maskDecode.arrayAdd(&decodeLow);
     2163    maskDecode.arrayAdd(&decodeHigh);
     2164    maskColorMap = new GfxImageColorMap(1, &maskDecode,
     2165                                        new GfxDeviceGrayColorSpace());
     2166    maskDecode.free();
     2167    drawSoftMaskedImage(state, ref, str, width, height, colorMap,
     2168                        maskStr, maskWidth, maskHeight, maskColorMap);
     2169    delete maskColorMap;
     2170
     2171  } else {
     2172
     2173    //----- scale the mask image to the same size as the source image
     2174
     2175    mat[0] = (SplashCoord)width;
     2176    mat[1] = 0;
     2177    mat[2] = 0;
     2178    mat[3] = (SplashCoord)height;
     2179    mat[4] = 0;
     2180    mat[5] = 0;
     2181    imgMaskData.imgStr = new ImageStream(maskStr, maskWidth, 1, 1);
     2182    imgMaskData.imgStr->reset();
     2183    imgMaskData.invert = maskInvert ? 0 : 1;
     2184    imgMaskData.width = maskWidth;
     2185    imgMaskData.height = maskHeight;
     2186    imgMaskData.y = 0;
     2187    maskBitmap = new SplashBitmap(width, height, 1, splashModeMono1, gFalse);
     2188    maskSplash = new Splash(maskBitmap, gFalse);
     2189    maskColor[0] = 0;
     2190    maskSplash->clear(maskColor);
     2191    maskColor[0] = 0xff;
     2192    maskSplash->setFillPattern(new SplashSolidColor(maskColor));
     2193    maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData,
     2194                              maskWidth, maskHeight, mat, gFalse);
     2195    delete imgMaskData.imgStr;
     2196    maskStr->close();
     2197    delete maskSplash;
     2198
     2199    //----- draw the source image
     2200
     2201    ctm = state->getCTM();
     2202    mat[0] = ctm[0];
     2203    mat[1] = ctm[1];
     2204    mat[2] = -ctm[2];
     2205    mat[3] = -ctm[3];
     2206    mat[4] = ctm[2] + ctm[4];
     2207    mat[5] = ctm[3] + ctm[5];
     2208
     2209    imgData.imgStr = new ImageStream(str, width,
     2210                                     colorMap->getNumPixelComps(),
     2211                                     colorMap->getBits());
     2212    imgData.imgStr->reset();
     2213    imgData.colorMap = colorMap;
     2214    imgData.mask = maskBitmap;
     2215    imgData.colorMode = colorMode;
     2216    imgData.width = width;
     2217    imgData.height = height;
     2218    imgData.y = 0;
     2219
     2220    // special case for one-channel (monochrome/gray/separation) images:
     2221    // build a lookup table here
     2222    imgData.lookup = NULL;
     2223    if (colorMap->getNumPixelComps() == 1) {
     2224      n = 1 << colorMap->getBits();
     2225      switch (colorMode) {
     2226      case splashModeMono1:
     2227      case splashModeMono8:
     2228        imgData.lookup = (SplashColorPtr)gmalloc(n);
     2229        for (i = 0; i < n; ++i) {
     2230          pix = (Guchar)i;
     2231          colorMap->getGray(&pix, &gray);
     2232          imgData.lookup[i] = colToByte(gray);
     2233        }
     2234        break;
     2235      case splashModeRGB8:
     2236      case splashModeBGR8:
     2237        imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
     2238        for (i = 0; i < n; ++i) {
     2239          pix = (Guchar)i;
     2240          colorMap->getRGB(&pix, &rgb);
     2241          imgData.lookup[3*i] = colToByte(rgb.r);
     2242          imgData.lookup[3*i+1] = colToByte(rgb.g);
     2243          imgData.lookup[3*i+2] = colToByte(rgb.b);
     2244        }
     2245        break;
     2246      case splashModeXBGR8:
     2247        imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
     2248        for (i = 0; i < n; ++i) {
     2249          pix = (Guchar)i;
     2250          colorMap->getRGB(&pix, &rgb);
     2251          imgData.lookup[4*i] = colToByte(rgb.r);
     2252          imgData.lookup[4*i+1] = colToByte(rgb.g);
     2253          imgData.lookup[4*i+2] = colToByte(rgb.b);
     2254          imgData.lookup[4*i+3] = 255;
     2255        }
     2256        break;
     2257#if SPLASH_CMYK
     2258      case splashModeCMYK8:
     2259        imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
     2260        for (i = 0; i < n; ++i) {
     2261          pix = (Guchar)i;
     2262          colorMap->getCMYK(&pix, &cmyk);
     2263          imgData.lookup[4*i] = colToByte(cmyk.c);
     2264          imgData.lookup[4*i+1] = colToByte(cmyk.m);
     2265          imgData.lookup[4*i+2] = colToByte(cmyk.y);
     2266          imgData.lookup[4*i+3] = colToByte(cmyk.k);
     2267        }
     2268        break;
     2269#endif
     2270      }
     2271    }
     2272
     2273    if (colorMode == splashModeMono1) {
     2274      srcMode = splashModeMono8;
     2275    } else {
     2276      srcMode = colorMode;
     2277    }
     2278    splash->drawImage(&maskedImageSrc, &imgData, srcMode, gTrue,
     2279                      width, height, mat);
     2280
     2281    delete maskBitmap;
     2282    gfree(imgData.lookup);
     2283    delete imgData.imgStr;
     2284    str->close();
     2285  }
    22952286}
    22962287
     
    23452336  }
    23462337  maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
    2347                                 1, splashModeMono8);
    2348   maskSplash = new Splash(maskBitmap);
     2338                                1, splashModeMono8, gFalse);
     2339  maskSplash = new Splash(maskBitmap, vectorAntialias);
    23492340  maskColor[0] = 0;
    23502341  maskSplash->clear(maskColor);
    2351   maskSplash->drawImage(&imageSrc, &imgMaskData,
    2352                         splashModeMono8, maskWidth, maskHeight, mat);
     2342  maskSplash->drawImage(&imageSrc, &imgMaskData, splashModeMono8, gFalse,
     2343                        maskWidth, maskHeight, mat);
    23532344  delete imgMaskData.imgStr;
    23542345  maskStr->close();
     
    23862377      break;
    23872378    case splashModeRGB8:
    2388     case splashModeRGB8Qt:
     2379    case splashModeBGR8:
    23892380      imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
    23902381      for (i = 0; i < n; ++i) {
     
    23962387      }
    23972388      break;
    2398     case splashModeBGR8:
    2399       imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
     2389    case splashModeXBGR8:
     2390      imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
    24002391      for (i = 0; i < n; ++i) {
    24012392        pix = (Guchar)i;
    24022393        colorMap->getRGB(&pix, &rgb);
    2403         imgData.lookup[3*i] = colToByte(rgb.b);
    2404         imgData.lookup[3*i+1] = colToByte(rgb.g);
    2405         imgData.lookup[3*i+2] = colToByte(rgb.r);
     2394        imgData.lookup[4*i] = colToByte(rgb.r);
     2395        imgData.lookup[4*i+1] = colToByte(rgb.g);
     2396        imgData.lookup[4*i+2] = colToByte(rgb.b);
     2397        imgData.lookup[4*i+3] = 255;
    24062398      }
    24072399      break;
     
    24192411      break;
    24202412#endif
    2421     default:
    2422       //~ unimplemented
    2423       break;
    2424     }
    2425   }
    2426 
    2427   switch (colorMode) {
    2428   case splashModeMono1:
    2429   case splashModeMono8:
     2413    }
     2414  }
     2415
     2416  if (colorMode == splashModeMono1) {
    24302417    srcMode = splashModeMono8;
    2431     break;
    2432   case splashModeRGB8:
    2433   case splashModeRGB8Qt:
    2434     srcMode = splashModeRGB8;
    2435     break;
    2436   case splashModeBGR8:
    2437     srcMode = splashModeBGR8;
    2438     break;
    2439 #if SPLASH_CMYK
    2440   case splashModeCMYK8:
    2441     srcMode = splashModeCMYK8;
    2442     break;
    2443 #endif
    2444   default:
    2445     //~ unimplemented
    2446     srcMode = splashModeRGB8;
    2447     break;
    2448   } 
    2449   splash->drawImage(&imageSrc, &imgData, srcMode, width, height, mat);
     2418  } else {
     2419    srcMode = colorMode;
     2420  }
     2421  splash->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat);
    24502422
    24512423  splash->setSoftMask(NULL);
     
    24552427}
    24562428
     2429void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
     2430                                             GfxColorSpace *blendingColorSpace,
     2431                                             GBool isolated, GBool /*knockout*/,
     2432                                             GBool /*forSoftMask*/) {
     2433  SplashTransparencyGroup *transpGroup;
     2434  SplashColor color;
     2435  double xMin, yMin, xMax, yMax, x, y;
     2436  int tx, ty, w, h;
     2437
     2438  // transform the bbox
     2439  state->transform(bbox[0], bbox[1], &x, &y);
     2440  xMin = xMax = x;
     2441  yMin = yMax = y;
     2442  state->transform(bbox[0], bbox[3], &x, &y);
     2443  if (x < xMin) {
     2444    xMin = x;
     2445  } else if (x > xMax) {
     2446    xMax = x;
     2447  }
     2448  if (y < yMin) {
     2449    yMin = y;
     2450  } else if (y > yMax) {
     2451    yMax = y;
     2452  }
     2453  state->transform(bbox[2], bbox[1], &x, &y);
     2454  if (x < xMin) {
     2455    xMin = x;
     2456  } else if (x > xMax) {
     2457    xMax = x;
     2458  }
     2459  if (y < yMin) {
     2460    yMin = y;
     2461  } else if (y > yMax) {
     2462    yMax = y;
     2463  }
     2464  state->transform(bbox[2], bbox[3], &x, &y);
     2465  if (x < xMin) {
     2466    xMin = x;
     2467  } else if (x > xMax) {
     2468    xMax = x;
     2469  }
     2470  if (y < yMin) {
     2471    yMin = y;
     2472  } else if (y > yMax) {
     2473    yMax = y;
     2474  }
     2475  tx = (int)floor(xMin);
     2476  if (tx < 0) {
     2477    tx = 0;
     2478  } else if (tx > bitmap->getWidth()) {
     2479    tx = bitmap->getWidth();
     2480  }
     2481  ty = (int)floor(yMin);
     2482  if (ty < 0) {
     2483    ty = 0;
     2484  } else if (ty > bitmap->getHeight()) {
     2485    ty = bitmap->getHeight();
     2486  }
     2487  w = (int)ceil(xMax) - tx + 1;
     2488  if (tx + w > bitmap->getWidth()) {
     2489    w = bitmap->getWidth() - tx;
     2490  }
     2491  if (w < 1) {
     2492    w = 1;
     2493  }
     2494  h = (int)ceil(yMax) - ty + 1;
     2495  if (ty + h > bitmap->getHeight()) {
     2496    h = bitmap->getHeight() - ty;
     2497  }
     2498  if (h < 1) {
     2499    h = 1;
     2500  }
     2501
     2502  // push a new stack entry
     2503  transpGroup = new SplashTransparencyGroup();
     2504  transpGroup->tx = tx;
     2505  transpGroup->ty = ty;
     2506  transpGroup->blendingColorSpace = blendingColorSpace;
     2507  transpGroup->isolated = isolated;
     2508  transpGroup->next = transpGroupStack;
     2509  transpGroupStack = transpGroup;
     2510
     2511  // save state
     2512  transpGroup->origBitmap = bitmap;
     2513  transpGroup->origSplash = splash;
     2514
     2515  //~ this ignores the blendingColorSpace arg
     2516
     2517  // create the temporary bitmap
     2518  bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue,
     2519                            bitmapTopDown);
     2520  splash = new Splash(bitmap, vectorAntialias,
     2521                      transpGroup->origSplash->getScreen());
     2522  if (isolated) {
     2523    switch (colorMode) {
     2524    case splashModeMono1:
     2525    case splashModeMono8:
     2526      color[0] = 0;
     2527      break;
     2528    case splashModeXBGR8:
     2529      color[3] = 255;
     2530    case splashModeRGB8:
     2531    case splashModeBGR8:
     2532      color[0] = color[1] = color[2] = 0;
     2533      break;
     2534#if SPLASH_CMYK
     2535    case splashModeCMYK8:
     2536      color[0] = color[1] = color[2] = color[3] = 0;
     2537      break;
     2538#endif
     2539    default:
     2540      // make gcc happy
     2541      break;
     2542    }
     2543    splash->clear(color, 0);
     2544  } else {
     2545    splash->blitTransparent(transpGroup->origBitmap, tx, ty, 0, 0, w, h);
     2546    splash->setInNonIsolatedGroup(transpGroup->origBitmap, tx, ty);
     2547  }
     2548  transpGroup->tBitmap = bitmap;
     2549  state->shiftCTM(-tx, -ty);
     2550  updateCTM(state, 0, 0, 0, 0, 0, 0);
     2551}
     2552
     2553void SplashOutputDev::endTransparencyGroup(GfxState *state) {
     2554  double *ctm;
     2555
     2556  // restore state
     2557  delete splash;
     2558  bitmap = transpGroupStack->origBitmap;
     2559  splash = transpGroupStack->origSplash;
     2560  ctm = state->getCTM();
     2561  state->shiftCTM(transpGroupStack->tx, transpGroupStack->ty);
     2562  updateCTM(state, 0, 0, 0, 0, 0, 0);
     2563}
     2564
     2565void SplashOutputDev::paintTransparencyGroup(GfxState * /*state*/, double * /*bbox*/) {
     2566  SplashBitmap *tBitmap;
     2567  SplashTransparencyGroup *transpGroup;
     2568  GBool isolated;
     2569  int tx, ty;
     2570
     2571  tx = transpGroupStack->tx;
     2572  ty = transpGroupStack->ty;
     2573  tBitmap = transpGroupStack->tBitmap;
     2574  isolated = transpGroupStack->isolated;
     2575
     2576  // paint the transparency group onto the parent bitmap
     2577  // - the clip path was set in the parent's state)
     2578  splash->composite(tBitmap, 0, 0, tx, ty,
     2579                    tBitmap->getWidth(), tBitmap->getHeight(),
     2580                    gFalse, !isolated);
     2581
     2582  // pop the stack
     2583  transpGroup = transpGroupStack;
     2584  transpGroupStack = transpGroup->next;
     2585  delete transpGroup;
     2586
     2587  delete tBitmap;
     2588}
     2589
     2590void SplashOutputDev::setSoftMask(GfxState * /*state*/, double * /*bbox*/,
     2591                                  GBool alpha, Function *transferFunc,
     2592                                  GfxColor *backdropColor) {
     2593  SplashBitmap *softMask, *tBitmap;
     2594  Splash *tSplash;
     2595  SplashTransparencyGroup *transpGroup;
     2596  SplashColor color;
     2597  SplashColorPtr p;
     2598  GfxGray gray;
     2599  GfxRGB rgb;
     2600#if SPLASH_CMYK
     2601  GfxCMYK cmyk;
     2602#endif
     2603  double lum, lum2;
     2604  int tx, ty, x, y;
     2605
     2606  tx = transpGroupStack->tx;
     2607  ty = transpGroupStack->ty;
     2608  tBitmap = transpGroupStack->tBitmap;
     2609
     2610  // composite with backdrop color
     2611  if (!alpha && colorMode != splashModeMono1) {
     2612    //~ need to correctly handle the case where no blending color
     2613    //~ space is given
     2614    if (transpGroupStack->blendingColorSpace) {
     2615      tSplash = new Splash(tBitmap, vectorAntialias,
     2616                           transpGroupStack->origSplash->getScreen());
     2617      switch (colorMode) {
     2618      case splashModeMono1:
     2619        // transparency is not supported in mono1 mode
     2620        break;
     2621      case splashModeMono8:
     2622        transpGroupStack->blendingColorSpace->getGray(backdropColor, &gray);
     2623        color[0] = colToByte(gray);
     2624        tSplash->compositeBackground(color);
     2625        break;
     2626      case splashModeXBGR8:
     2627        color[3] = 255;
     2628      case splashModeRGB8:
     2629      case splashModeBGR8:
     2630        transpGroupStack->blendingColorSpace->getRGB(backdropColor, &rgb);
     2631        color[0] = colToByte(rgb.r);
     2632        color[1] = colToByte(rgb.g);
     2633        color[2] = colToByte(rgb.b);
     2634        tSplash->compositeBackground(color);
     2635        break;
     2636#if SPLASH_CMYK
     2637      case splashModeCMYK8:
     2638        transpGroupStack->blendingColorSpace->getCMYK(backdropColor, &cmyk);
     2639        color[0] = colToByte(cmyk.c);
     2640        color[1] = colToByte(cmyk.m);
     2641        color[2] = colToByte(cmyk.y);
     2642        color[3] = colToByte(cmyk.k);
     2643        tSplash->compositeBackground(color);
     2644        break;
     2645#endif
     2646      }
     2647      delete tSplash;
     2648    }
     2649  }
     2650
     2651  softMask = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
     2652                              1, splashModeMono8, gFalse);
     2653  memset(softMask->getDataPtr(), 0,
     2654         softMask->getRowSize() * softMask->getHeight());
     2655  p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx;
     2656  int xMax = tBitmap->getWidth();
     2657  int yMax = tBitmap->getHeight();
     2658  if (xMax + tx > bitmap->getWidth()) xMax = bitmap->getWidth() - tx;
     2659  if (yMax + ty > bitmap->getHeight()) yMax = bitmap->getHeight() - ty;
     2660  for (y = 0; y < yMax; ++y) {
     2661    for (x = 0; x < xMax; ++x) {
     2662      tBitmap->getPixel(x, y, color);
     2663      if (alpha) {
     2664        //~ unimplemented
     2665      } else {
     2666        // convert to luminosity
     2667        switch (colorMode) {
     2668        case splashModeMono1:
     2669        case splashModeMono8:
     2670          lum = color[0] / 255.0;
     2671          break;
     2672        case splashModeXBGR8:
     2673        case splashModeRGB8:
     2674        case splashModeBGR8:
     2675          lum = (0.3 / 255.0) * color[0] +
     2676                (0.59 / 255.0) * color[1] +
     2677                (0.11 / 255.0) * color[2];
     2678          break;
     2679#if SPLASH_CMYK
     2680        case splashModeCMYK8:
     2681          lum = (1 - color[4] / 255.0)
     2682                - (0.3 / 255.0) * color[0]
     2683                - (0.59 / 255.0) * color[1]
     2684                - (0.11 / 255.0) * color[2];
     2685          if (lum < 0) {
     2686            lum = 0;
     2687          }
     2688          break;
     2689#endif
     2690        }
     2691        if (transferFunc) {
     2692          transferFunc->transform(&lum, &lum2);
     2693        } else {
     2694          lum2 = lum;
     2695        }
     2696        p[x] = (int)(lum2 * 255.0 + 0.5);
     2697      }
     2698    }
     2699    p += softMask->getRowSize();
     2700  }
     2701  splash->setSoftMask(softMask);
     2702
     2703  // pop the stack
     2704  transpGroup = transpGroupStack;
     2705  transpGroupStack = transpGroup->next;
     2706  delete transpGroup;
     2707
     2708  delete tBitmap;
     2709}
     2710
     2711void SplashOutputDev::clearSoftMask(GfxState * /*state*/) {
     2712  splash->setSoftMask(NULL);
     2713}
     2714
    24572715void SplashOutputDev::setPaperColor(SplashColorPtr paperColorA) {
    24582716  splashColorCopy(paperColor, paperColorA);
     
    24712729
    24722730  ret = bitmap;
    2473   bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode, bitmapTopDown);
     2731  bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode,
     2732                            colorMode != splashModeMono1, bitmapTopDown);
    24742733  return ret;
    24752734}
     
    24942753  rgb.g = byteToCol(g);
    24952754  rgb.b = byteToCol(b);
    2496   gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.g + 0.5);
     2755  gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b + 0.5);
    24972756  if (gray > gfxColorComp1) {
    24982757    gray = gfxColorComp1;
     
    25092768}
    25102769
     2770#if 1 //~tmp: turn off anti-aliasing temporarily
     2771GBool SplashOutputDev::getVectorAntialias() {
     2772  return splash->getVectorAntialias();
     2773}
     2774
     2775void SplashOutputDev::setVectorAntialias(GBool vaa) {
     2776  splash->setVectorAntialias(vaa);
     2777}
     2778#endif
Note: See TracChangeset for help on using the changeset viewer.