beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / splash / SplashFont.cc
blob3d6d6b2343e379c6c2ce8c9dd294a1c9ae7c0e13
1 //========================================================================
2 //
3 // SplashFont.cc
4 //
5 //========================================================================
7 //========================================================================
8 //
9 // Modified under the Poppler project - http://poppler.freedesktop.org
11 // All changes made under the Poppler project to this file are licensed
12 // under GPL version 2 or later
14 // Copyright (C) 2007-2008, 2010, 2014 Albert Astals Cid <aacid@kde.org>
16 // To see a description of the changes please see the Changelog file that
17 // came with your tarball or type make ChangeLog if you are building from git
19 //========================================================================
21 #include <config.h>
23 #ifdef USE_GCC_PRAGMAS
24 #pragma implementation
25 #endif
27 #include <limits.h>
28 #include <string.h>
29 #include "goo/gmem.h"
30 #include "SplashMath.h"
31 #include "SplashGlyphBitmap.h"
32 #include "SplashFontFile.h"
33 #include "SplashFont.h"
35 //------------------------------------------------------------------------
37 struct SplashFontCacheTag {
38 int c;
39 short xFrac, yFrac; // x and y fractions
40 int mru; // valid bit (0x80000000) and MRU index
41 int x, y, w, h; // offset and size of glyph
44 //------------------------------------------------------------------------
45 // SplashFont
46 //------------------------------------------------------------------------
48 SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
49 SplashCoord *textMatA, GBool aaA) {
50 fontFile = fontFileA;
51 fontFile->incRefCnt();
52 mat[0] = matA[0];
53 mat[1] = matA[1];
54 mat[2] = matA[2];
55 mat[3] = matA[3];
56 textMat[0] = textMatA[0];
57 textMat[1] = textMatA[1];
58 textMat[2] = textMatA[2];
59 textMat[3] = textMatA[3];
60 aa = aaA;
62 cache = NULL;
63 cacheTags = NULL;
65 xMin = yMin = xMax = yMax = 0;
68 void SplashFont::initCache() {
69 int i;
71 // this should be (max - min + 1), but we add some padding to
72 // deal with rounding errors
73 glyphW = xMax - xMin + 3;
74 glyphH = yMax - yMin + 3;
75 if (glyphW > INT_MAX / glyphH) {
76 glyphSize = -1;
77 } else {
78 if (aa) {
79 glyphSize = glyphW * glyphH;
80 } else {
81 glyphSize = ((glyphW + 7) >> 3) * glyphH;
85 // set up the glyph pixmap cache
86 cacheAssoc = 8;
87 if (glyphSize <= 64) {
88 cacheSets = 32;
89 } else if (glyphSize <= 128) {
90 cacheSets = 16;
91 } else if (glyphSize <= 256) {
92 cacheSets = 8;
93 } else if (glyphSize <= 512) {
94 cacheSets = 4;
95 } else if (glyphSize <= 1024) {
96 cacheSets = 2;
97 } else {
98 cacheSets = 1;
100 cache = (Guchar *)gmallocn_checkoverflow(cacheSets* cacheAssoc, glyphSize);
101 if (cache != NULL) {
102 cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc,
103 sizeof(SplashFontCacheTag));
104 for (i = 0; i < cacheSets * cacheAssoc; ++i) {
105 cacheTags[i].mru = i & (cacheAssoc - 1);
107 } else {
108 cacheAssoc = 0;
112 SplashFont::~SplashFont() {
113 fontFile->decRefCnt();
114 if (cache) {
115 gfree(cache);
117 if (cacheTags) {
118 gfree(cacheTags);
122 GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
123 SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes) {
124 SplashGlyphBitmap bitmap2;
125 int size;
126 Guchar *p;
127 int i, j, k;
129 // no fractional coordinates for large glyphs or non-anti-aliased
130 // glyphs
131 if (!aa || glyphH > 50) {
132 xFrac = yFrac = 0;
135 // check the cache
136 i = (c & (cacheSets - 1)) * cacheAssoc;
137 for (j = 0; j < cacheAssoc; ++j) {
138 if ((cacheTags[i+j].mru & 0x80000000) &&
139 cacheTags[i+j].c == c &&
140 (int)cacheTags[i+j].xFrac == xFrac &&
141 (int)cacheTags[i+j].yFrac == yFrac) {
142 bitmap->x = cacheTags[i+j].x;
143 bitmap->y = cacheTags[i+j].y;
144 bitmap->w = cacheTags[i+j].w;
145 bitmap->h = cacheTags[i+j].h;
146 for (k = 0; k < cacheAssoc; ++k) {
147 if (k != j &&
148 (cacheTags[i+k].mru & 0x7fffffff) <
149 (cacheTags[i+j].mru & 0x7fffffff)) {
150 ++cacheTags[i+k].mru;
153 cacheTags[i+j].mru = 0x80000000;
154 bitmap->aa = aa;
155 bitmap->data = cache + (i+j) * glyphSize;
156 bitmap->freeData = gFalse;
158 *clipRes = clip->testRect(x0 - bitmap->x,
159 y0 - bitmap->y,
160 x0 - bitmap->x + bitmap->w - 1,
161 y0 - bitmap->y + bitmap->h - 1);
163 return gTrue;
167 // generate the glyph bitmap
168 if (!makeGlyph(c, xFrac, yFrac, &bitmap2, x0, y0, clip, clipRes)) {
169 return gFalse;
172 if (*clipRes == splashClipAllOutside)
174 bitmap->freeData = gFalse;
175 if (bitmap2.freeData) gfree(bitmap2.data);
176 return gTrue;
179 // if the glyph doesn't fit in the bounding box, return a temporary
180 // uncached bitmap
181 if (bitmap2.w > glyphW || bitmap2.h > glyphH) {
182 *bitmap = bitmap2;
183 return gTrue;
186 // insert glyph pixmap in cache
187 if (aa) {
188 size = bitmap2.w * bitmap2.h;
189 } else {
190 size = ((bitmap2.w + 7) >> 3) * bitmap2.h;
192 p = NULL; // make gcc happy
193 if (cacheAssoc == 0)
195 // we had problems on the malloc of the cache, so ignore it
196 *bitmap = bitmap2;
198 else
200 for (j = 0; j < cacheAssoc; ++j) {
201 if ((cacheTags[i+j].mru & 0x7fffffff) == cacheAssoc - 1) {
202 cacheTags[i+j].mru = 0x80000000;
203 cacheTags[i+j].c = c;
204 cacheTags[i+j].xFrac = (short)xFrac;
205 cacheTags[i+j].yFrac = (short)yFrac;
206 cacheTags[i+j].x = bitmap2.x;
207 cacheTags[i+j].y = bitmap2.y;
208 cacheTags[i+j].w = bitmap2.w;
209 cacheTags[i+j].h = bitmap2.h;
210 p = cache + (i+j) * glyphSize;
211 memcpy(p, bitmap2.data, size);
212 } else {
213 ++cacheTags[i+j].mru;
216 *bitmap = bitmap2;
217 bitmap->data = p;
218 bitmap->freeData = gFalse;
219 if (bitmap2.freeData) {
220 gfree(bitmap2.data);
223 return gTrue;