1 //========================================================================
5 //========================================================================
7 //========================================================================
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 //========================================================================
23 #ifdef USE_GCC_PRAGMAS
24 #pragma implementation
30 #include "SplashMath.h"
31 #include "SplashGlyphBitmap.h"
32 #include "SplashFontFile.h"
33 #include "SplashFont.h"
35 //------------------------------------------------------------------------
37 struct SplashFontCacheTag
{
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 //------------------------------------------------------------------------
46 //------------------------------------------------------------------------
48 SplashFont::SplashFont(SplashFontFile
*fontFileA
, SplashCoord
*matA
,
49 SplashCoord
*textMatA
, GBool aaA
) {
51 fontFile
->incRefCnt();
56 textMat
[0] = textMatA
[0];
57 textMat
[1] = textMatA
[1];
58 textMat
[2] = textMatA
[2];
59 textMat
[3] = textMatA
[3];
65 xMin
= yMin
= xMax
= yMax
= 0;
68 void SplashFont::initCache() {
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
) {
79 glyphSize
= glyphW
* glyphH
;
81 glyphSize
= ((glyphW
+ 7) >> 3) * glyphH
;
85 // set up the glyph pixmap cache
87 if (glyphSize
<= 64) {
89 } else if (glyphSize
<= 128) {
91 } else if (glyphSize
<= 256) {
93 } else if (glyphSize
<= 512) {
95 } else if (glyphSize
<= 1024) {
100 cache
= (Guchar
*)gmallocn_checkoverflow(cacheSets
* cacheAssoc
, glyphSize
);
102 cacheTags
= (SplashFontCacheTag
*)gmallocn(cacheSets
* cacheAssoc
,
103 sizeof(SplashFontCacheTag
));
104 for (i
= 0; i
< cacheSets
* cacheAssoc
; ++i
) {
105 cacheTags
[i
].mru
= i
& (cacheAssoc
- 1);
112 SplashFont::~SplashFont() {
113 fontFile
->decRefCnt();
122 GBool
SplashFont::getGlyph(int c
, int xFrac
, int yFrac
,
123 SplashGlyphBitmap
*bitmap
, int x0
, int y0
, SplashClip
*clip
, SplashClipResult
*clipRes
) {
124 SplashGlyphBitmap bitmap2
;
129 // no fractional coordinates for large glyphs or non-anti-aliased
131 if (!aa
|| glyphH
> 50) {
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
) {
148 (cacheTags
[i
+k
].mru
& 0x7fffffff) <
149 (cacheTags
[i
+j
].mru
& 0x7fffffff)) {
150 ++cacheTags
[i
+k
].mru
;
153 cacheTags
[i
+j
].mru
= 0x80000000;
155 bitmap
->data
= cache
+ (i
+j
) * glyphSize
;
156 bitmap
->freeData
= gFalse
;
158 *clipRes
= clip
->testRect(x0
- bitmap
->x
,
160 x0
- bitmap
->x
+ bitmap
->w
- 1,
161 y0
- bitmap
->y
+ bitmap
->h
- 1);
167 // generate the glyph bitmap
168 if (!makeGlyph(c
, xFrac
, yFrac
, &bitmap2
, x0
, y0
, clip
, clipRes
)) {
172 if (*clipRes
== splashClipAllOutside
)
174 bitmap
->freeData
= gFalse
;
175 if (bitmap2
.freeData
) gfree(bitmap2
.data
);
179 // if the glyph doesn't fit in the bounding box, return a temporary
181 if (bitmap2
.w
> glyphW
|| bitmap2
.h
> glyphH
) {
186 // insert glyph pixmap in cache
188 size
= bitmap2
.w
* bitmap2
.h
;
190 size
= ((bitmap2
.w
+ 7) >> 3) * bitmap2
.h
;
192 p
= NULL
; // make gcc happy
195 // we had problems on the malloc of the cache, so ignore it
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
);
213 ++cacheTags
[i
+j
].mru
;
218 bitmap
->freeData
= gFalse
;
219 if (bitmap2
.freeData
) {