oops.. only build it when it _is_ valid.
[AROS-Contrib.git] / arospdf / splash / SplashFont.cc
blob3a30cc8722d775f8b6107317b9073f5fdaf91d7b
1 //========================================================================
2 //
3 // SplashFont.cc
4 //
5 //========================================================================
7 #include <aconf.h>
9 #ifdef USE_GCC_PRAGMAS
10 #pragma implementation
11 #endif
13 #include <string.h>
14 #include "gmem.h"
15 #include "SplashMath.h"
16 #include "SplashGlyphBitmap.h"
17 #include "SplashFontFile.h"
18 #include "SplashFont.h"
20 //------------------------------------------------------------------------
22 struct SplashFontCacheTag {
23 int c;
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 //------------------------------------------------------------------------
30 // SplashFont
31 //------------------------------------------------------------------------
33 SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
34 SplashCoord *textMatA, GBool aaA) {
35 fontFile = fontFileA;
36 fontFile->incRefCnt();
37 mat[0] = matA[0];
38 mat[1] = matA[1];
39 mat[2] = matA[2];
40 mat[3] = matA[3];
41 textMat[0] = textMatA[0];
42 textMat[1] = textMatA[1];
43 textMat[2] = textMatA[2];
44 textMat[3] = textMatA[3];
45 aa = aaA;
47 cache = NULL;
48 cacheTags = NULL;
50 xMin = yMin = xMax = yMax = 0;
53 void SplashFont::initCache() {
54 int i;
56 // this should be (max - min + 1), but we add some padding to
57 // deal with rounding errors
58 glyphW = xMax - xMin + 3;
59 glyphH = yMax - yMin + 3;
60 if (aa) {
61 glyphSize = glyphW * glyphH;
62 } else {
63 glyphSize = ((glyphW + 7) >> 3) * glyphH;
66 // set up the glyph pixmap cache
67 cacheAssoc = 8;
68 if (glyphSize <= 256) {
69 cacheSets = 8;
70 } else if (glyphSize <= 512) {
71 cacheSets = 4;
72 } else if (glyphSize <= 1024) {
73 cacheSets = 2;
74 } else {
75 cacheSets = 1;
77 cache = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize);
78 cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc,
79 sizeof(SplashFontCacheTag));
80 for (i = 0; i < cacheSets * cacheAssoc; ++i) {
81 cacheTags[i].mru = i & (cacheAssoc - 1);
85 SplashFont::~SplashFont() {
86 fontFile->decRefCnt();
87 if (cache) {
88 gfree(cache);
90 if (cacheTags) {
91 gfree(cacheTags);
95 GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
96 SplashGlyphBitmap *bitmap) {
97 SplashGlyphBitmap bitmap2;
98 int size;
99 Guchar *p;
100 int i, j, k;
102 // no fractional coordinates for large glyphs or non-anti-aliased
103 // glyphs
104 if (!aa || glyphH > 50) {
105 xFrac = yFrac = 0;
108 // check the cache
109 i = (c & (cacheSets - 1)) * cacheAssoc;
110 for (j = 0; j < cacheAssoc; ++j) {
111 if ((cacheTags[i+j].mru & 0x80000000) &&
112 cacheTags[i+j].c == c &&
113 (int)cacheTags[i+j].xFrac == xFrac &&
114 (int)cacheTags[i+j].yFrac == yFrac) {
115 bitmap->x = cacheTags[i+j].x;
116 bitmap->y = cacheTags[i+j].y;
117 bitmap->w = cacheTags[i+j].w;
118 bitmap->h = cacheTags[i+j].h;
119 for (k = 0; k < cacheAssoc; ++k) {
120 if (k != j &&
121 (cacheTags[i+k].mru & 0x7fffffff) <
122 (cacheTags[i+j].mru & 0x7fffffff)) {
123 ++cacheTags[i+k].mru;
126 cacheTags[i+j].mru = 0x80000000;
127 bitmap->aa = aa;
128 bitmap->data = cache + (i+j) * glyphSize;
129 bitmap->freeData = gFalse;
130 return gTrue;
134 // generate the glyph bitmap
135 if (!makeGlyph(c, xFrac, yFrac, &bitmap2)) {
136 return gFalse;
139 // if the glyph doesn't fit in the bounding box, return a temporary
140 // uncached bitmap
141 if (bitmap2.w > glyphW || bitmap2.h > glyphH) {
142 *bitmap = bitmap2;
143 return gTrue;
146 // insert glyph pixmap in cache
147 if (aa) {
148 size = bitmap2.w * bitmap2.h;
149 } else {
150 size = ((bitmap2.w + 7) >> 3) * bitmap2.h;
152 p = NULL; // make gcc happy
153 for (j = 0; j < cacheAssoc; ++j) {
154 if ((cacheTags[i+j].mru & 0x7fffffff) == cacheAssoc - 1) {
155 cacheTags[i+j].mru = 0x80000000;
156 cacheTags[i+j].c = c;
157 cacheTags[i+j].xFrac = (short)xFrac;
158 cacheTags[i+j].yFrac = (short)yFrac;
159 cacheTags[i+j].x = bitmap2.x;
160 cacheTags[i+j].y = bitmap2.y;
161 cacheTags[i+j].w = bitmap2.w;
162 cacheTags[i+j].h = bitmap2.h;
163 p = cache + (i+j) * glyphSize;
164 memcpy(p, bitmap2.data, size);
165 } else {
166 ++cacheTags[i+j].mru;
169 *bitmap = bitmap2;
170 bitmap->data = p;
171 bitmap->freeData = gFalse;
172 if (bitmap2.freeData) {
173 gfree(bitmap2.data);
175 return gTrue;