Not quite sure part of this fix which remove a bunch of xMin/yMin/xMax/yMax related code would lead any side effect I do not know, but they make the code more clean.
-Sam On Sun, Aug 28, 2011 at 1:26 PM, Sam Liao <[email protected]> wrote: > Most of the efforts of font rendering is wasted on makeGlyph as > for the cache mechinism, this fix tries to use a unlimited cache > to improve the performance. Testing result of the perf-test program > showes up it reduces about more than 25% running time. > > Possible further improvement not added: > - SplashFontEngine cache size/mechanism. This is also a fixed-size > cache. > --- > splash/SplashFTFont.cc | 65 ------------------- > splash/SplashFTFontFile.cc | 1 - > splash/SplashFont.cc | 153 +++++++++---------------------------------- > splash/SplashFont.h | 46 ++++++++----- > splash/SplashT1FontFile.cc | 1 - > 5 files changed, 61 insertions(+), 205 deletions(-) > > diff --git a/splash/SplashFTFont.cc b/splash/SplashFTFont.cc > index eea3d64..d8edb18 100644 > --- a/splash/SplashFTFont.cc > +++ b/splash/SplashFTFont.cc > @@ -62,8 +62,6 @@ SplashFTFont::SplashFTFont(SplashFTFontFile > *fontFileA, SplashCoord *matA, > enableSlightHinting(fontFileA->engine->enableSlightHinting) > { > FT_Face face; > - double div; > - int x, y; > > face = fontFileA->face; > if (FT_New_Size(face, &sizeObj)) { > @@ -81,69 +79,6 @@ SplashFTFont::SplashFTFont(SplashFTFontFile > *fontFileA, SplashCoord *matA, > // arithmetic doesn't work so well > textScale = splashSqrt(textMat[2]*textMat[2] + textMat[3]*textMat[3]) / > size; > > - div = face->bbox.xMax > 20000 ? 65536 : 1; > - > - // transform the four corners of the font bounding box -- the min > - // and max values form the bounding box of the transformed font > - x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMin) / > - (div * face->units_per_EM)); > - xMin = xMax = x; > - y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMin) / > - (div * face->units_per_EM)); > - yMin = yMax = y; > - x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMax) / > - (div * face->units_per_EM)); > - if (x < xMin) { > - xMin = x; > - } else if (x > xMax) { > - xMax = x; > - } > - y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMax) / > - (div * face->units_per_EM)); > - if (y < yMin) { > - yMin = y; > - } else if (y > yMax) { > - yMax = y; > - } > - x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMin) / > - (div * face->units_per_EM)); > - if (x < xMin) { > - xMin = x; > - } else if (x > xMax) { > - xMax = x; > - } > - y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMin) / > - (div * face->units_per_EM)); > - if (y < yMin) { > - yMin = y; > - } else if (y > yMax) { > - yMax = y; > - } > - x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMax) / > - (div * face->units_per_EM)); > - if (x < xMin) { > - xMin = x; > - } else if (x > xMax) { > - xMax = x; > - } > - y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMax) / > - (div * face->units_per_EM)); > - if (y < yMin) { > - yMin = y; > - } else if (y > yMax) { > - yMax = y; > - } > - // This is a kludge: some buggy PDF generators embed fonts with > - // zero bounding boxes. > - if (xMax == xMin) { > - xMin = 0; > - xMax = (int)size; > - } > - if (yMax == yMin) { > - yMin = 0; > - yMax = (int)((SplashCoord)1.2 * size); > - } > - > // compute the transform matrix > #if USE_FIXEDPOINT > matrix.xx = (FT_Fixed)((mat[0] / size).getRaw()); > diff --git a/splash/SplashFTFontFile.cc b/splash/SplashFTFontFile.cc > index 160481e..40aac17 100644 > --- a/splash/SplashFTFontFile.cc > +++ b/splash/SplashFTFontFile.cc > @@ -132,7 +132,6 @@ SplashFont *SplashFTFontFile::makeFont(SplashCoord *mat, > SplashFont *font; > > font = new SplashFTFont(this, mat, textMat); > - font->initCache(); > return font; > } > > diff --git a/splash/SplashFont.cc b/splash/SplashFont.cc > index 2bfcdc8..58ae214 100644 > --- a/splash/SplashFont.cc > +++ b/splash/SplashFont.cc > @@ -32,15 +32,6 @@ > #include "SplashFont.h" > > //------------------------------------------------------------------------ > - > -struct SplashFontCacheTag { > - int c; > - short xFrac, yFrac; // x and y fractions > - int mru; // valid bit (0x80000000) and MRU index > - int x, y, w, h; // offset and size of glyph > -}; > - > -//------------------------------------------------------------------------ > // SplashFont > //------------------------------------------------------------------------ > > @@ -57,106 +48,45 @@ SplashFont::SplashFont(SplashFontFile *fontFileA, > SplashCoord *matA, > textMat[2] = textMatA[2]; > textMat[3] = textMatA[3]; > aa = aaA; > - > - cache = NULL; > - cacheTags = NULL; > - > - xMin = yMin = xMax = yMax = 0; > -} > - > -void SplashFont::initCache() { > - int i; > - > - // this should be (max - min + 1), but we add some padding to > - // deal with rounding errors > - glyphW = xMax - xMin + 3; > - glyphH = yMax - yMin + 3; > - if (aa) { > - glyphSize = glyphW * glyphH; > - } else { > - glyphSize = ((glyphW + 7) >> 3) * glyphH; > - } > - > - // set up the glyph pixmap cache > - cacheAssoc = 8; > - if (glyphSize <= 64) { > - cacheSets = 32; > - } else if (glyphSize <= 128) { > - cacheSets = 16; > - } else if (glyphSize <= 256) { > - cacheSets = 8; > - } else if (glyphSize <= 512) { > - cacheSets = 4; > - } else if (glyphSize <= 1024) { > - cacheSets = 2; > - } else { > - cacheSets = 1; > - } > - 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); > - } > - } else { > - cacheAssoc = 0; > - } > } > > SplashFont::~SplashFont() { > fontFile->decRefCnt(); > - if (cache) { > - gfree(cache); > - } > - if (cacheTags) { > - gfree(cacheTags); > - } > } > > GBool SplashFont::getGlyph(int c, int xFrac, int yFrac, > SplashGlyphBitmap *bitmap, int x0, int y0, > SplashClip *clip, > SplashClipResult *clipRes) { > SplashGlyphBitmap bitmap2; > int size; > - Guchar *p; > - int i, j, k; > + SplashFontCacheKey key; > + SplashFontCacheEntity ent; > > // no fractional coordinates for large glyphs or non-anti-aliased > // glyphs > - if (!aa || glyphH > 50) { > + if (!aa) { > xFrac = yFrac = 0; > } > > - // check the cache > - i = (c & (cacheSets - 1)) * cacheAssoc; > - for (j = 0; j < cacheAssoc; ++j) { > - if ((cacheTags[i+j].mru & 0x80000000) && > - cacheTags[i+j].c == c && > - (int)cacheTags[i+j].xFrac == xFrac && > - (int)cacheTags[i+j].yFrac == yFrac) { > - bitmap->x = cacheTags[i+j].x; > - bitmap->y = cacheTags[i+j].y; > - bitmap->w = cacheTags[i+j].w; > - bitmap->h = cacheTags[i+j].h; > - for (k = 0; k < cacheAssoc; ++k) { > - if (k != j && > - (cacheTags[i+k].mru & 0x7fffffff) < > - (cacheTags[i+j].mru & 0x7fffffff)) { > - ++cacheTags[i+k].mru; > - } > - } > - cacheTags[i+j].mru = 0x80000000; > + key.c = c; > + key.xFrac = (short) xFrac; > + key.yFrac = (short) yFrac; > + > + SplashFontCache::iterator iter = cache.find(key); > + > + if (iter != cache.end()) { > + bitmap->x = iter->second.x; > + bitmap->y = iter->second.y; > + bitmap->w = iter->second.w; > + bitmap->h = iter->second.h; > bitmap->aa = aa; > - bitmap->data = cache + (i+j) * glyphSize; > + bitmap->data = iter->second.data.get(); > 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 > @@ -171,49 +101,30 @@ GBool SplashFont::getGlyph(int c, int xFrac, int yFrac, > return gTrue; > } > > - // if the glyph doesn't fit in the bounding box, return a temporary > - // uncached bitmap > - if (bitmap2.w > glyphW || bitmap2.h > glyphH) { > - *bitmap = bitmap2; > - return gTrue; > - } > - > // insert glyph pixmap in cache > if (aa) { > size = bitmap2.w * bitmap2.h; > } else { > size = ((bitmap2.w + 7) >> 3) * bitmap2.h; > } > - p = NULL; // make gcc happy > - if (cacheAssoc == 0) > - { > - // we had problems on the malloc of the cache, so ignore it > - *bitmap = bitmap2; > - } > - else > - { > - for (j = 0; j < cacheAssoc; ++j) { > - if ((cacheTags[i+j].mru & 0x7fffffff) == cacheAssoc - 1) { > - cacheTags[i+j].mru = 0x80000000; > - cacheTags[i+j].c = c; > - cacheTags[i+j].xFrac = (short)xFrac; > - cacheTags[i+j].yFrac = (short)yFrac; > - cacheTags[i+j].x = bitmap2.x; > - cacheTags[i+j].y = bitmap2.y; > - cacheTags[i+j].w = bitmap2.w; > - cacheTags[i+j].h = bitmap2.h; > - p = cache + (i+j) * glyphSize; > - memcpy(p, bitmap2.data, size); > - } else { > - ++cacheTags[i+j].mru; > + > + ent.x = bitmap2.x; > + ent.y = bitmap2.y; > + ent.w = bitmap2.w; > + ent.h = bitmap2.h; > + ent.data = GucharPtr((Guchar *)gmallocn_checkoverflow (1, size), gfree); > + if (ent.data.get() != NULL) { > + memcpy(ent.data.get(), bitmap2.data, size); > + cache[key] = ent; > + > + *bitmap = bitmap2; > + bitmap->data = ent.data.get(); > + bitmap->freeData = gFalse; > + if (bitmap2.freeData) { > + gfree(bitmap2.data); > } > - } > - *bitmap = bitmap2; > - bitmap->data = p; > - bitmap->freeData = gFalse; > - if (bitmap2.freeData) { > - gfree(bitmap2.data); > - } > + } else { > + *bitmap = bitmap2; > } > return gTrue; > } > diff --git a/splash/SplashFont.h b/splash/SplashFont.h > index 78b00d2..1f78dbc 100644 > --- a/splash/SplashFont.h > +++ b/splash/SplashFont.h > @@ -26,11 +26,13 @@ > #endif > > #include "goo/gtypes.h" > +#include "goo/GooString.h" > #include "SplashTypes.h" > #include "SplashClip.h" > +#include <tr1/memory> > +#include <map> > > struct SplashGlyphBitmap; > -struct SplashFontCacheTag; > class SplashFontFile; > class SplashPath; > > @@ -44,6 +46,31 @@ class SplashPath; > ((SplashCoord)1 / (SplashCoord)splashFontFraction) > > //------------------------------------------------------------------------ > + > +struct SplashFontCacheKey { > + int c; > + short xFrac, yFrac; // x and y fractions > + > + bool operator <(const SplashFontCacheKey& b) const { > + if (c != b.c) > + return c < b.c; > + if (xFrac != b.xFrac) > + return xFrac < b.xFrac; > + if (yFrac != b.yFrac) > + return yFrac < b.yFrac; > + return false; > + } > +}; > + > +typedef std::tr1::shared_ptr<Guchar> GucharPtr; > +struct SplashFontCacheEntity { > + int x, y, w, h; // offset and size of glyph > + GucharPtr data; > +}; > + > +typedef std::map<struct SplashFontCacheKey, struct > SplashFontCacheEntity> SplashFontCache; > + > +//------------------------------------------------------------------------ > // SplashFont > //------------------------------------------------------------------------ > > @@ -53,10 +80,6 @@ public: > SplashFont(SplashFontFile *fontFileA, SplashCoord *matA, > SplashCoord *textMatA, GBool aaA); > > - // This must be called after the constructor, so that the subclass > - // constructor has a chance to compute the bbox. > - void initCache(); > - > virtual ~SplashFont(); > > SplashFontFile *getFontFile() { return fontFile; } > @@ -96,10 +119,6 @@ public: > // Return the font transform matrix. > SplashCoord *getMatrix() { return mat; } > > - // Return the glyph bounding box. > - void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA) > - { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } > - > protected: > > SplashFontFile *fontFile; > @@ -108,14 +127,7 @@ protected: > SplashCoord textMat[4]; // text transform matrix > // (text space -> user space) > GBool aa; // anti-aliasing > - int xMin, yMin, xMax, yMax; // glyph bounding box > - Guchar *cache; // glyph bitmap cache > - SplashFontCacheTag * // cache tags > - cacheTags; > - int glyphW, glyphH; // size of glyph bitmaps > - int glyphSize; // size of glyph bitmaps, in bytes > - int cacheSets; // number of sets in cache > - int cacheAssoc; // cache associativity (glyphs per set) > + SplashFontCache cache; > }; > > #endif > diff --git a/splash/SplashT1FontFile.cc b/splash/SplashT1FontFile.cc > index 3f46ba6..45059a1 100644 > --- a/splash/SplashT1FontFile.cc > +++ b/splash/SplashT1FontFile.cc > @@ -127,7 +127,6 @@ SplashFont *SplashT1FontFile::makeFont(SplashCoord *mat, > SplashFont *font; > > font = new SplashT1Font(this, mat, textMat); > - font->initCache(); > return font; > } > > -- > 1.7.4.1 > _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
