]> git.ipfire.org Git - thirdparty/cups.git/blob - pdftops/SplashFont.cxx
Load cups into easysw/current.
[thirdparty/cups.git] / pdftops / SplashFont.cxx
1 //========================================================================
2 //
3 // SplashFont.cc
4 //
5 //========================================================================
6
7 #include <config.h>
8
9 #ifdef USE_GCC_PRAGMAS
10 #pragma implementation
11 #endif
12
13 #include <string.h>
14 #include "gmem.h"
15 #include "SplashMath.h"
16 #include "SplashGlyphBitmap.h"
17 #include "SplashFontFile.h"
18 #include "SplashFont.h"
19
20 //------------------------------------------------------------------------
21
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
27 };
28
29 //------------------------------------------------------------------------
30 // SplashFont
31 //------------------------------------------------------------------------
32
33 SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
34 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 aa = aaA;
42
43 cache = NULL;
44 cacheTags = NULL;
45
46 xMin = yMin = xMax = yMax = 0;
47 }
48
49 void SplashFont::initCache() {
50 int i;
51
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;
56 if (aa) {
57 glyphSize = glyphW * glyphH;
58 } else {
59 glyphSize = ((glyphW + 7) >> 3) * glyphH;
60 }
61
62 // set up the glyph pixmap cache
63 cacheAssoc = 8;
64 if (glyphSize <= 256) {
65 cacheSets = 8;
66 } else if (glyphSize <= 512) {
67 cacheSets = 4;
68 } else if (glyphSize <= 1024) {
69 cacheSets = 2;
70 } else {
71 cacheSets = 1;
72 }
73 cache = (Guchar *)gmallocn(cacheSets* cacheAssoc, glyphSize);
74 cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc,
75 sizeof(SplashFontCacheTag));
76 for (i = 0; i < cacheSets * cacheAssoc; ++i) {
77 cacheTags[i].mru = i & (cacheAssoc - 1);
78 }
79 }
80
81 SplashFont::~SplashFont() {
82 fontFile->decRefCnt();
83 if (cache) {
84 gfree(cache);
85 }
86 if (cacheTags) {
87 gfree(cacheTags);
88 }
89 }
90
91 GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
92 SplashGlyphBitmap *bitmap) {
93 SplashGlyphBitmap bitmap2;
94 int size;
95 Guchar *p;
96 int i, j, k;
97
98 // no fractional coordinates for large glyphs or non-anti-aliased
99 // glyphs
100 if (!aa || glyphH > 50) {
101 xFrac = yFrac = 0;
102 }
103
104 // check the cache
105 i = (c & (cacheSets - 1)) * cacheAssoc;
106 for (j = 0; j < cacheAssoc; ++j) {
107 if ((cacheTags[i+j].mru & 0x80000000) &&
108 cacheTags[i+j].c == c &&
109 (int)cacheTags[i+j].xFrac == xFrac &&
110 (int)cacheTags[i+j].yFrac == yFrac) {
111 bitmap->x = cacheTags[i+j].x;
112 bitmap->y = cacheTags[i+j].y;
113 bitmap->w = cacheTags[i+j].w;
114 bitmap->h = cacheTags[i+j].h;
115 for (k = 0; k < cacheAssoc; ++k) {
116 if (k != j &&
117 (cacheTags[i+k].mru & 0x7fffffff) <
118 (cacheTags[i+j].mru & 0x7fffffff)) {
119 ++cacheTags[i+k].mru;
120 }
121 }
122 cacheTags[i+j].mru = 0x80000000;
123 bitmap->aa = aa;
124 bitmap->data = cache + (i+j) * glyphSize;
125 bitmap->freeData = gFalse;
126 return gTrue;
127 }
128 }
129
130 // generate the glyph bitmap
131 if (!makeGlyph(c, xFrac, yFrac, &bitmap2)) {
132 return gFalse;
133 }
134
135 // if the glyph doesn't fit in the bounding box, return a temporary
136 // uncached bitmap
137 if (bitmap2.w > glyphW || bitmap2.h > glyphH) {
138 *bitmap = bitmap2;
139 return gTrue;
140 }
141
142 // insert glyph pixmap in cache
143 if (aa) {
144 size = bitmap2.w * bitmap2.h;
145 } else {
146 size = ((bitmap2.w + 7) >> 3) * bitmap2.h;
147 }
148 p = NULL; // make gcc happy
149 for (j = 0; j < cacheAssoc; ++j) {
150 if ((cacheTags[i+j].mru & 0x7fffffff) == cacheAssoc - 1) {
151 cacheTags[i+j].mru = 0x80000000;
152 cacheTags[i+j].c = c;
153 cacheTags[i+j].xFrac = (short)xFrac;
154 cacheTags[i+j].yFrac = (short)yFrac;
155 cacheTags[i+j].x = bitmap2.x;
156 cacheTags[i+j].y = bitmap2.y;
157 cacheTags[i+j].w = bitmap2.w;
158 cacheTags[i+j].h = bitmap2.h;
159 p = cache + (i+j) * glyphSize;
160 memcpy(p, bitmap2.data, size);
161 } else {
162 ++cacheTags[i+j].mru;
163 }
164 }
165 *bitmap = bitmap2;
166 bitmap->data = p;
167 bitmap->freeData = gFalse;
168 if (bitmap2.freeData) {
169 gfree(bitmap2.data);
170 }
171 return gTrue;
172 }