diff --git a/xpdf/goo/gmem.cc b/xpdf/goo/gmem.cc index 6b13b38d0..7676db893 100644 --- a/xpdf/goo/gmem.cc +++ b/xpdf/goo/gmem.cc @@ -172,6 +172,25 @@ void *gmallocn(int nObjs, int objSize) GMEM_EXCEP { return gmalloc(n); } +void *gmallocn_checkoverflow(int nObjs, int objSize) GMEM_EXCEP { + int n; + + if (nObjs == 0) { + return NULL; + } + n = nObjs * objSize; + if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) { +#if USE_EXCEPTIONS + throw GMemException(); +#else + fprintf(stderr, "Bogus memory allocation size\n"); + return NULL; +#endif + } + return gmalloc(n); +} + + void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP { int n; diff --git a/xpdf/goo/gmem.h b/xpdf/goo/gmem.h index da34736f2..ffe5b0da3 100644 --- a/xpdf/goo/gmem.h +++ b/xpdf/goo/gmem.h @@ -52,6 +52,7 @@ extern void *grealloc(void *p, int size) GMEM_EXCEP; */ extern void *gmallocn(int nObjs, int objSize) GMEM_EXCEP; extern void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP; +extern void *gmallocn_checkoverflow(int nObjs, int objSize) GMEM_EXCEP; /* * Same as free, but checks for and ignores NULL pointers. diff --git a/xpdf/splash/Splash.cc b/xpdf/splash/Splash.cc index a3588a0f9..3c252e062 100644 --- a/xpdf/splash/Splash.cc +++ b/xpdf/splash/Splash.cc @@ -1626,7 +1626,7 @@ SplashError Splash::fillChar(SplashCoord x, SplashCoord y, SplashGlyphBitmap glyph; SplashCoord xt, yt; int x0, y0, xFrac, yFrac; - SplashError err; + SplashClipResult clipRes; if (debugMode) { printf("fillChar: x=%.2f y=%.2f c=%3d=0x%02x='%c'\n", @@ -1637,17 +1637,20 @@ SplashError Splash::fillChar(SplashCoord x, SplashCoord y, xFrac = splashFloor((xt - x0) * splashFontFraction); y0 = splashFloor(yt); yFrac = splashFloor((yt - y0) * splashFontFraction); - if (!font->getGlyph(c, xFrac, yFrac, &glyph)) { + if (!font->getGlyph(c, xFrac, yFrac, &glyph, x0, y0, state->clip, &clipRes)) { return splashErrNoGlyph; } - err = fillGlyph2(x0, y0, &glyph); + if (clipRes != splashClipAllOutside) { + fillGlyph2(x0, y0, &glyph, clipRes == splashClipAllInside); + } + opClipRes = clipRes; if (glyph.freeData) { gfree(glyph.data); } - return err; + return splashOk; } -SplashError Splash::fillGlyph(SplashCoord x, SplashCoord y, +void Splash::fillGlyph(SplashCoord x, SplashCoord y, SplashGlyphBitmap *glyph) { SplashCoord xt, yt; int x0, y0; @@ -1655,24 +1658,22 @@ SplashError Splash::fillGlyph(SplashCoord x, SplashCoord y, transform(state->matrix, x, y, &xt, &yt); x0 = splashFloor(xt); y0 = splashFloor(yt); - return fillGlyph2(x0, y0, glyph); + SplashClipResult clipRes = state->clip->testRect(x0 - glyph->x, + y0 - glyph->y, + x0 - glyph->x + glyph->w - 1, + y0 - glyph->y + glyph->h - 1); + if (clipRes != splashClipAllOutside) { + fillGlyph2(x0, y0, glyph, clipRes == splashClipAllInside); + } + opClipRes = clipRes; } -SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { +void Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph, GBool noClip) { SplashPipe pipe; - SplashClipResult clipRes; - GBool noClip; int alpha0, alpha; Guchar *p; int x1, y1, xx, xx1, yy; - if ((clipRes = state->clip->testRect(x0 - glyph->x, - y0 - glyph->y, - x0 - glyph->x + glyph->w - 1, - y0 - glyph->y + glyph->h - 1)) - != splashClipAllOutside) { - noClip = clipRes == splashClipAllInside; - if (noClip) { if (glyph->aa) { pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, @@ -1763,10 +1764,6 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { } } } - } - opClipRes = clipRes; - - return splashOk; } SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData, diff --git a/xpdf/splash/Splash.h b/xpdf/splash/Splash.h index c6246227c..3c7571fbd 100644 --- a/xpdf/splash/Splash.h +++ b/xpdf/splash/Splash.h @@ -151,7 +151,7 @@ public: // Draw a glyph, using the current fill pattern. This function does // not free any data, i.e., it ignores glyph->freeData. - SplashError fillGlyph(SplashCoord x, SplashCoord y, + void fillGlyph(SplashCoord x, SplashCoord y, SplashGlyphBitmap *glyph); // Draws an image mask using the fill color. This will read @@ -267,7 +267,7 @@ private: SplashPath *makeDashedPath(SplashPath *xPath); SplashError fillWithPattern(SplashPath *path, GBool eo, SplashPattern *pattern, SplashCoord alpha); - SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph); + void fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph, GBool noclip); void dumpPath(SplashPath *path); void dumpXPath(SplashXPath *path); diff --git a/xpdf/splash/SplashFTFont.cc b/xpdf/splash/SplashFTFont.cc index 26fad7476..42d92af40 100644 --- a/xpdf/splash/SplashFTFont.cc +++ b/xpdf/splash/SplashFTFont.cc @@ -147,12 +147,12 @@ SplashFTFont::~SplashFTFont() { } GBool SplashFTFont::getGlyph(int c, int xFrac, int /*yFrac*/, - SplashGlyphBitmap *bitmap) { - return SplashFont::getGlyph(c, xFrac, 0, bitmap); + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes) { + return SplashFont::getGlyph(c, xFrac, 0, bitmap, x0, y0, clip, clipRes); } GBool SplashFTFont::makeGlyph(int c, int xFrac, int /*yFrac*/, - SplashGlyphBitmap *bitmap) { + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes) { SplashFTFontFile *ff; FT_Vector offset; FT_GlyphSlot slot; @@ -196,6 +196,24 @@ GBool SplashFTFont::makeGlyph(int c, int xFrac, int /*yFrac*/, return gFalse; } #endif + + FT_Glyph_Metrics *glyphMetrics = &(ff->face->glyph->metrics); + // prelimirary values from FT_Glyph_Metrics + bitmap->x = splashRound(-glyphMetrics->horiBearingX / 64.0); + bitmap->y = splashRound(glyphMetrics->horiBearingY / 64.0); + bitmap->w = splashRound(glyphMetrics->width / 64.0); + bitmap->h = splashRound(glyphMetrics->height / 64.0); + + *clipRes = clip->testRect(x0 - bitmap->x, + y0 - bitmap->y, + x0 - bitmap->x + bitmap->w - 1, + y0 - bitmap->y + bitmap->h - 1); + if (*clipRes == splashClipAllOutside) + { + bitmap->freeData = gFalse; + return gTrue; + } + if (FT_Render_Glyph(slot, aa ? ft_render_mode_normal : ft_render_mode_mono)) { return gFalse; diff --git a/xpdf/splash/SplashFTFont.h b/xpdf/splash/SplashFTFont.h index 8e31d1459..e014ba3fd 100644 --- a/xpdf/splash/SplashFTFont.h +++ b/xpdf/splash/SplashFTFont.h @@ -35,12 +35,12 @@ public: // Munge xFrac and yFrac before calling SplashFont::getGlyph. virtual GBool getGlyph(int c, int xFrac, int yFrac, - SplashGlyphBitmap *bitmap); + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes); // Rasterize a glyph. The and values are the same // as described for getGlyph. virtual GBool makeGlyph(int c, int xFrac, int yFrac, - SplashGlyphBitmap *bitmap); + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes); // Return the path for a glyph. virtual SplashPath *getGlyphPath(int c); diff --git a/xpdf/splash/SplashFont.cc b/xpdf/splash/SplashFont.cc index 3a30cc872..e4ab59c89 100644 --- a/xpdf/splash/SplashFont.cc +++ b/xpdf/splash/SplashFont.cc @@ -74,11 +74,15 @@ void SplashFont::initCache() { } else { cacheSets = 1; } - cache = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize); - cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc, + cache = (Guchar *)gmallocn_checkoverflow(cacheSets * cacheAssoc, glyphSize); + if (cache != NULL) { + cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc, sizeof(SplashFontCacheTag)); - for (i = 0; i < cacheSets * cacheAssoc; ++i) { - cacheTags[i].mru = i & (cacheAssoc - 1); + for (i = 0; i < cacheSets * cacheAssoc; ++i) { + cacheTags[i].mru = i & (cacheAssoc - 1); + } + } else { + cacheAssoc = 0; } } @@ -93,7 +97,7 @@ SplashFont::~SplashFont() { } GBool SplashFont::getGlyph(int c, int xFrac, int yFrac, - SplashGlyphBitmap *bitmap) { + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes) { SplashGlyphBitmap bitmap2; int size; Guchar *p; @@ -127,15 +131,28 @@ GBool SplashFont::getGlyph(int c, int xFrac, int yFrac, bitmap->aa = aa; bitmap->data = cache + (i+j) * glyphSize; bitmap->freeData = gFalse; + + *clipRes = clip->testRect(x0 - bitmap->x, + y0 - bitmap->y, + x0 - bitmap->x + bitmap->w - 1, + y0 - bitmap->y + bitmap->h - 1); + return gTrue; } } // generate the glyph bitmap - if (!makeGlyph(c, xFrac, yFrac, &bitmap2)) { + if (!makeGlyph(c, xFrac, yFrac, &bitmap2, x0, y0, clip, clipRes)) { return gFalse; } + if (*clipRes == splashClipAllOutside) + { + bitmap->freeData = gFalse; + if (bitmap2.freeData) gfree(bitmap2.data); + return gTrue; + } + // if the glyph doesn't fit in the bounding box, return a temporary // uncached bitmap if (bitmap2.w > glyphW || bitmap2.h > glyphH) { diff --git a/xpdf/splash/SplashFont.h b/xpdf/splash/SplashFont.h index 60a2db763..82ee0370d 100644 --- a/xpdf/splash/SplashFont.h +++ b/xpdf/splash/SplashFont.h @@ -15,6 +15,7 @@ #include "gtypes.h" #include "SplashTypes.h" +#include "SplashClip.h" struct SplashGlyphBitmap; struct SplashFontCacheTag; @@ -66,12 +67,12 @@ public: // should override this to zero out xFrac and/or yFrac if they don't // support fractional coordinates. virtual GBool getGlyph(int c, int xFrac, int yFrac, - SplashGlyphBitmap *bitmap); + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes); // Rasterize a glyph. The and values are the same // as described for getGlyph. virtual GBool makeGlyph(int c, int xFrac, int yFrac, - SplashGlyphBitmap *bitmap) = 0; + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes) = 0; // Return the path for a glyph. virtual SplashPath *getGlyphPath(int c) = 0; diff --git a/xpdf/splash/SplashT1Font.cc b/xpdf/splash/SplashT1Font.cc index 8219596c6..19237e1d0 100644 --- a/xpdf/splash/SplashT1Font.cc +++ b/xpdf/splash/SplashT1Font.cc @@ -176,12 +176,12 @@ SplashT1Font::~SplashT1Font() { } GBool SplashT1Font::getGlyph(int c, int xFrac, int yFrac, - SplashGlyphBitmap *bitmap) { - return SplashFont::getGlyph(c, 0, 0, bitmap); + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes) { + return SplashFont::getGlyph(c, 0, 0, bitmap, x0, y0, clip, clipRes); } GBool SplashT1Font::makeGlyph(int c, int xFrac, int yFrac, - SplashGlyphBitmap *bitmap) { + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes) { GLYPH *glyph; int n, i; @@ -211,6 +211,11 @@ GBool SplashT1Font::makeGlyph(int c, int xFrac, int yFrac, bitmap->freeData = gTrue; } + *clipRes = clip->testRect(x0 - bitmap->x, + y0 - bitmap->y, + x0 - bitmap->x + bitmap->w - 1, + y0 - bitmap->y + bitmap->h - 1); + return gTrue; } diff --git a/xpdf/splash/SplashT1Font.h b/xpdf/splash/SplashT1Font.h index 8ea74de48..129c6ad58 100644 --- a/xpdf/splash/SplashT1Font.h +++ b/xpdf/splash/SplashT1Font.h @@ -33,12 +33,12 @@ public: // Munge xFrac and yFrac before calling SplashFont::getGlyph. virtual GBool getGlyph(int c, int xFrac, int yFrac, - SplashGlyphBitmap *bitmap); + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes); // Rasterize a glyph. The and values are the same // as described for getGlyph. virtual GBool makeGlyph(int c, int xFrac, int yFrac, - SplashGlyphBitmap *bitmap); + SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes); // Return the path for a glyph. virtual SplashPath *getGlyphPath(int c);