1 //========================================================================
5 //========================================================================
10 #pragma implementation
15 #include "SplashMath.h"
16 #include "SplashGlyphBitmap.h"
17 #include "SplashFontFile.h"
18 #include "SplashFont.h"
20 //------------------------------------------------------------------------
22 struct SplashFontCacheTag {
24 short xFrac, yFrac; // x and y fractions
25 int mru; // valid bit (0x80000000) and MRU index
26 int x, y, w, h; // offset and size of glyph
29 //------------------------------------------------------------------------
31 //------------------------------------------------------------------------
33 SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
36 fontFile->incRefCnt();
46 xMin = yMin = xMax = yMax = 0;
49 void SplashFont::initCache() {
52 // this should be (max - min + 1), but we add some padding to
53 // deal with rounding errors
54 glyphW = xMax - xMin + 3;
55 glyphH = yMax - yMin + 3;
57 glyphSize = glyphW * glyphH;
59 glyphSize = ((glyphW + 7) >> 3) * glyphH;
62 // set up the glyph pixmap cache
64 if (glyphSize <= 256) {
66 } else if (glyphSize <= 512) {
68 } else if (glyphSize <= 1024) {
73 cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
74 cacheTags = (SplashFontCacheTag *)gmalloc(cacheSets * cacheAssoc *
75 sizeof(SplashFontCacheTag));
76 for (i = 0; i < cacheSets * cacheAssoc; ++i) {
77 cacheTags[i].mru = i & (cacheAssoc - 1);
81 SplashFont::~SplashFont() {
82 fontFile->decRefCnt();
91 GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
92 SplashGlyphBitmap *bitmap) {
93 SplashGlyphBitmap bitmap2;
99 i = (c & (cacheSets - 1)) * cacheAssoc;
100 for (j = 0; j < cacheAssoc; ++j) {
101 if ((cacheTags[i+j].mru & 0x80000000) &&
102 cacheTags[i+j].c == c &&
103 (int)cacheTags[i+j].xFrac == xFrac &&
104 (int)cacheTags[i+j].yFrac == yFrac) {
105 bitmap->x = cacheTags[i+j].x;
106 bitmap->y = cacheTags[i+j].y;
107 bitmap->w = cacheTags[i+j].w;
108 bitmap->h = cacheTags[i+j].h;
109 for (k = 0; k < cacheAssoc; ++k) {
111 (cacheTags[i+k].mru & 0x7fffffff) <
112 (cacheTags[i+j].mru & 0x7fffffff)) {
113 ++cacheTags[i+k].mru;
116 cacheTags[i+j].mru = 0x80000000;
118 bitmap->data = cache + (i+j) * glyphSize;
119 bitmap->freeData = gFalse;
124 // generate the glyph bitmap
125 if (!makeGlyph(c, xFrac, yFrac, &bitmap2)) {
129 // if the glyph doesn't fit in the bounding box, return a temporary
131 if (bitmap2.w > glyphW || bitmap2.h > glyphH) {
136 // insert glyph pixmap in cache
138 size = bitmap2.w * bitmap2.h;
140 size = ((bitmap2.w + 7) >> 3) * bitmap2.h;
142 p = NULL; // make gcc happy
143 for (j = 0; j < cacheAssoc; ++j) {
144 if ((cacheTags[i+j].mru & 0x7fffffff) == cacheAssoc - 1) {
145 cacheTags[i+j].mru = 0x80000000;
146 cacheTags[i+j].c = c;
147 cacheTags[i+j].xFrac = (short)xFrac;
148 cacheTags[i+j].yFrac = (short)yFrac;
149 cacheTags[i+j].x = bitmap2.x;
150 cacheTags[i+j].y = bitmap2.y;
151 cacheTags[i+j].w = bitmap2.w;
152 cacheTags[i+j].h = bitmap2.h;
153 p = cache + (i+j) * glyphSize;
154 memcpy(p, bitmap2.data, size);
156 ++cacheTags[i+j].mru;
161 bitmap->freeData = gFalse;
162 if (bitmap2.freeData) {