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
,
36 fontFile
->incRefCnt();
46 xMin
= yMin
= xMax
= yMax
= 0;
49 void SplashFont::initCache() {
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;
57 glyphSize
= glyphW
* glyphH
;
59 glyphSize
= ((glyphW
+ 7) >> 3) * glyphH
;
62 // set up the glyph pixmap cache
64 if (glyphSize
<= 256) {
66 } else if (glyphSize
<= 512) {
68 } else if (glyphSize
<= 1024) {
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);
81 SplashFont::~SplashFont() {
82 fontFile
->decRefCnt();
91 GBool
SplashFont::getGlyph(int c
, int xFrac
, int yFrac
,
92 SplashGlyphBitmap
*bitmap
) {
93 SplashGlyphBitmap bitmap2
;
98 // no fractional coordinates for large glyphs or non-anti-aliased
100 if (!aa
|| glyphH
> 50) {
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
) {
117 (cacheTags
[i
+k
].mru
& 0x7fffffff) <
118 (cacheTags
[i
+j
].mru
& 0x7fffffff)) {
119 ++cacheTags
[i
+k
].mru
;
122 cacheTags
[i
+j
].mru
= 0x80000000;
124 bitmap
->data
= cache
+ (i
+j
) * glyphSize
;
125 bitmap
->freeData
= gFalse
;
130 // generate the glyph bitmap
131 if (!makeGlyph(c
, xFrac
, yFrac
, &bitmap2
)) {
135 // if the glyph doesn't fit in the bounding box, return a temporary
137 if (bitmap2
.w
> glyphW
|| bitmap2
.h
> glyphH
) {
142 // insert glyph pixmap in cache
144 size
= bitmap2
.w
* bitmap2
.h
;
146 size
= ((bitmap2
.w
+ 7) >> 3) * bitmap2
.h
;
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
);
162 ++cacheTags
[i
+j
].mru
;
167 bitmap
->freeData
= gFalse
;
168 if (bitmap2
.freeData
) {