📄 splashoutputdev.cc
字号:
//========================================================================//// SplashOutputDev.cc//// Copyright 2003 Glyph & Cog, LLC////========================================================================#include <aconf.h>#ifdef USE_GCC_PRAGMAS#pragma implementation#endif#include <string.h>#include <unistd.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 + italicstatic 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -