summaryrefslogtreecommitdiffstats
path: root/kpdf/xpdf/splash/SplashFont.cc
diff options
context:
space:
mode:
Diffstat (limited to 'kpdf/xpdf/splash/SplashFont.cc')
-rw-r--r--kpdf/xpdf/splash/SplashFont.cc201
1 files changed, 201 insertions, 0 deletions
diff --git a/kpdf/xpdf/splash/SplashFont.cc b/kpdf/xpdf/splash/SplashFont.cc
new file mode 100644
index 00000000..4a91d5e8
--- /dev/null
+++ b/kpdf/xpdf/splash/SplashFont.cc
@@ -0,0 +1,201 @@
+//========================================================================
+//
+// SplashFont.cc
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include "gmem.h"
+#include "SplashMath.h"
+#include "SplashGlyphBitmap.h"
+#include "SplashFontFile.h"
+#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
+//------------------------------------------------------------------------
+
+SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
+ SplashCoord *textMatA, GBool aaA) {
+ fontFile = fontFileA;
+ fontFile->incRefCnt();
+ mat[0] = matA[0];
+ mat[1] = matA[1];
+ mat[2] = matA[2];
+ mat[3] = matA[3];
+ textMat[0] = textMatA[0];
+ textMat[1] = textMatA[1];
+ 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 <= 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;
+
+ // no fractional coordinates for large glyphs or non-anti-aliased
+ // glyphs
+ if (!aa || glyphH > 50) {
+ 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;
+ 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, 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) {
+ *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;
+ }
+ }
+ *bitmap = bitmap2;
+ bitmap->data = p;
+ bitmap->freeData = gFalse;
+ if (bitmap2.freeData) {
+ gfree(bitmap2.data);
+ }
+ }
+ return gTrue;
+}