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,
34
SplashCoord *textMatA, GBool aaA) {
36
fontFile->incRefCnt();
41
textMat[0] = textMatA[0];
42
textMat[1] = textMatA[1];
43
textMat[2] = textMatA[2];
44
textMat[3] = textMatA[3];
50
xMin = yMin = xMax = yMax = 0;
53
void SplashFont::initCache() {
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;
61
glyphSize = glyphW * glyphH;
63
glyphSize = ((glyphW + 7) >> 3) * glyphH;
66
// set up the glyph pixmap cache
68
if (glyphSize <= 256) {
70
} else if (glyphSize <= 512) {
72
} else if (glyphSize <= 1024) {
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();
95
GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
96
SplashGlyphBitmap *bitmap) {
97
SplashGlyphBitmap bitmap2;
102
// no fractional coordinates for large glyphs or non-anti-aliased
104
if (!aa || glyphH > 50) {
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) {
121
(cacheTags[i+k].mru & 0x7fffffff) <
122
(cacheTags[i+j].mru & 0x7fffffff)) {
123
++cacheTags[i+k].mru;
126
cacheTags[i+j].mru = 0x80000000;
128
bitmap->data = cache + (i+j) * glyphSize;
129
bitmap->freeData = gFalse;
134
// generate the glyph bitmap
135
if (!makeGlyph(c, xFrac, yFrac, &bitmap2)) {
139
// if the glyph doesn't fit in the bounding box, return a temporary
141
if (bitmap2.w > glyphW || bitmap2.h > glyphH) {
146
// insert glyph pixmap in cache
148
size = bitmap2.w * bitmap2.h;
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);
166
++cacheTags[i+j].mru;
171
bitmap->freeData = gFalse;
172
if (bitmap2.freeData) {