[poppler] splash/Splash.cc splash/SplashFont.cc splash/SplashFont.h splash/SplashFTFont.cc splash/SplashFTFont.h splash/Splash.h splash/SplashT1Font.cc splash/SplashT1Font.h
Albert Astals Cid
aacid at kemper.freedesktop.org
Mon Oct 22 13:14:51 PDT 2007
splash/Splash.cc | 207 ++++++++++++++++++++++++-------------------------
splash/Splash.h | 4
splash/SplashFTFont.cc | 23 ++++-
splash/SplashFTFont.h | 4
splash/SplashFont.cc | 29 +++++-
splash/SplashFont.h | 5 -
splash/SplashT1Font.cc | 11 +-
splash/SplashT1Font.h | 4
8 files changed, 162 insertions(+), 125 deletions(-)
New commits:
commit 2a333e5a618b5c92f3c703816b950321f25d3aab
Author: Albert Astals Cid <tsdgeos at bluebox.localdomain>
Date: Mon Oct 22 22:14:43 2007 +0200
Splash rework, check if font is inside clip area before rendering it to a temporary bitmap. Fixes KDE bug 150693
This change is not trivial. What i did is:
It is getGlyph the one that does the intersection between clip area and rendering area of the font instead fillGlyph2
That means some clipRes = state->clip->testRect but we win more robustness against broken pdf that specify HUGE fonts
diff --git a/splash/Splash.cc b/splash/Splash.cc
index 45eb6fe..d9306fa 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,118 +1707,112 @@ 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,
- state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
- p = glyph->data;
- for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
- pipeSetXY(&pipe, x0 - glyph->x, y1);
- for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) {
- alpha = *p++;
- if (alpha != 0) {
- pipe.shape = (SplashCoord)(alpha / 255.0);
- pipeRun(&pipe);
- updateModX(x1);
- updateModY(y1);
- } else {
- pipeIncX(&pipe);
- }
- }
- }
- } else {
- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
- state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
- p = glyph->data;
- for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
- pipeSetXY(&pipe, x0 - glyph->x, y1);
- for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) {
- alpha0 = *p++;
- for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) {
- if (alpha0 & 0x80) {
- pipeRun(&pipe);
- updateModX(x1);
- updateModY(y1);
- } else {
- pipeIncX(&pipe);
- }
- alpha0 <<= 1;
- }
- }
- }
+ if (noClip) {
+ if (glyph->aa) {
+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
+ state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
+ p = glyph->data;
+ for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
+ pipeSetXY(&pipe, x0 - glyph->x, y1);
+ for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) {
+ alpha = *p++;
+ if (alpha != 0) {
+ pipe.shape = (SplashCoord)(alpha / 255.0);
+ pipeRun(&pipe);
+ updateModX(x1);
+ updateModY(y1);
+ } else {
+ pipeIncX(&pipe);
+ }
+ }
}
} else {
- if (glyph->aa) {
- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
- state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
- p = glyph->data;
- for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
- pipeSetXY(&pipe, x0 - glyph->x, y1);
- for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) {
- if (state->clip->test(x1, y1)) {
- alpha = *p++;
- if (alpha != 0) {
- pipe.shape = (SplashCoord)(alpha / 255.0);
- pipeRun(&pipe);
- updateModX(x1);
- updateModY(y1);
- } else {
- pipeIncX(&pipe);
- }
- } else {
- pipeIncX(&pipe);
- ++p;
- }
- }
- }
- } else {
- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
- state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
- p = glyph->data;
- for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
- pipeSetXY(&pipe, x0 - glyph->x, y1);
- for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) {
- alpha0 = *p++;
- for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) {
- if (state->clip->test(x1, y1)) {
- if (alpha0 & 0x80) {
- pipeRun(&pipe);
- updateModX(x1);
- updateModY(y1);
- } else {
- pipeIncX(&pipe);
- }
- } else {
- pipeIncX(&pipe);
- }
- alpha0 <<= 1;
- }
- }
- }
+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
+ state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
+ p = glyph->data;
+ for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
+ pipeSetXY(&pipe, x0 - glyph->x, y1);
+ for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) {
+ alpha0 = *p++;
+ for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) {
+ if (alpha0 & 0x80) {
+ pipeRun(&pipe);
+ updateModX(x1);
+ updateModY(y1);
+ } else {
+ pipeIncX(&pipe);
+ }
+ alpha0 <<= 1;
+ }
+ }
+ }
+ }
+ } else {
+ if (glyph->aa) {
+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
+ state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
+ p = glyph->data;
+ for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
+ pipeSetXY(&pipe, x0 - glyph->x, y1);
+ for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) {
+ if (state->clip->test(x1, y1)) {
+ alpha = *p++;
+ if (alpha != 0) {
+ pipe.shape = (SplashCoord)(alpha / 255.0);
+ pipeRun(&pipe);
+ updateModX(x1);
+ updateModY(y1);
+ } else {
+ pipeIncX(&pipe);
+ }
+ } else {
+ pipeIncX(&pipe);
+ ++p;
+ }
+ }
+ }
+ } else {
+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
+ state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
+ p = glyph->data;
+ for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
+ pipeSetXY(&pipe, x0 - glyph->x, y1);
+ for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) {
+ alpha0 = *p++;
+ for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) {
+ if (state->clip->test(x1, y1)) {
+ if (alpha0 & 0x80) {
+ pipeRun(&pipe);
+ updateModX(x1);
+ updateModY(y1);
+ } else {
+ pipeIncX(&pipe);
+ }
+ } else {
+ pipeIncX(&pipe);
+ }
+ alpha0 <<= 1;
+ }
+ }
}
}
}
- 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..0241df0 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,23 @@ 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/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..9c34599 100644
--- a/splash/SplashFont.cc
+++ b/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/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);
More information about the poppler
mailing list