summaryrefslogtreecommitdiffstats
path: root/kpdf/xpdf/xpdf/SplashOutputDev.cc
diff options
context:
space:
mode:
Diffstat (limited to 'kpdf/xpdf/xpdf/SplashOutputDev.cc')
-rw-r--r--kpdf/xpdf/xpdf/SplashOutputDev.cc2851
1 files changed, 0 insertions, 2851 deletions
diff --git a/kpdf/xpdf/xpdf/SplashOutputDev.cc b/kpdf/xpdf/xpdf/SplashOutputDev.cc
deleted file mode 100644
index fe235fb8..00000000
--- a/kpdf/xpdf/xpdf/SplashOutputDev.cc
+++ /dev/null
@@ -1,2851 +0,0 @@
-//========================================================================
-//
-// SplashOutputDev.cc
-//
-// Copyright 2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <string.h>
-#include <math.h>
-#include "gfile.h"
-#include "GlobalParams.h"
-#include "Error.h"
-#include "Object.h"
-#include "GfxFont.h"
-#include "Link.h"
-#include "CharCodeToUnicode.h"
-#include "FontEncodingTables.h"
-#include "FoFiTrueType.h"
-#include "SplashBitmap.h"
-#include "SplashGlyphBitmap.h"
-#include "SplashPattern.h"
-#include "SplashScreen.h"
-#include "SplashPath.h"
-#include "SplashState.h"
-#include "SplashErrorCodes.h"
-#include "SplashFontEngine.h"
-#include "SplashFont.h"
-#include "SplashFontFile.h"
-#include "SplashFontFileID.h"
-#include "Splash.h"
-#include "SplashOutputDev.h"
-
-#ifdef VMS
-#if (__VMS_VER < 70000000)
-extern "C" int unlink(char *filename);
-#endif
-#endif
-
-//------------------------------------------------------------------------
-
-// Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result.
-static inline Guchar div255(int x) {
- return (Guchar)((x + (x >> 8) + 0x80) >> 8);
-}
-
-//------------------------------------------------------------------------
-// Blend functions
-//------------------------------------------------------------------------
-
-static void splashOutBlendMultiply(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = (dest[i] * src[i]) / 255;
- }
-}
-
-static void splashOutBlendScreen(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] + src[i] - (dest[i] * src[i]) / 255;
- }
-}
-
-static void splashOutBlendOverlay(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] < 0x80
- ? (src[i] * 2 * dest[i]) / 255
- : 255 - 2 * ((255 - src[i]) * (255 - dest[i])) / 255;
- }
-}
-
-static void splashOutBlendDarken(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] < src[i] ? dest[i] : src[i];
- }
-}
-
-static void splashOutBlendLighten(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] > src[i] ? dest[i] : src[i];
- }
-}
-
-static void splashOutBlendColorDodge(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend,
- SplashColorMode cm) {
- int i, x;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- if (src[i] == 255) {
- blend[i] = 255;
- } else {
- x = (dest[i] * 255) / (255 - src[i]);
- blend[i] = x <= 255 ? x : 255;
- }
- }
-}
-
-static void splashOutBlendColorBurn(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i, x;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- if (src[i] == 0) {
- blend[i] = 0;
- } else {
- x = ((255 - dest[i]) * 255) / src[i];
- blend[i] = x <= 255 ? 255 - x : 0;
- }
- }
-}
-
-static void splashOutBlendHardLight(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = src[i] < 0x80
- ? (dest[i] * 2 * src[i]) / 255
- : 255 - 2 * ((255 - dest[i]) * (255 - src[i])) / 255;
- }
-}
-
-static void splashOutBlendSoftLight(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i, x;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- if (src[i] < 0x80) {
- blend[i] = dest[i] - (255 - 2 * src[i]) * dest[i] * (255 - dest[i]) /
- (255 * 255);
- } else {
- if (dest[i] < 0x40) {
- x = (((((16 * dest[i] - 12 * 255) * dest[i]) / 255)
- + 4 * 255) * dest[i]) / 255;
- } else {
- x = (int)sqrt(255.0 * dest[i]);
- }
- blend[i] = dest[i] + (2 * src[i] - 255) * (x - dest[i]) / 255;
- }
- }
-}
-
-static void splashOutBlendDifference(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend,
- SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] < src[i] ? src[i] - dest[i] : dest[i] - src[i];
- }
-}
-
-static void splashOutBlendExclusion(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] + src[i] - (2 * dest[i] * src[i]) / 255;
- }
-}
-
-static void cvtRGBToHSV(Guchar r, Guchar g, Guchar b, int *h, int *s, int *v) {
- int cmax, cmid, cmin, x;
-
- if (r >= g) {
- if (g >= b) { x = 0; cmax = r; cmid = g; cmin = b; }
- else if (b >= r) { x = 4; cmax = b; cmid = r; cmin = g; }
- else { x = 5; cmax = r; cmid = b; cmin = g; }
- } else {
- if (r >= b) { x = 1; cmax = g; cmid = r; cmin = b; }
- else if (g >= b) { x = 2; cmax = g; cmid = b; cmin = r; }
- else { x = 3; cmax = b; cmid = g; cmin = r; }
- }
- if (cmax == cmin) {
- *h = *s = 0;
- } else {
- *h = x * 60;
- if (x & 1) {
- *h += ((cmax - cmid) * 60) / (cmax - cmin);
- } else {
- *h += ((cmid - cmin) * 60) / (cmax - cmin);
- }
- *s = (255 * (cmax - cmin)) / cmax;
- }
- *v = cmax;
-}
-
-static void cvtHSVToRGB(int h, int s, int v, Guchar *r, Guchar *g, Guchar *b) {
- int x, f, cmax, cmid, cmin;
-
- if (s == 0) {
- *r = *g = *b = v;
- } else {
- x = h / 60;
- f = h % 60;
- cmax = v;
- if (x & 1) {
- cmid = div255(v * 255 - ((s * f) / 60));
- } else {
- cmid = div255(v * (255 - ((s * (60 - f)) / 60)));
- }
- cmin = div255(v * (255 - s));
- switch (x) {
- case 0: *r = cmax; *g = cmid; *b = cmin; break;
- case 1: *g = cmax; *r = cmid; *b = cmin; break;
- case 2: *g = cmax; *b = cmid; *r = cmin; break;
- case 3: *b = cmax; *g = cmid; *r = cmin; break;
- case 4: *b = cmax; *r = cmid; *g = cmin; break;
- case 5: *r = cmax; *b = cmid; *g = cmin; break;
- }
- }
-}
-
-static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int hs, ss, vs, hd, sd, vd;
-#if SPLASH_CMYK
- Guchar r, g, b;
-#endif
-
- switch (cm) {
- case splashModeMono1:
- case splashModeMono8:
- blend[0] = dest[0];
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
- cvtHSVToRGB(hs, sd, vd, &blend[0], &blend[1], &blend[2]);
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- //~ (0xff - ...) should be clipped
- cvtRGBToHSV(0xff - (src[0] + src[3]),
- 0xff - (src[1] + src[3]),
- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
- 0xff - (dest[1] + dest[3]),
- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
- cvtHSVToRGB(hs, sd, vd, &r, &g, &b);
- //~ should do black generation
- blend[0] = 0xff - r;
- blend[1] = 0xff - g;
- blend[2] = 0xff - b;
- blend[3] = 0;
- break;
-#endif
- }
-}
-
-static void splashOutBlendSaturation(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend,
- SplashColorMode cm) {
- int hs, ss, vs, hd, sd, vd;
-#if SPLASH_CMYK
- Guchar r, g, b;
-#endif
-
- switch (cm) {
- case splashModeMono1:
- case splashModeMono8:
- blend[0] = dest[0];
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
- cvtHSVToRGB(hd, ss, vd, &blend[0], &blend[1], &blend[2]);
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- //~ (0xff - ...) should be clipped
- cvtRGBToHSV(0xff - (src[0] + src[3]),
- 0xff - (src[1] + src[3]),
- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
- 0xff - (dest[1] + dest[3]),
- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
- cvtHSVToRGB(hd, ss, vd, &r, &g, &b);
- //~ should do black generation
- blend[0] = 0xff - r;
- blend[1] = 0xff - g;
- blend[2] = 0xff - b;
- blend[3] = 0;
- break;
-#endif
- }
-}
-
-static void splashOutBlendColor(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int hs, ss, vs, hd, sd, vd;
-#if SPLASH_CMYK
- Guchar r, g, b;
-#endif
-
- switch (cm) {
- case splashModeMono1:
- case splashModeMono8:
- blend[0] = dest[0];
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
- cvtHSVToRGB(hs, ss, vd, &blend[0], &blend[1], &blend[2]);
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- //~ (0xff - ...) should be clipped
- cvtRGBToHSV(0xff - (src[0] + src[3]),
- 0xff - (src[1] + src[3]),
- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
- 0xff - (dest[1] + dest[3]),
- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
- cvtHSVToRGB(hs, ss, vd, &r, &g, &b);
- //~ should do black generation
- blend[0] = 0xff - r;
- blend[1] = 0xff - g;
- blend[2] = 0xff - b;
- blend[3] = 0;
- break;
-#endif
- }
-}
-
-static void splashOutBlendLuminosity(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend,
- SplashColorMode cm) {
- int hs, ss, vs, hd, sd, vd;
-#if SPLASH_CMYK
- Guchar r, g, b;
-#endif
-
- switch (cm) {
- case splashModeMono1:
- case splashModeMono8:
- blend[0] = dest[0];
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
- cvtHSVToRGB(hd, sd, vs, &blend[0], &blend[1], &blend[2]);
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- //~ (0xff - ...) should be clipped
- cvtRGBToHSV(0xff - (src[0] + src[3]),
- 0xff - (src[1] + src[3]),
- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
- 0xff - (dest[1] + dest[3]),
- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
- cvtHSVToRGB(hd, sd, vs, &r, &g, &b);
- //~ should do black generation
- blend[0] = 0xff - r;
- blend[1] = 0xff - g;
- blend[2] = 0xff - b;
- blend[3] = 0;
- break;
-#endif
- }
-}
-
-// NB: This must match the GfxBlendMode enum defined in GfxState.h.
-SplashBlendFunc splashOutBlendFuncs[] = {
- NULL,
- &splashOutBlendMultiply,
- &splashOutBlendScreen,
- &splashOutBlendOverlay,
- &splashOutBlendDarken,
- &splashOutBlendLighten,
- &splashOutBlendColorDodge,
- &splashOutBlendColorBurn,
- &splashOutBlendHardLight,
- &splashOutBlendSoftLight,
- &splashOutBlendDifference,
- &splashOutBlendExclusion,
- &splashOutBlendHue,
- &splashOutBlendSaturation,
- &splashOutBlendColor,
- &splashOutBlendLuminosity
-};
-
-//------------------------------------------------------------------------
-// Font substitutions
-//------------------------------------------------------------------------
-
-struct SplashOutFontSubst {
- char *name;
- double mWidth;
-};
-
-// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
-static SplashOutFontSubst splashOutSubstFonts[16] = {
- {"Helvetica", 0.833},
- {"Helvetica-Oblique", 0.833},
- {"Helvetica-Bold", 0.889},
- {"Helvetica-BoldOblique", 0.889},
- {"Times-Roman", 0.788},
- {"Times-Italic", 0.722},
- {"Times-Bold", 0.833},
- {"Times-BoldItalic", 0.778},
- {"Courier", 0.600},
- {"Courier-Oblique", 0.600},
- {"Courier-Bold", 0.600},
- {"Courier-BoldOblique", 0.600},
- {"Symbol", 0.576},
- {"Symbol", 0.576},
- {"Symbol", 0.576},
- {"Symbol", 0.576}
-};
-
-//------------------------------------------------------------------------
-// SplashOutFontFileID
-//------------------------------------------------------------------------
-
-class SplashOutFontFileID: public SplashFontFileID {
-public:
-
- SplashOutFontFileID(Ref *rA) { r = *rA; substIdx = -1; }
-
- ~SplashOutFontFileID() {}
-
- GBool matches(SplashFontFileID *id) {
- return ((SplashOutFontFileID *)id)->r.num == r.num &&
- ((SplashOutFontFileID *)id)->r.gen == r.gen;
- }
-
- void setSubstIdx(int substIdxA) { substIdx = substIdxA; }
- int getSubstIdx() { return substIdx; }
-
-private:
-
- Ref r;
- int substIdx;
-};
-
-//------------------------------------------------------------------------
-// T3FontCache
-//------------------------------------------------------------------------
-
-struct T3FontCacheTag {
- Gushort code;
- Gushort mru; // valid bit (0x8000) and MRU index
-};
-
-class T3FontCache {
-public:
-
- T3FontCache(Ref *fontID, double m11A, double m12A,
- double m21A, double m22A,
- int glyphXA, int glyphYA, int glyphWA, int glyphHA,
- GBool aa, GBool validBBoxA);
- ~T3FontCache();
- GBool matches(Ref *idA, double m11A, double m12A,
- double m21A, double m22A)
- { return fontID.num == idA->num && fontID.gen == idA->gen &&
- m11 == m11A && m12 == m12A && m21 == m21A && m22 == m22A; }
-
- Ref fontID; // PDF font ID
- double m11, m12, m21, m22; // transform matrix
- int glyphX, glyphY; // pixel offset of glyph bitmaps
- int glyphW, glyphH; // size of glyph bitmaps, in pixels
- GBool validBBox; // false if the bbox was [0 0 0 0]
- int glyphSize; // size of glyph bitmaps, in bytes
- int cacheSets; // number of sets in cache
- int cacheAssoc; // cache associativity (glyphs per set)
- Guchar *cacheData; // glyph pixmap cache
- T3FontCacheTag *cacheTags; // cache tags, i.e., char codes
-};
-
-T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A,
- double m21A, double m22A,
- int glyphXA, int glyphYA, int glyphWA, int glyphHA,
- GBool validBBoxA, GBool aa) {
- int i;
-
- fontID = *fontIDA;
- m11 = m11A;
- m12 = m12A;
- m21 = m21A;
- m22 = m22A;
- glyphX = glyphXA;
- glyphY = glyphYA;
- glyphW = glyphWA;
- glyphH = glyphHA;
- validBBox = validBBoxA;
- if (aa) {
- glyphSize = glyphW * glyphH;
- } else {
- glyphSize = ((glyphW + 7) >> 3) * glyphH;
- }
- cacheAssoc = 8;
- if (glyphSize <= 256) {
- cacheSets = 8;
- } else if (glyphSize <= 512) {
- cacheSets = 4;
- } else if (glyphSize <= 1024) {
- cacheSets = 2;
- } else {
- cacheSets = 1;
- }
- cacheData = (Guchar *)gmallocn_checkoverflow(cacheSets * cacheAssoc, glyphSize);
- if (cacheData != NULL)
- {
- cacheTags = (T3FontCacheTag *)gmallocn(cacheSets * cacheAssoc,
- sizeof(T3FontCacheTag));
- for (i = 0; i < cacheSets * cacheAssoc; ++i) {
- cacheTags[i].mru = i & (cacheAssoc - 1);
- }
- }
- else
- {
- cacheTags = NULL;
- }
-}
-
-T3FontCache::~T3FontCache() {
- gfree(cacheData);
- gfree(cacheTags);
-}
-
-struct T3GlyphStack {
- Gushort code; // character code
-
- //----- cache info
- T3FontCache *cache; // font cache for the current font
- T3FontCacheTag *cacheTag; // pointer to cache tag for the glyph
- Guchar *cacheData; // pointer to cache data for the glyph
-
- //----- saved state
- SplashBitmap *origBitmap;
- Splash *origSplash;
- double origCTM4, origCTM5;
-
- T3GlyphStack *next; // next object on stack
-};
-
-//------------------------------------------------------------------------
-// SplashTransparencyGroup
-//------------------------------------------------------------------------
-
-struct SplashTransparencyGroup {
- int tx, ty; // translation coordinates
- SplashBitmap *tBitmap; // bitmap for transparency group
- GfxColorSpace *blendingColorSpace;
- GBool isolated;
-
- //----- saved state
- SplashBitmap *origBitmap;
- Splash *origSplash;
-
- SplashTransparencyGroup *next;
-};
-
-//------------------------------------------------------------------------
-// SplashOutputDev
-//------------------------------------------------------------------------
-
-SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA,
- int bitmapRowPadA,
- GBool reverseVideoA,
- SplashColorPtr paperColorA,
- GBool bitmapTopDownA,
- GBool allowAntialiasA) {
- colorMode = colorModeA;
- bitmapRowPad = bitmapRowPadA;
- bitmapTopDown = bitmapTopDownA;
- allowAntialias = allowAntialiasA;
- vectorAntialias = allowAntialias &&
- globalParams->getVectorAntialias() &&
- colorMode != splashModeMono1;
- setupScreenParams(72.0, 72.0);
- reverseVideo = reverseVideoA;
- splashColorCopy(paperColor, paperColorA);
-
- xref = NULL;
-
- bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode,
- colorMode != splashModeMono1, bitmapTopDown);
- splash = new Splash(bitmap, vectorAntialias, &screenParams);
- splash->clear(paperColor, 0);
-
- fontEngine = NULL;
-
- nT3Fonts = 0;
- t3GlyphStack = NULL;
-
- font = NULL;
- needFontUpdate = gFalse;
- textClipPath = NULL;
-
- transpGroupStack = NULL;
-}
-
-void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) {
- screenParams.size = globalParams->getScreenSize();
- screenParams.dotRadius = globalParams->getScreenDotRadius();
- screenParams.gamma = (SplashCoord)globalParams->getScreenGamma();
- screenParams.blackThreshold =
- (SplashCoord)globalParams->getScreenBlackThreshold();
- screenParams.whiteThreshold =
- (SplashCoord)globalParams->getScreenWhiteThreshold();
- switch (globalParams->getScreenType()) {
- case screenDispersed:
- screenParams.type = splashScreenDispersed;
- if (screenParams.size < 0) {
- screenParams.size = 4;
- }
- break;
- case screenClustered:
- screenParams.type = splashScreenClustered;
- if (screenParams.size < 0) {
- screenParams.size = 10;
- }
- break;
- case screenStochasticClustered:
- screenParams.type = splashScreenStochasticClustered;
- if (screenParams.size < 0) {
- screenParams.size = 100;
- }
- if (screenParams.dotRadius < 0) {
- screenParams.dotRadius = 2;
- }
- break;
- case screenUnset:
- default:
- // use clustered dithering for resolution >= 300 dpi
- // (compare to 299.9 to avoid floating point issues)
- if (hDPI > 299.9 && vDPI > 299.9) {
- screenParams.type = splashScreenStochasticClustered;
- if (screenParams.size < 0) {
- screenParams.size = 100;
- }
- if (screenParams.dotRadius < 0) {
- screenParams.dotRadius = 2;
- }
- } else {
- screenParams.type = splashScreenDispersed;
- if (screenParams.size < 0) {
- screenParams.size = 4;
- }
- }
- }
-}
-
-SplashOutputDev::~SplashOutputDev() {
- int i;
-
- for (i = 0; i < nT3Fonts; ++i) {
- delete t3FontCache[i];
- }
- if (fontEngine) {
- delete fontEngine;
- }
- if (splash) {
- delete splash;
- }
- if (bitmap) {
- delete bitmap;
- }
-}
-
-void SplashOutputDev::startDoc(XRef *xrefA) {
- int i;
-
- xref = xrefA;
- if (fontEngine) {
- delete fontEngine;
- }
- fontEngine = new SplashFontEngine(
-#if HAVE_T1LIB_H
- globalParams->getEnableT1lib(),
-#endif
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
- globalParams->getEnableFreeType(),
-#endif
- allowAntialias &&
- globalParams->getAntialias() &&
- colorMode != splashModeMono1);
- for (i = 0; i < nT3Fonts; ++i) {
- delete t3FontCache[i];
- }
- nT3Fonts = 0;
-}
-
-void SplashOutputDev::startPage(int /*pageNum*/, GfxState *state) {
- int w, h;
- double *ctm;
- SplashCoord mat[6];
- SplashColor color;
-
- if (state) {
- setupScreenParams(state->getHDPI(), state->getVDPI());
- w = (int)(state->getPageWidth() + 0.5);
- if (w <= 0) {
- w = 1;
- }
- h = (int)(state->getPageHeight() + 0.5);
- if (h <= 0) {
- h = 1;
- }
- } else {
- w = h = 1;
- }
- if (splash) {
- delete splash;
- }
- if (!bitmap || w != bitmap->getWidth() || h != bitmap->getHeight()) {
- if (bitmap) {
- delete bitmap;
- }
- bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode,
- colorMode != splashModeMono1, bitmapTopDown);
- }
- splash = new Splash(bitmap, vectorAntialias, &screenParams);
- if (state) {
- ctm = state->getCTM();
- mat[0] = (SplashCoord)ctm[0];
- mat[1] = (SplashCoord)ctm[1];
- mat[2] = (SplashCoord)ctm[2];
- mat[3] = (SplashCoord)ctm[3];
- mat[4] = (SplashCoord)ctm[4];
- mat[5] = (SplashCoord)ctm[5];
- splash->setMatrix(mat);
- }
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- color[0] = 0;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- color[0] = color[1] = color[2] = 0;
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- color[0] = color[1] = color[2] = color[3] = 0;
- break;
-#endif
- }
- splash->setStrokePattern(new SplashSolidColor(color));
- splash->setFillPattern(new SplashSolidColor(color));
- splash->setLineCap(splashLineCapButt);
- splash->setLineJoin(splashLineJoinMiter);
- splash->setLineDash(NULL, 0, 0);
- splash->setMiterLimit(10);
- splash->setFlatness(1);
- // the SA parameter supposedly defaults to false, but Acrobat
- // apparently hardwires it to true
- splash->setStrokeAdjust(globalParams->getStrokeAdjust());
- splash->clear(paperColor, 0);
-}
-
-void SplashOutputDev::endPage() {
- if (colorMode != splashModeMono1) {
- splash->compositeBackground(paperColor);
- }
-}
-
-void SplashOutputDev::saveState(GfxState * /*state*/) {
- splash->saveState();
-}
-
-void SplashOutputDev::restoreState(GfxState * /*state*/) {
- splash->restoreState();
- needFontUpdate = gTrue;
-}
-
-void SplashOutputDev::updateAll(GfxState *state) {
- updateLineDash(state);
- updateLineJoin(state);
- updateLineCap(state);
- updateLineWidth(state);
- updateFlatness(state);
- updateMiterLimit(state);
- updateStrokeAdjust(state);
- updateFillColor(state);
- updateStrokeColor(state);
- needFontUpdate = gTrue;
-}
-
-void SplashOutputDev::updateCTM(GfxState *state, double /*m11*/, double /*m12*/,
- double /*m21*/, double /*m22*/,
- double /*m31*/, double /*m32*/) {
- double *ctm;
- SplashCoord mat[6];
-
- ctm = state->getCTM();
- mat[0] = (SplashCoord)ctm[0];
- mat[1] = (SplashCoord)ctm[1];
- mat[2] = (SplashCoord)ctm[2];
- mat[3] = (SplashCoord)ctm[3];
- mat[4] = (SplashCoord)ctm[4];
- mat[5] = (SplashCoord)ctm[5];
- splash->setMatrix(mat);
-}
-
-void SplashOutputDev::updateLineDash(GfxState *state) {
- double *dashPattern;
- int dashLength;
- double dashStart;
- SplashCoord dash[20];
- int i;
-
- state->getLineDash(&dashPattern, &dashLength, &dashStart);
- if (dashLength > 20) {
- dashLength = 20;
- }
- for (i = 0; i < dashLength; ++i) {
- dash[i] = (SplashCoord)dashPattern[i];
- if (dash[i] < 0) {
- dash[i] = 0;
- }
- }
- splash->setLineDash(dash, dashLength, (SplashCoord)dashStart);
-}
-
-void SplashOutputDev::updateFlatness(GfxState *state) {
- splash->setFlatness(state->getFlatness());
-}
-
-void SplashOutputDev::updateLineJoin(GfxState *state) {
- splash->setLineJoin(state->getLineJoin());
-}
-
-void SplashOutputDev::updateLineCap(GfxState *state) {
- splash->setLineCap(state->getLineCap());
-}
-
-void SplashOutputDev::updateMiterLimit(GfxState *state) {
- splash->setMiterLimit(state->getMiterLimit());
-}
-
-void SplashOutputDev::updateLineWidth(GfxState *state) {
- splash->setLineWidth(state->getLineWidth());
-}
-
-void SplashOutputDev::updateStrokeAdjust(GfxState * /*state*/) {
-#if 0 // the SA parameter supposedly defaults to false, but Acrobat
- // apparently hardwires it to true
- splash->setStrokeAdjust(state->getStrokeAdjust());
-#endif
-}
-
-void SplashOutputDev::updateFillColor(GfxState *state) {
- GfxGray gray;
- GfxRGB rgb;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
-
- state->getFillGray(&gray);
- state->getFillRGB(&rgb);
-#if SPLASH_CMYK
- state->getFillCMYK(&cmyk);
- splash->setFillPattern(getColor(gray, &rgb, &cmyk));
-#else
- splash->setFillPattern(getColor(gray, &rgb));
-#endif
-}
-
-void SplashOutputDev::updateStrokeColor(GfxState *state) {
- GfxGray gray;
- GfxRGB rgb;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
-
- state->getStrokeGray(&gray);
- state->getStrokeRGB(&rgb);
-#if SPLASH_CMYK
- state->getStrokeCMYK(&cmyk);
- splash->setStrokePattern(getColor(gray, &rgb, &cmyk));
-#else
- splash->setStrokePattern(getColor(gray, &rgb));
-#endif
-}
-
-#if SPLASH_CMYK
-SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb,
- GfxCMYK *cmyk) {
-#else
-SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb) {
-#endif
- SplashPattern *pattern;
- SplashColor color;
- GfxColorComp r, g, b;
-
- if (reverseVideo) {
- gray = gfxColorComp1 - gray;
- r = gfxColorComp1 - rgb->r;
- g = gfxColorComp1 - rgb->g;
- b = gfxColorComp1 - rgb->b;
- } else {
- r = rgb->r;
- g = rgb->g;
- b = rgb->b;
- }
-
- pattern = NULL; // make gcc happy
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- color[0] = colToByte(gray);
- pattern = new SplashSolidColor(color);
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- color[0] = colToByte(r);
- color[1] = colToByte(g);
- color[2] = colToByte(b);
- pattern = new SplashSolidColor(color);
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- color[0] = colToByte(cmyk->c);
- color[1] = colToByte(cmyk->m);
- color[2] = colToByte(cmyk->y);
- color[3] = colToByte(cmyk->k);
- pattern = new SplashSolidColor(color);
- break;
-#endif
- }
-
- return pattern;
-}
-
-void SplashOutputDev::updateBlendMode(GfxState *state) {
- splash->setBlendFunc(splashOutBlendFuncs[state->getBlendMode()]);
-}
-
-void SplashOutputDev::updateFillOpacity(GfxState *state) {
- splash->setFillAlpha((SplashCoord)state->getFillOpacity());
-}
-
-void SplashOutputDev::updateStrokeOpacity(GfxState *state) {
- splash->setStrokeAlpha((SplashCoord)state->getStrokeOpacity());
-}
-
-void SplashOutputDev::updateFont(GfxState * /*state*/) {
- needFontUpdate = gTrue;
-}
-
-void SplashOutputDev::doUpdateFont(GfxState *state) {
- GfxFont *gfxFont;
- GfxFontType fontType;
- SplashOutFontFileID *id;
- SplashFontFile *fontFile;
- SplashFontSrc *fontsrc = NULL;
- FoFiTrueType *ff;
- Ref embRef;
- Object refObj, strObj;
- GString *fileName, *substName;
- char *tmpBuf;
- int tmpBufLen;
- Gushort *codeToGID;
- DisplayFontParam *dfp;
- CharCodeToUnicode *ctu;
- double *textMat;
- double m11, m12, m21, m22, w1, w2, fontSize;
- SplashCoord mat[4];
- char *name;
- Unicode uBuf[8];
- int substIdx, n, code, cmap;
- int faceIndex = 0;
-
- needFontUpdate = gFalse;
- font = NULL;
- fileName = NULL;
- tmpBuf = NULL;
- substIdx = -1;
- dfp = NULL;
-
- if (!(gfxFont = state->getFont())) {
- goto err1;
- }
- fontType = gfxFont->getType();
- if (fontType == fontType3) {
- goto err1;
- }
-
- // check the font file cache
- id = new SplashOutFontFileID(gfxFont->getID());
- if ((fontFile = fontEngine->getFontFile(id))) {
- delete id;
-
- } else {
-
- // if there is an embedded font, write it to disk
- if (gfxFont->getEmbeddedFontID(&embRef)) {
- tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen);
- if (! tmpBuf)
- goto err2;
-
- // if there is an external font file, use it
- } else if (!(fileName = gfxFont->getExtFontFile())) {
-
- // look for a display font mapping or a substitute font
- if (gfxFont->isCIDFont()) {
- if (((GfxCIDFont *)gfxFont)->getCollection()) {
- dfp = globalParams->
- getDisplayCIDFont(gfxFont->getName(),
- ((GfxCIDFont *)gfxFont)->getCollection());
- }
- } else {
- if (gfxFont->getName()) {
- dfp = globalParams->getDisplayFont(gfxFont->getName());
- }
- if (!dfp) {
- // 8-bit font substitution
- if (gfxFont->isFixedWidth()) {
- substIdx = 8;
- } else if (gfxFont->isSerif()) {
- substIdx = 4;
- } else {
- substIdx = 0;
- }
- if (gfxFont->isBold()) {
- substIdx += 2;
- }
- if (gfxFont->isItalic()) {
- substIdx += 1;
- }
- substName = new GString(splashOutSubstFonts[substIdx].name);
- dfp = globalParams->getDisplayFont(substName);
- delete substName;
- id->setSubstIdx(substIdx);
- }
- }
- if (!dfp) {
- error(-1, "Couldn't find a font for '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- goto err2;
- }
- switch (dfp->kind) {
- case displayFontT1:
- fileName = dfp->t1.fileName;
- fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1;
- break;
- case displayFontTT:
- fileName = dfp->tt.fileName;
- fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType;
- faceIndex = dfp->tt.faceIndex;
- break;
- }
- }
-
- fontsrc = new SplashFontSrc;
- if (fileName)
- fontsrc->setFile(fileName, gFalse);
- else
- fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue);
-
- // load the font file
- switch (fontType) {
- case fontType1:
- if (!(fontFile = fontEngine->loadType1Font(
- id,
- fontsrc,
- ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
- error(-1, "Couldn't create a font for '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- goto err2;
- }
- break;
- case fontType1C:
- if (!(fontFile = fontEngine->loadType1CFont(
- id,
- fontsrc,
- ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
- error(-1, "Couldn't create a font for '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- goto err2;
- }
- break;
- case fontType1COT:
- if (!(fontFile = fontEngine->loadOpenTypeT1CFont(
- id,
- fontsrc,
- ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
- error(-1, "Couldn't create a font for '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- goto err2;
- }
- break;
- case fontTrueType:
- case fontTrueTypeOT:
- if (fileName)
- ff = FoFiTrueType::load(fileName->getCString());
- else
- ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
- if (ff) {
- codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
- n = 256;
- delete ff;
- } else {
- codeToGID = NULL;
- n = 0;
- }
- if (!(fontFile = fontEngine->loadTrueTypeFont(
- id,
- fontsrc,
- codeToGID, n))) {
- error(-1, "Couldn't create a font for '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- goto err2;
- }
- break;
- case fontCIDType0:
- case fontCIDType0C:
- if (!(fontFile = fontEngine->loadCIDFont(
- id,
- fontsrc))) {
- error(-1, "Couldn't create a font for '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- goto err2;
- }
- break;
- case fontCIDType0COT:
- if (!(fontFile = fontEngine->loadOpenTypeCFFFont(
- id,
- fontsrc))) {
- error(-1, "Couldn't create a font for '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- goto err2;
- }
- break;
- case fontCIDType2:
- case fontCIDType2OT:
- codeToGID = NULL;
- n = 0;
- if (dfp) {
- // create a CID-to-GID mapping, via Unicode
- if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) {
- if (fileName)
- ff = FoFiTrueType::load(fileName->getCString());
- else
- ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
- if (ff) {
- // look for a Unicode cmap
- for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) {
- if ((ff->getCmapPlatform(cmap) == 3 &&
- ff->getCmapEncoding(cmap) == 1) ||
- ff->getCmapPlatform(cmap) == 0) {
- break;
- }
- }
- if (cmap < ff->getNumCmaps()) {
- // map CID -> Unicode -> GID
- n = ctu->getLength();
- codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
- for (code = 0; code < n; ++code) {
- if (ctu->mapToUnicode(code, uBuf, 8) > 0) {
- codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]);
- } else {
- codeToGID[code] = 0;
- }
- }
- }
- delete ff;
- }
- ctu->decRefCnt();
- } else {
- error(-1, "Couldn't find a mapping to Unicode for font '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- }
- } else {
- if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
- n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
- codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
- memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
- n * sizeof(Gushort));
- }
- }
- if (!(fontFile = fontEngine->loadTrueTypeFont(
- id,
- fontsrc,
- codeToGID, n, faceIndex))) {
- error(-1, "Couldn't create a font for '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- goto err2;
- }
- break;
- default:
- // this shouldn't happen
- goto err2;
- }
- }
-
- // get the font matrix
- textMat = state->getTextMat();
- fontSize = state->getFontSize();
- m11 = textMat[0] * fontSize * state->getHorizScaling();
- m12 = textMat[1] * fontSize * state->getHorizScaling();
- m21 = textMat[2] * fontSize;
- m22 = textMat[3] * fontSize;
-
- // for substituted fonts: adjust the font matrix -- compare the
- // width of 'm' in the original font and the substituted font
- substIdx = ((SplashOutFontFileID *)fontFile->getID())->getSubstIdx();
- if (substIdx >= 0) {
- for (code = 0; code < 256; ++code) {
- if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
- name[0] == 'm' && name[1] == '\0') {
- break;
- }
- }
- if (code < 256) {
- w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
- w2 = splashOutSubstFonts[substIdx].mWidth;
- if (!gfxFont->isSymbolic()) {
- // if real font is substantially narrower than substituted
- // font, reduce the font size accordingly
- if (w1 > 0.01 && w1 < 0.9 * w2) {
- w1 /= w2;
- m11 *= w1;
- m21 *= w1;
- }
- }
- }
- }
-
- // create the scaled font
- mat[0] = m11; mat[1] = m12;
- mat[2] = m21; mat[3] = m22;
- font = fontEngine->getFont(fontFile, mat, splash->getMatrix());
-
- if (fontsrc && !fontsrc->isFile)
- fontsrc->unref();
-
- return;
-
- err2:
- delete id;
- err1:
- if (fontsrc && !fontsrc->isFile)
- fontsrc->unref();
- return;
-}
-
-void SplashOutputDev::stroke(GfxState *state) {
- SplashPath *path;
-
- if (state->getStrokeColorSpace()->isNonMarking()) {
- return;
- }
- path = convertPath(state, state->getPath());
- splash->stroke(path);
- delete path;
-}
-
-void SplashOutputDev::fill(GfxState *state) {
- SplashPath *path;
-
- if (state->getFillColorSpace()->isNonMarking()) {
- return;
- }
- path = convertPath(state, state->getPath());
- splash->fill(path, gFalse);
- delete path;
-}
-
-void SplashOutputDev::eoFill(GfxState *state) {
- SplashPath *path;
-
- if (state->getFillColorSpace()->isNonMarking()) {
- return;
- }
- path = convertPath(state, state->getPath());
- splash->fill(path, gTrue);
- delete path;
-}
-
-void SplashOutputDev::clip(GfxState *state) {
- SplashPath *path;
-
- path = convertPath(state, state->getPath());
- splash->clipToPath(path, gFalse);
- delete path;
-}
-
-void SplashOutputDev::eoClip(GfxState *state) {
- SplashPath *path;
-
- path = convertPath(state, state->getPath());
- splash->clipToPath(path, gTrue);
- delete path;
-}
-
-void SplashOutputDev::clipToStrokePath(GfxState *state) {
- SplashPath *path, *path2;
-
- path = convertPath(state, state->getPath());
- path2 = splash->makeStrokePath(path);
- delete path;
- splash->clipToPath(path2, gFalse);
- delete path2;
-}
-
-SplashPath *SplashOutputDev::convertPath(GfxState * /*state*/, GfxPath *path) {
- SplashPath *sPath;
- GfxSubpath *subpath;
- int i, j;
-
- sPath = new SplashPath();
- for (i = 0; i < path->getNumSubpaths(); ++i) {
- subpath = path->getSubpath(i);
- if (subpath->getNumPoints() > 0) {
- sPath->moveTo((SplashCoord)subpath->getX(0),
- (SplashCoord)subpath->getY(0));
- j = 1;
- while (j < subpath->getNumPoints()) {
- if (subpath->getCurve(j)) {
- sPath->curveTo((SplashCoord)subpath->getX(j),
- (SplashCoord)subpath->getY(j),
- (SplashCoord)subpath->getX(j+1),
- (SplashCoord)subpath->getY(j+1),
- (SplashCoord)subpath->getX(j+2),
- (SplashCoord)subpath->getY(j+2));
- j += 3;
- } else {
- sPath->lineTo((SplashCoord)subpath->getX(j),
- (SplashCoord)subpath->getY(j));
- ++j;
- }
- }
- if (subpath->isClosed()) {
- sPath->close();
- }
- }
- }
- return sPath;
-}
-
-void SplashOutputDev::drawChar(GfxState *state, double x, double y,
- double /*dx*/, double /*dy*/,
- double originX, double originY,
- CharCode code, int /*nBytes*/,
- Unicode * /*u*/, int /*uLen*/) {
- SplashPath *path;
- int render;
-
- // check for invisible text -- this is used by Acrobat Capture
- render = state->getRender();
- if (render == 3) {
- return;
- }
-
- if (needFontUpdate) {
- doUpdateFont(state);
- }
- if (!font) {
- return;
- }
-
- x -= originX;
- y -= originY;
-
- // fill
- if (!(render & 1)) {
- if (!state->getFillColorSpace()->isNonMarking()) {
- splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font);
- }
- }
-
- // stroke
- if ((render & 3) == 1 || (render & 3) == 2) {
- if (!state->getStrokeColorSpace()->isNonMarking()) {
- if ((path = font->getGlyphPath(code))) {
- path->offset((SplashCoord)x, (SplashCoord)y);
- splash->stroke(path);
- delete path;
- }
- }
- }
-
- // clip
- if (render & 4) {
- if ((path = font->getGlyphPath(code))) {
- path->offset((SplashCoord)x, (SplashCoord)y);
- if (textClipPath) {
- textClipPath->append(path);
- delete path;
- } else {
- textClipPath = path;
- }
- }
- }
-}
-
-GBool SplashOutputDev::beginType3Char(GfxState *state, double /*x*/, double /*y*/,
- double /*dx*/, double /*dy*/,
- CharCode code, Unicode * /*u*/, int /*uLen*/) {
- GfxFont *gfxFont;
- Ref *fontID;
- double *ctm, *bbox;
- T3FontCache *t3Font;
- T3GlyphStack *t3gs;
- GBool validBBox;
- double x1, y1, xMin, yMin, xMax, yMax, xt, yt;
- int i, j;
-
- if (!(gfxFont = state->getFont())) {
- return gFalse;
- }
- fontID = gfxFont->getID();
- ctm = state->getCTM();
- state->transform(0, 0, &xt, &yt);
-
- // is it the first (MRU) font in the cache?
- if (!(nT3Fonts > 0 &&
- t3FontCache[0]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3]))) {
-
- // is the font elsewhere in the cache?
- for (i = 1; i < nT3Fonts; ++i) {
- if (t3FontCache[i]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3])) {
- t3Font = t3FontCache[i];
- for (j = i; j > 0; --j) {
- t3FontCache[j] = t3FontCache[j - 1];
- }
- t3FontCache[0] = t3Font;
- break;
- }
- }
- if (i >= nT3Fonts) {
-
- // create new entry in the font cache
- if (nT3Fonts == splashOutT3FontCacheSize) {
- delete t3FontCache[nT3Fonts - 1];
- --nT3Fonts;
- }
- for (j = nT3Fonts; j > 0; --j) {
- t3FontCache[j] = t3FontCache[j - 1];
- }
- ++nT3Fonts;
- bbox = gfxFont->getFontBBox();
- if (bbox[0] == 0 && bbox[1] == 0 && bbox[2] == 0 && bbox[3] == 0) {
- // unspecified bounding box -- just take a guess
- xMin = xt - 5;
- xMax = xMin + 30;
- yMax = yt + 15;
- yMin = yMax - 45;
- validBBox = gFalse;
- } else {
- state->transform(bbox[0], bbox[1], &x1, &y1);
- xMin = xMax = x1;
- yMin = yMax = y1;
- state->transform(bbox[0], bbox[3], &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- state->transform(bbox[2], bbox[1], &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- state->transform(bbox[2], bbox[3], &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- validBBox = gTrue;
- }
- t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[3],
- (int)floor(xMin - xt),
- (int)floor(yMin - yt),
- (int)ceil(xMax) - (int)floor(xMin) + 3,
- (int)ceil(yMax) - (int)floor(yMin) + 3,
- validBBox,
- colorMode != splashModeMono1);
- }
- }
- t3Font = t3FontCache[0];
-
- // is the glyph in the cache?
- i = (code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc;
- for (j = 0; j < t3Font->cacheAssoc; ++j) {
- if (t3Font->cacheTags != NULL) {
- if ((t3Font->cacheTags[i+j].mru & 0x8000) &&
- t3Font->cacheTags[i+j].code == code) {
- drawType3Glyph(t3Font, &t3Font->cacheTags[i+j],
- t3Font->cacheData + (i+j) * t3Font->glyphSize);
- return gTrue;
- }
- }
- }
-
- // push a new Type 3 glyph record
- t3gs = new T3GlyphStack();
- t3gs->next = t3GlyphStack;
- t3GlyphStack = t3gs;
- t3GlyphStack->code = code;
- t3GlyphStack->cache = t3Font;
- t3GlyphStack->cacheTag = NULL;
- t3GlyphStack->cacheData = NULL;
-
- return gFalse;
-}
-
-void SplashOutputDev::endType3Char(GfxState *state) {
- T3GlyphStack *t3gs;
- double *ctm;
-
- if (t3GlyphStack->cacheTag) {
- memcpy(t3GlyphStack->cacheData, bitmap->getDataPtr(),
- t3GlyphStack->cache->glyphSize);
- delete bitmap;
- delete splash;
- bitmap = t3GlyphStack->origBitmap;
- splash = t3GlyphStack->origSplash;
- ctm = state->getCTM();
- state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
- t3GlyphStack->origCTM4, t3GlyphStack->origCTM5);
- updateCTM(state, 0, 0, 0, 0, 0, 0);
- drawType3Glyph(t3GlyphStack->cache,
- t3GlyphStack->cacheTag, t3GlyphStack->cacheData);
- }
- t3gs = t3GlyphStack;
- t3GlyphStack = t3gs->next;
- delete t3gs;
-}
-
-void SplashOutputDev::type3D0(GfxState * /*state*/, double /*wx*/, double /*wy*/) {
-}
-
-void SplashOutputDev::type3D1(GfxState *state, double /*wx*/, double /*wy*/,
- double llx, double lly, double urx, double ury) {
- double *ctm;
- T3FontCache *t3Font;
- SplashColor color;
- double xt, yt, xMin, xMax, yMin, yMax, x1, y1;
- int i, j;
-
- t3Font = t3GlyphStack->cache;
-
- // check for a valid bbox
- state->transform(0, 0, &xt, &yt);
- state->transform(llx, lly, &x1, &y1);
- xMin = xMax = x1;
- yMin = yMax = y1;
- state->transform(llx, ury, &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- state->transform(urx, lly, &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- state->transform(urx, ury, &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- if (xMin - xt < t3Font->glyphX ||
- yMin - yt < t3Font->glyphY ||
- xMax - xt > t3Font->glyphX + t3Font->glyphW ||
- yMax - yt > t3Font->glyphY + t3Font->glyphH) {
- if (t3Font->validBBox) {
- error(-1, "Bad bounding box in Type 3 glyph");
- }
- return;
- }
-
- // allocate a cache entry
- i = (t3GlyphStack->code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc;
- for (j = 0; j < t3Font->cacheAssoc; ++j) {
- if ((t3Font->cacheTags[i+j].mru & 0x7fff) == t3Font->cacheAssoc - 1) {
- t3Font->cacheTags[i+j].mru = 0x8000;
- t3Font->cacheTags[i+j].code = t3GlyphStack->code;
- t3GlyphStack->cacheTag = &t3Font->cacheTags[i+j];
- t3GlyphStack->cacheData = t3Font->cacheData + (i+j) * t3Font->glyphSize;
- } else {
- ++t3Font->cacheTags[i+j].mru;
- }
- }
-
- // save state
- t3GlyphStack->origBitmap = bitmap;
- t3GlyphStack->origSplash = splash;
- ctm = state->getCTM();
- t3GlyphStack->origCTM4 = ctm[4];
- t3GlyphStack->origCTM5 = ctm[5];
-
- // create the temporary bitmap
- if (colorMode == splashModeMono1) {
- bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1,
- splashModeMono1, gFalse);
- splash = new Splash(bitmap, gFalse,
- t3GlyphStack->origSplash->getScreen());
- color[0] = 0;
- splash->clear(color);
- color[0] = 1;
- } else {
- bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1,
- splashModeMono8, gFalse);
- splash = new Splash(bitmap, vectorAntialias,
- t3GlyphStack->origSplash->getScreen());
- color[0] = 0x00;
- splash->clear(color);
- color[0] = 0xff;
- }
- splash->setFillPattern(new SplashSolidColor(color));
- splash->setStrokePattern(new SplashSolidColor(color));
- //~ this should copy other state from t3GlyphStack->origSplash?
- state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
- -t3Font->glyphX, -t3Font->glyphY);
- updateCTM(state, 0, 0, 0, 0, 0, 0);
-}
-
-void SplashOutputDev::drawType3Glyph(T3FontCache *t3Font,
- T3FontCacheTag * /*tag*/, Guchar *data) {
- SplashGlyphBitmap glyph;
-
- glyph.x = -t3Font->glyphX;
- glyph.y = -t3Font->glyphY;
- glyph.w = t3Font->glyphW;
- glyph.h = t3Font->glyphH;
- glyph.aa = colorMode != splashModeMono1;
- glyph.data = data;
- glyph.freeData = gFalse;
- splash->fillGlyph(0, 0, &glyph);
-}
-
-void SplashOutputDev::endTextObject(GfxState * /*state*/) {
- if (textClipPath) {
- splash->clipToPath(textClipPath, gFalse);
- delete textClipPath;
- textClipPath = NULL;
- }
-}
-
-struct SplashOutImageMaskData {
- ImageStream *imgStr;
- GBool invert;
- int width, height, y;
-};
-
-GBool SplashOutputDev::imageMaskSrc(void *data, SplashColorPtr line) {
- SplashOutImageMaskData *imgMaskData = (SplashOutImageMaskData *)data;
- Guchar *p;
- SplashColorPtr q;
- int x;
-
- if (imgMaskData->y == imgMaskData->height) {
- return gFalse;
- }
- for (x = 0, p = imgMaskData->imgStr->getLine(), q = line;
- x < imgMaskData->width;
- ++x) {
- *q++ = *p++ ^ imgMaskData->invert;
- }
- ++imgMaskData->y;
- return gTrue;
-}
-
-void SplashOutputDev::drawImageMask(GfxState *state, Object * /*ref*/, Stream *str,
- int width, int height, GBool invert,
- GBool inlineImg) {
- double *ctm;
- SplashCoord mat[6];
- SplashOutImageMaskData imgMaskData;
-
- if (state->getFillColorSpace()->isNonMarking()) {
- return;
- }
-
- ctm = state->getCTM();
- mat[0] = ctm[0];
- mat[1] = ctm[1];
- mat[2] = -ctm[2];
- mat[3] = -ctm[3];
- mat[4] = ctm[2] + ctm[4];
- mat[5] = ctm[3] + ctm[5];
-
- imgMaskData.imgStr = new ImageStream(str, width, 1, 1);
- imgMaskData.imgStr->reset();
- imgMaskData.invert = invert ? 0 : 1;
- imgMaskData.width = width;
- imgMaskData.height = height;
- imgMaskData.y = 0;
-
- splash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat,
- t3GlyphStack != NULL);
- if (inlineImg) {
- while (imgMaskData.y < height) {
- imgMaskData.imgStr->getLine();
- ++imgMaskData.y;
- }
- }
-
- delete imgMaskData.imgStr;
- str->close();
-}
-
-struct SplashOutImageData {
- ImageStream *imgStr;
- GfxImageColorMap *colorMap;
- SplashColorPtr lookup;
- int *maskColors;
- SplashColorMode colorMode;
- int width, height, y;
-};
-
-GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
- Guchar * /*alphaLine*/) {
- SplashOutImageData *imgData = (SplashOutImageData *)data;
- Guchar *p;
- SplashColorPtr q, col;
- GfxRGB rgb;
- GfxGray gray;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
- int nComps, x;
-
- if (imgData->y == imgData->height) {
- return gFalse;
- }
-
- nComps = imgData->colorMap->getNumPixelComps();
-
- if (imgData->lookup) {
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, ++p) {
- *q++ = imgData->lookup[*p];
- }
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, ++p) {
- col = &imgData->lookup[3 * *p];
- *q++ = col[0];
- *q++ = col[1];
- *q++ = col[2];
- }
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, ++p) {
- col = &imgData->lookup[4 * *p];
- *q++ = col[0];
- *q++ = col[1];
- *q++ = col[2];
- *q++ = col[3];
- }
- break;
-#endif
- }
- } else {
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, p += nComps) {
- imgData->colorMap->getGray(p, &gray);
- *q++ = colToByte(gray);
- }
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, p += nComps) {
- imgData->colorMap->getRGB(p, &rgb);
- *q++ = colToByte(rgb.r);
- *q++ = colToByte(rgb.g);
- *q++ = colToByte(rgb.b);
- }
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, p += nComps) {
- imgData->colorMap->getCMYK(p, &cmyk);
- *q++ = colToByte(cmyk.c);
- *q++ = colToByte(cmyk.m);
- *q++ = colToByte(cmyk.y);
- *q++ = colToByte(cmyk.k);
- }
- break;
-#endif
- }
- }
-
- ++imgData->y;
- return gTrue;
-}
-
-GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
- Guchar *alphaLine) {
- SplashOutImageData *imgData = (SplashOutImageData *)data;
- Guchar *p, *aq;
- SplashColorPtr q, col;
- GfxRGB rgb;
- GfxGray gray;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
- Guchar alpha;
- int nComps, x, i;
-
- if (imgData->y == imgData->height) {
- return gFalse;
- }
-
- nComps = imgData->colorMap->getNumPixelComps();
-
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine;
- x < imgData->width;
- ++x, p += nComps) {
- alpha = 0;
- for (i = 0; i < nComps; ++i) {
- if (p[i] < imgData->maskColors[2*i] ||
- p[i] > imgData->maskColors[2*i+1]) {
- alpha = 0xff;
- break;
- }
- }
- if (imgData->lookup) {
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- *q++ = imgData->lookup[*p];
- *aq++ = alpha;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- col = &imgData->lookup[3 * *p];
- *q++ = col[0];
- *q++ = col[1];
- *q++ = col[2];
- *aq++ = alpha;
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- col = &imgData->lookup[4 * *p];
- *q++ = col[0];
- *q++ = col[1];
- *q++ = col[2];
- *q++ = col[3];
- *aq++ = alpha;
- break;
-#endif
- }
- } else {
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- imgData->colorMap->getGray(p, &gray);
- *q++ = colToByte(gray);
- *aq++ = alpha;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- imgData->colorMap->getRGB(p, &rgb);
- *q++ = colToByte(rgb.r);
- *q++ = colToByte(rgb.g);
- *q++ = colToByte(rgb.b);
- *aq++ = alpha;
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- imgData->colorMap->getCMYK(p, &cmyk);
- *q++ = colToByte(cmyk.c);
- *q++ = colToByte(cmyk.m);
- *q++ = colToByte(cmyk.y);
- *q++ = colToByte(cmyk.k);
- *aq++ = alpha;
- break;
-#endif
- }
- }
- }
-
- ++imgData->y;
- return gTrue;
-}
-
-void SplashOutputDev::drawImage(GfxState *state, Object * /*ref*/, Stream *str,
- int width, int height,
- GfxImageColorMap *colorMap,
- int *maskColors, GBool inlineImg) {
- double *ctm;
- SplashCoord mat[6];
- SplashOutImageData imgData;
- SplashColorMode srcMode;
- SplashImageSource src;
- GfxGray gray;
- GfxRGB rgb;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
- Guchar pix;
- int n, i;
-
- ctm = state->getCTM();
- mat[0] = ctm[0];
- mat[1] = ctm[1];
- mat[2] = -ctm[2];
- mat[3] = -ctm[3];
- mat[4] = ctm[2] + ctm[4];
- mat[5] = ctm[3] + ctm[5];
-
- imgData.imgStr = new ImageStream(str, width,
- colorMap->getNumPixelComps(),
- colorMap->getBits());
- imgData.imgStr->reset();
- imgData.colorMap = colorMap;
- imgData.maskColors = maskColors;
- imgData.colorMode = colorMode;
- imgData.width = width;
- imgData.height = height;
- imgData.y = 0;
-
- // special case for one-channel (monochrome/gray/separation) images:
- // build a lookup table here
- imgData.lookup = NULL;
- if (colorMap->getNumPixelComps() == 1) {
- n = 1 << colorMap->getBits();
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- imgData.lookup = (SplashColorPtr)gmalloc(n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getGray(&pix, &gray);
- imgData.lookup[i] = colToByte(gray);
- }
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getRGB(&pix, &rgb);
- imgData.lookup[3*i] = colToByte(rgb.r);
- imgData.lookup[3*i+1] = colToByte(rgb.g);
- imgData.lookup[3*i+2] = colToByte(rgb.b);
- }
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getCMYK(&pix, &cmyk);
- imgData.lookup[4*i] = colToByte(cmyk.c);
- imgData.lookup[4*i+1] = colToByte(cmyk.m);
- imgData.lookup[4*i+2] = colToByte(cmyk.y);
- imgData.lookup[4*i+3] = colToByte(cmyk.k);
- }
- break;
-#endif
- break;
- }
- }
-
- if (colorMode == splashModeMono1) {
- srcMode = splashModeMono8;
- } else {
- srcMode = colorMode;
- }
- src = maskColors ? &alphaImageSrc : &imageSrc;
- splash->drawImage(src, &imgData, srcMode, maskColors ? gTrue : gFalse,
- width, height, mat);
- if (inlineImg) {
- while (imgData.y < height) {
- imgData.imgStr->getLine();
- ++imgData.y;
- }
- }
-
- gfree(imgData.lookup);
- delete imgData.imgStr;
- str->close();
-}
-
-struct SplashOutMaskedImageData {
- ImageStream *imgStr;
- GfxImageColorMap *colorMap;
- SplashBitmap *mask;
- SplashColorPtr lookup;
- SplashColorMode colorMode;
- int width, height, y;
-};
-
-GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
- Guchar *alphaLine) {
- SplashOutMaskedImageData *imgData = (SplashOutMaskedImageData *)data;
- Guchar *p, *aq;
- SplashColor maskColor;
- SplashColorPtr q, col;
- GfxRGB rgb;
- GfxGray gray;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
- Guchar alpha;
- int nComps, x;
-
- if (imgData->y == imgData->height) {
- return gFalse;
- }
-
- nComps = imgData->colorMap->getNumPixelComps();
-
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine;
- x < imgData->width;
- ++x, p += nComps) {
- imgData->mask->getPixel(x, imgData->y, maskColor);
- alpha = maskColor[0] ? 0xff : 0x00;
- if (imgData->lookup) {
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- *q++ = imgData->lookup[*p];
- *aq++ = alpha;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- col = &imgData->lookup[3 * *p];
- *q++ = col[0];
- *q++ = col[1];
- *q++ = col[2];
- *aq++ = alpha;
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- col = &imgData->lookup[4 * *p];
- *q++ = col[0];
- *q++ = col[1];
- *q++ = col[2];
- *q++ = col[3];
- *aq++ = alpha;
- break;
-#endif
- }
- } else {
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- imgData->colorMap->getGray(p, &gray);
- *q++ = colToByte(gray);
- *aq++ = alpha;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- imgData->colorMap->getRGB(p, &rgb);
- *q++ = colToByte(rgb.r);
- *q++ = colToByte(rgb.g);
- *q++ = colToByte(rgb.b);
- *aq++ = alpha;
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- imgData->colorMap->getCMYK(p, &cmyk);
- *q++ = colToByte(cmyk.c);
- *q++ = colToByte(cmyk.m);
- *q++ = colToByte(cmyk.y);
- *q++ = colToByte(cmyk.k);
- *aq++ = alpha;
- break;
-#endif
- }
- }
- }
-
- ++imgData->y;
- return gTrue;
-}
-
-void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
- Stream *str, int width, int height,
- GfxImageColorMap *colorMap,
- Stream *maskStr, int maskWidth,
- int maskHeight, GBool maskInvert) {
- GfxImageColorMap *maskColorMap;
- Object maskDecode, decodeLow, decodeHigh;
- double *ctm;
- SplashCoord mat[6];
- SplashOutMaskedImageData imgData;
- SplashOutImageMaskData imgMaskData;
- SplashColorMode srcMode;
- SplashBitmap *maskBitmap;
- Splash *maskSplash;
- SplashColor maskColor;
- GfxGray gray;
- GfxRGB rgb;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
- Guchar pix;
- int n, i;
-
- // If the mask is higher resolution than the image, use
- // drawSoftMaskedImage() instead.
- if (maskWidth > width || maskHeight > height) {
- decodeLow.initInt(maskInvert ? 0 : 1);
- decodeHigh.initInt(maskInvert ? 1 : 0);
- maskDecode.initArray(xref);
- maskDecode.arrayAdd(&decodeLow);
- maskDecode.arrayAdd(&decodeHigh);
- maskColorMap = new GfxImageColorMap(1, &maskDecode,
- new GfxDeviceGrayColorSpace());
- maskDecode.free();
- drawSoftMaskedImage(state, ref, str, width, height, colorMap,
- maskStr, maskWidth, maskHeight, maskColorMap);
- delete maskColorMap;
-
- } else {
-
- //----- scale the mask image to the same size as the source image
-
- mat[0] = (SplashCoord)width;
- mat[1] = 0;
- mat[2] = 0;
- mat[3] = (SplashCoord)height;
- mat[4] = 0;
- mat[5] = 0;
- imgMaskData.imgStr = new ImageStream(maskStr, maskWidth, 1, 1);
- imgMaskData.imgStr->reset();
- imgMaskData.invert = maskInvert ? 0 : 1;
- imgMaskData.width = maskWidth;
- imgMaskData.height = maskHeight;
- imgMaskData.y = 0;
- maskBitmap = new SplashBitmap(width, height, 1, splashModeMono1, gFalse);
- maskSplash = new Splash(maskBitmap, gFalse);
- maskColor[0] = 0;
- maskSplash->clear(maskColor);
- maskColor[0] = 0xff;
- maskSplash->setFillPattern(new SplashSolidColor(maskColor));
- maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData,
- maskWidth, maskHeight, mat, gFalse);
- delete imgMaskData.imgStr;
- maskStr->close();
- delete maskSplash;
-
- //----- draw the source image
-
- ctm = state->getCTM();
- mat[0] = ctm[0];
- mat[1] = ctm[1];
- mat[2] = -ctm[2];
- mat[3] = -ctm[3];
- mat[4] = ctm[2] + ctm[4];
- mat[5] = ctm[3] + ctm[5];
-
- imgData.imgStr = new ImageStream(str, width,
- colorMap->getNumPixelComps(),
- colorMap->getBits());
- imgData.imgStr->reset();
- imgData.colorMap = colorMap;
- imgData.mask = maskBitmap;
- imgData.colorMode = colorMode;
- imgData.width = width;
- imgData.height = height;
- imgData.y = 0;
-
- // special case for one-channel (monochrome/gray/separation) images:
- // build a lookup table here
- imgData.lookup = NULL;
- if (colorMap->getNumPixelComps() == 1) {
- n = 1 << colorMap->getBits();
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- imgData.lookup = (SplashColorPtr)gmalloc(n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getGray(&pix, &gray);
- imgData.lookup[i] = colToByte(gray);
- }
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getRGB(&pix, &rgb);
- imgData.lookup[3*i] = colToByte(rgb.r);
- imgData.lookup[3*i+1] = colToByte(rgb.g);
- imgData.lookup[3*i+2] = colToByte(rgb.b);
- }
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getCMYK(&pix, &cmyk);
- imgData.lookup[4*i] = colToByte(cmyk.c);
- imgData.lookup[4*i+1] = colToByte(cmyk.m);
- imgData.lookup[4*i+2] = colToByte(cmyk.y);
- imgData.lookup[4*i+3] = colToByte(cmyk.k);
- }
- break;
-#endif
- }
- }
-
- if (colorMode == splashModeMono1) {
- srcMode = splashModeMono8;
- } else {
- srcMode = colorMode;
- }
- splash->drawImage(&maskedImageSrc, &imgData, srcMode, gTrue,
- width, height, mat);
-
- delete maskBitmap;
- gfree(imgData.lookup);
- delete imgData.imgStr;
- str->close();
- }
-}
-
-void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object * /*ref*/,
- Stream *str, int width, int height,
- GfxImageColorMap *colorMap,
- Stream *maskStr,
- int maskWidth, int maskHeight,
- GfxImageColorMap *maskColorMap) {
- double *ctm;
- SplashCoord mat[6];
- SplashOutImageData imgData;
- SplashOutImageData imgMaskData;
- SplashColorMode srcMode;
- SplashBitmap *maskBitmap;
- Splash *maskSplash;
- SplashColor maskColor;
- GfxGray gray;
- GfxRGB rgb;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
- Guchar pix;
- int n, i;
-
- ctm = state->getCTM();
- mat[0] = ctm[0];
- mat[1] = ctm[1];
- mat[2] = -ctm[2];
- mat[3] = -ctm[3];
- mat[4] = ctm[2] + ctm[4];
- mat[5] = ctm[3] + ctm[5];
-
- //----- set up the soft mask
-
- imgMaskData.imgStr = new ImageStream(maskStr, maskWidth,
- maskColorMap->getNumPixelComps(),
- maskColorMap->getBits());
- imgMaskData.imgStr->reset();
- imgMaskData.colorMap = maskColorMap;
- imgMaskData.maskColors = NULL;
- imgMaskData.colorMode = splashModeMono8;
- imgMaskData.width = maskWidth;
- imgMaskData.height = maskHeight;
- imgMaskData.y = 0;
- n = 1 << maskColorMap->getBits();
- imgMaskData.lookup = (SplashColorPtr)gmalloc(n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- maskColorMap->getGray(&pix, &gray);
- imgMaskData.lookup[i] = colToByte(gray);
- }
- maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
- 1, splashModeMono8, gFalse);
- maskSplash = new Splash(maskBitmap, vectorAntialias);
- maskColor[0] = 0;
- maskSplash->clear(maskColor);
- maskSplash->drawImage(&imageSrc, &imgMaskData, splashModeMono8, gFalse,
- maskWidth, maskHeight, mat);
- delete imgMaskData.imgStr;
- maskStr->close();
- gfree(imgMaskData.lookup);
- delete maskSplash;
- splash->setSoftMask(maskBitmap);
-
- //----- draw the source image
-
- imgData.imgStr = new ImageStream(str, width,
- colorMap->getNumPixelComps(),
- colorMap->getBits());
- imgData.imgStr->reset();
- imgData.colorMap = colorMap;
- imgData.maskColors = NULL;
- imgData.colorMode = colorMode;
- imgData.width = width;
- imgData.height = height;
- imgData.y = 0;
-
- // special case for one-channel (monochrome/gray/separation) images:
- // build a lookup table here
- imgData.lookup = NULL;
- if (colorMap->getNumPixelComps() == 1) {
- n = 1 << colorMap->getBits();
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- imgData.lookup = (SplashColorPtr)gmalloc(n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getGray(&pix, &gray);
- imgData.lookup[i] = colToByte(gray);
- }
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getRGB(&pix, &rgb);
- imgData.lookup[3*i] = colToByte(rgb.r);
- imgData.lookup[3*i+1] = colToByte(rgb.g);
- imgData.lookup[3*i+2] = colToByte(rgb.b);
- }
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getCMYK(&pix, &cmyk);
- imgData.lookup[4*i] = colToByte(cmyk.c);
- imgData.lookup[4*i+1] = colToByte(cmyk.m);
- imgData.lookup[4*i+2] = colToByte(cmyk.y);
- imgData.lookup[4*i+3] = colToByte(cmyk.k);
- }
- break;
-#endif
- }
- }
-
- if (colorMode == splashModeMono1) {
- srcMode = splashModeMono8;
- } else {
- srcMode = colorMode;
- }
- splash->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat);
-
- splash->setSoftMask(NULL);
- gfree(imgData.lookup);
- delete imgData.imgStr;
- str->close();
-}
-
-void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
- GfxColorSpace *blendingColorSpace,
- GBool isolated, GBool /*knockout*/,
- GBool /*forSoftMask*/) {
- SplashTransparencyGroup *transpGroup;
- SplashColor color;
- double xMin, yMin, xMax, yMax, x, y;
- int tx, ty, w, h;
-
- // transform the bbox
- state->transform(bbox[0], bbox[1], &x, &y);
- xMin = xMax = x;
- yMin = yMax = y;
- state->transform(bbox[0], bbox[3], &x, &y);
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- state->transform(bbox[2], bbox[1], &x, &y);
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- state->transform(bbox[2], bbox[3], &x, &y);
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- tx = (int)floor(xMin);
- if (tx < 0) {
- tx = 0;
- } else if (tx > bitmap->getWidth()) {
- tx = bitmap->getWidth();
- }
- ty = (int)floor(yMin);
- if (ty < 0) {
- ty = 0;
- } else if (ty > bitmap->getHeight()) {
- ty = bitmap->getHeight();
- }
- w = (int)ceil(xMax) - tx + 1;
- if (tx + w > bitmap->getWidth()) {
- w = bitmap->getWidth() - tx;
- }
- if (w < 1) {
- w = 1;
- }
- h = (int)ceil(yMax) - ty + 1;
- if (ty + h > bitmap->getHeight()) {
- h = bitmap->getHeight() - ty;
- }
- if (h < 1) {
- h = 1;
- }
-
- // push a new stack entry
- transpGroup = new SplashTransparencyGroup();
- transpGroup->tx = tx;
- transpGroup->ty = ty;
- transpGroup->blendingColorSpace = blendingColorSpace;
- transpGroup->isolated = isolated;
- transpGroup->next = transpGroupStack;
- transpGroupStack = transpGroup;
-
- // save state
- transpGroup->origBitmap = bitmap;
- transpGroup->origSplash = splash;
-
- //~ this ignores the blendingColorSpace arg
-
- // create the temporary bitmap
- bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue,
- bitmapTopDown);
- splash = new Splash(bitmap, vectorAntialias,
- transpGroup->origSplash->getScreen());
- if (isolated) {
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- color[0] = 0;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- color[0] = color[1] = color[2] = 0;
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- color[0] = color[1] = color[2] = color[3] = 0;
- break;
-#endif
- default:
- // make gcc happy
- break;
- }
- splash->clear(color, 0);
- } else {
- splash->blitTransparent(transpGroup->origBitmap, tx, ty, 0, 0, w, h);
- splash->setInNonIsolatedGroup(transpGroup->origBitmap, tx, ty);
- }
- transpGroup->tBitmap = bitmap;
- state->shiftCTM(-tx, -ty);
- updateCTM(state, 0, 0, 0, 0, 0, 0);
-}
-
-void SplashOutputDev::endTransparencyGroup(GfxState *state) {
- double *ctm;
-
- // restore state
- delete splash;
- bitmap = transpGroupStack->origBitmap;
- splash = transpGroupStack->origSplash;
- ctm = state->getCTM();
- state->shiftCTM(transpGroupStack->tx, transpGroupStack->ty);
- updateCTM(state, 0, 0, 0, 0, 0, 0);
-}
-
-void SplashOutputDev::paintTransparencyGroup(GfxState * /*state*/, double * /*bbox*/) {
- SplashBitmap *tBitmap;
- SplashTransparencyGroup *transpGroup;
- GBool isolated;
- int tx, ty;
-
- tx = transpGroupStack->tx;
- ty = transpGroupStack->ty;
- tBitmap = transpGroupStack->tBitmap;
- isolated = transpGroupStack->isolated;
-
- // paint the transparency group onto the parent bitmap
- // - the clip path was set in the parent's state)
- splash->composite(tBitmap, 0, 0, tx, ty,
- tBitmap->getWidth(), tBitmap->getHeight(),
- gFalse, !isolated);
-
- // pop the stack
- transpGroup = transpGroupStack;
- transpGroupStack = transpGroup->next;
- delete transpGroup;
-
- delete tBitmap;
-}
-
-void SplashOutputDev::setSoftMask(GfxState * /*state*/, double * /*bbox*/,
- GBool alpha, Function *transferFunc,
- GfxColor *backdropColor) {
- SplashBitmap *softMask, *tBitmap;
- Splash *tSplash;
- SplashTransparencyGroup *transpGroup;
- SplashColor color;
- SplashColorPtr p;
- GfxGray gray;
- GfxRGB rgb;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
- double lum, lum2;
- int tx, ty, x, y;
-
- tx = transpGroupStack->tx;
- ty = transpGroupStack->ty;
- tBitmap = transpGroupStack->tBitmap;
-
- // composite with backdrop color
- if (!alpha && colorMode != splashModeMono1) {
- //~ need to correctly handle the case where no blending color
- //~ space is given
- tSplash = new Splash(tBitmap, vectorAntialias,
- transpGroupStack->origSplash->getScreen());
- if (transpGroupStack->blendingColorSpace) {
- switch (colorMode) {
- case splashModeMono1:
- // transparency is not supported in mono1 mode
- break;
- case splashModeMono8:
- transpGroupStack->blendingColorSpace->getGray(backdropColor, &gray);
- color[0] = colToByte(gray);
- tSplash->compositeBackground(color);
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- transpGroupStack->blendingColorSpace->getRGB(backdropColor, &rgb);
- color[0] = colToByte(rgb.r);
- color[1] = colToByte(rgb.g);
- color[2] = colToByte(rgb.b);
- tSplash->compositeBackground(color);
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- transpGroupStack->blendingColorSpace->getCMYK(backdropColor, &cmyk);
- color[0] = colToByte(cmyk.c);
- color[1] = colToByte(cmyk.m);
- color[2] = colToByte(cmyk.y);
- color[3] = colToByte(cmyk.k);
- tSplash->compositeBackground(color);
- break;
-#endif
- }
- delete tSplash;
- }
- }
-
- softMask = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
- 1, splashModeMono8, gFalse);
- memset(softMask->getDataPtr(), 0,
- softMask->getRowSize() * softMask->getHeight());
- p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx;
- int xMax = tBitmap->getWidth();
- int yMax = tBitmap->getHeight();
- if (xMax + tx > bitmap->getWidth()) xMax = bitmap->getWidth() - tx;
- if (yMax + ty > bitmap->getHeight()) yMax = bitmap->getHeight() - ty;
- for (y = 0; y < yMax; ++y) {
- for (x = 0; x < xMax; ++x) {
- tBitmap->getPixel(x, y, color);
- if (alpha) {
- //~ unimplemented
- } else {
- // convert to luminosity
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- lum = color[0] / 255.0;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- lum = (0.3 / 255.0) * color[0] +
- (0.59 / 255.0) * color[1] +
- (0.11 / 255.0) * color[2];
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- lum = (1 - color[3] / 255.0)
- - (0.3 / 255.0) * color[0]
- - (0.59 / 255.0) * color[1]
- - (0.11 / 255.0) * color[2];
- if (lum < 0) {
- lum = 0;
- }
- break;
-#endif
- }
- if (transferFunc) {
- transferFunc->transform(&lum, &lum2);
- } else {
- lum2 = lum;
- }
- p[x] = (int)(lum2 * 255.0 + 0.5);
- }
- }
- p += softMask->getRowSize();
- }
- splash->setSoftMask(softMask);
-
- // pop the stack
- transpGroup = transpGroupStack;
- transpGroupStack = transpGroup->next;
- delete transpGroup;
-
- delete tBitmap;
-}
-
-void SplashOutputDev::clearSoftMask(GfxState * /*state*/) {
- splash->setSoftMask(NULL);
-}
-
-void SplashOutputDev::setPaperColor(SplashColorPtr paperColorA) {
- splashColorCopy(paperColor, paperColorA);
-}
-
-int SplashOutputDev::getBitmapWidth() {
- return bitmap->getWidth();
-}
-
-int SplashOutputDev::getBitmapHeight() {
- return bitmap->getHeight();
-}
-
-SplashBitmap *SplashOutputDev::takeBitmap() {
- SplashBitmap *ret;
-
- ret = bitmap;
- bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode,
- colorMode != splashModeMono1, bitmapTopDown);
- return ret;
-}
-
-void SplashOutputDev::getModRegion(int *xMin, int *yMin,
- int *xMax, int *yMax) {
- splash->getModRegion(xMin, yMin, xMax, yMax);
-}
-
-void SplashOutputDev::clearModRegion() {
- splash->clearModRegion();
-}
-
-void SplashOutputDev::setFillColor(int r, int g, int b) {
- GfxRGB rgb;
- GfxGray gray;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
-
- rgb.r = byteToCol(r);
- rgb.g = byteToCol(g);
- rgb.b = byteToCol(b);
- gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b + 0.5);
- if (gray > gfxColorComp1) {
- gray = gfxColorComp1;
- }
-#if SPLASH_CMYK
- cmyk.c = gfxColorComp1 - rgb.r;
- cmyk.m = gfxColorComp1 - rgb.g;
- cmyk.y = gfxColorComp1 - rgb.b;
- cmyk.k = 0;
- splash->setFillPattern(getColor(gray, &rgb, &cmyk));
-#else
- splash->setFillPattern(getColor(gray, &rgb));
-#endif
-}
-
-SplashFont *SplashOutputDev::getFont(GString *name, double *textMatA) {
- DisplayFontParam *dfp;
- Ref ref;
- SplashOutFontFileID *id;
- SplashFontFile *fontFile;
- SplashFont *fontObj;
- FoFiTrueType *ff;
- Gushort *codeToGID;
- Unicode u;
- SplashCoord textMat[4];
- int cmap, i;
-
- for (i = 0; i < 16; ++i) {
- if (!name->cmp(splashOutSubstFonts[i].name)) {
- break;
- }
- }
- if (i == 16) {
- return NULL;
- }
- ref.num = i;
- ref.gen = -1;
- id = new SplashOutFontFileID(&ref);
-
- // check the font file cache
- if ((fontFile = fontEngine->getFontFile(id))) {
- delete id;
-
- // load the font file
- } else {
- dfp = globalParams->getDisplayFont(name);
- if (dfp && dfp->kind == displayFontT1) {
- SplashFontSrc *fontsrc = new SplashFontSrc;
- fontsrc->setFile(dfp->t1.fileName, gFalse);
- fontFile = fontEngine->loadType1Font(id, fontsrc, winAnsiEncoding);
- } else if (dfp && dfp->kind == displayFontTT) {
- if (!(ff = FoFiTrueType::load(dfp->tt.fileName->getCString()))) {
- return NULL;
- }
- for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) {
- if ((ff->getCmapPlatform(cmap) == 3 &&
- ff->getCmapEncoding(cmap) == 1) ||
- ff->getCmapPlatform(cmap) == 0) {
- break;
- }
- }
- if (cmap == ff->getNumCmaps()) {
- delete ff;
- return NULL;
- }
- codeToGID = (Gushort *)gmallocn(256, sizeof(Gushort));
- for (i = 0; i < 256; ++i) {
- codeToGID[i] = 0;
- if (winAnsiEncoding[i] &&
- (u = globalParams->mapNameToUnicode(winAnsiEncoding[i]))) {
- codeToGID[i] = ff->mapCodeToGID(cmap, u);
- }
- }
- delete ff;
- SplashFontSrc *fontsrc = new SplashFontSrc;
- fontsrc->setFile(dfp->tt.fileName->getCString(), gFalse);
- fontFile = fontEngine->loadTrueTypeFont(id, fontsrc, codeToGID, 256);
- } else {
- return NULL;
- }
- }
-
- // create the scaled font
- textMat[0] = (SplashCoord)textMatA[0];
- textMat[1] = (SplashCoord)textMatA[1];
- textMat[2] = (SplashCoord)textMatA[2];
- textMat[3] = (SplashCoord)textMatA[3];
- fontObj = fontEngine->getFont(fontFile, textMat, splash->getMatrix());
-
- return fontObj;
-}
-
-#if 1 //~tmp: turn off anti-aliasing temporarily
-GBool SplashOutputDev::getVectorAntialias() {
- return splash->getVectorAntialias();
-}
-
-void SplashOutputDev::setVectorAntialias(GBool vaa) {
- splash->setVectorAntialias(vaa);
-}
-#endif