Hi, this patch has two parts.
First, it removes all exit(1) calls in favor or the best i could find, that
is, return NULL (and hope the caller can understand NULL as error) in the
gmem routines and the correct ignore in DCTStream.
Second, in Splash code it moves the resposability for checking if a glyph is
inside the clip rect from Splash::fillGlyph2 to its callers,
Splash::fillGlyph and Splash::fillChar, that way i can check inside
SplashFTFont::makeGlyph if the font is inside the clip rect before rendering.
This fixes crash due to memory exhaustion on KDE bug 150693 [1] because that
pdf specifies a HUGE font outside the clip rect :-/
CairoOutputDev does not need to do that because cairo already does it.
If noone objects to the patch (that is a bit intrusive but clean enough imho)
i will commit it to HEAD and 0.6 branch next friday.
Albert
[1] http://bugs.kde.org/show_bug.cgi?id=150693
diff --git a/goo/gmem.cc b/goo/gmem.cc
index f1f8f5f..6f56fec 100644
--- a/goo/gmem.cc
+++ b/goo/gmem.cc
@@ -64,7 +64,7 @@ void *gmalloc(size_t size) GMEM_EXCEP {
throw GMemException();
#else
fprintf(stderr, "Out of memory\n");
- exit(1);
+ return NULL;
#endif
}
hdr = (GMemHdr *)mem;
@@ -99,7 +99,7 @@ void *gmalloc(size_t size) GMEM_EXCEP {
throw GMemException();
#else
fprintf(stderr, "Out of memory\n");
- exit(1);
+ return NULL;
#endif
}
return p;
@@ -147,7 +147,7 @@ void *grealloc(void *p, size_t size) GMEM_EXCEP {
throw GMemException();
#else
fprintf(stderr, "Out of memory\n");
- exit(1);
+ return NULL;
#endif
}
return q;
@@ -166,7 +166,7 @@ void *gmallocn(int nObjs, int objSize) GMEM_EXCEP {
throw GMemException();
#else
fprintf(stderr, "Bogus memory allocation size\n");
- exit(1);
+ return NULL;
#endif
}
return gmalloc(n);
@@ -187,7 +187,7 @@ void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP {
throw GMemException();
#else
fprintf(stderr, "Bogus memory allocation size\n");
- exit(1);
+ return NULL;
#endif
}
return grealloc(p, n);
diff --git a/poppler/DCTStream.cc b/poppler/DCTStream.cc
index 14132df..b568ca5 100644
--- a/poppler/DCTStream.cc
+++ b/poppler/DCTStream.cc
@@ -115,7 +115,8 @@ void DCTStream::reset() {
if (c == -1)
{
error(-1, "Could not find start of jpeg data");
- exit(1);
+ src.abort = true;
+ return;
}
if (c != 0xFF) c = 0;
}
diff --git a/splash/Splash.cc b/splash/Splash.cc
index ecb0881..d84c666 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -1675,7 +1675,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",
@@ -1686,17 +1686,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;
@@ -1704,24 +1707,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,
@@ -1812,10 +1813,6 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
}
}
}
- }
- opClipRes = clipRes;
-
- return splashOk;
}
SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData,
diff --git a/splash/Splash.h b/splash/Splash.h
index 99203b2..58de95a 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -149,7 +149,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 <h>
@@ -265,7 +265,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/splash/SplashFTFont.cc b/splash/SplashFTFont.cc
index 963d42d..e673980 100644
--- a/splash/SplashFTFont.cc
+++ b/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,20 @@ 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) return gTrue;
+
if (FT_Render_Glyph(slot, aa ? ft_render_mode_normal
: ft_render_mode_mono)) {
return gFalse;
diff --git a/splash/SplashFTFont.h b/splash/SplashFTFont.h
index f351b2f..70c01d3 100644
--- a/splash/SplashFTFont.h
+++ b/splash/SplashFTFont.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 <xFrac> and <yFrac> 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/splash/SplashFont.cc b/splash/SplashFont.cc
index bea6fc9..c899446 100644
--- a/splash/SplashFont.cc
+++ b/splash/SplashFont.cc
@@ -93,7 +93,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;
@@ -132,10 +132,17 @@ GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
}
// 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/splash/SplashFont.h b/splash/SplashFont.h
index d3b0353..3af9412 100644
--- a/splash/SplashFont.h
+++ b/splash/SplashFont.h
@@ -13,6 +13,7 @@
#include "goo/gtypes.h"
#include "SplashTypes.h"
+#include "SplashClip.h"
struct SplashGlyphBitmap;
struct SplashFontCacheTag;
@@ -64,12 +65,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 <xFrac> and <yFrac> 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/splash/SplashT1Font.cc b/splash/SplashT1Font.cc
index b30c0fc..87a51a7 100644
--- a/splash/SplashT1Font.cc
+++ b/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/splash/SplashT1Font.h b/splash/SplashT1Font.h
index 919dc03..d6816b8 100644
--- a/splash/SplashT1Font.h
+++ b/splash/SplashT1Font.h
@@ -31,12 +31,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 <xFrac> and <yFrac> 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);
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler