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
) {