source: trunk/poppler/mypoppler/splash/SplashFont.cc @ 44

Last change on this file since 44 was 2, checked in by Eugene Romanenko, 16 years ago

First import

File size: 4.1 KB
Line 
1//========================================================================
2//
3// SplashFont.cc
4//
5//========================================================================
6
7#include <config.h>
8
9#ifdef USE_GCC_PRAGMAS
10#pragma implementation
11#endif
12
13#include <string.h>
14#include "goo/gmem.h"
15#include "SplashMath.h"
16#include "SplashGlyphBitmap.h"
17#include "SplashFontFile.h"
18#include "SplashFont.h"
19
20//------------------------------------------------------------------------
21
22struct SplashFontCacheTag {
23  int c;
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
27};
28
29//------------------------------------------------------------------------
30// SplashFont
31//------------------------------------------------------------------------
32
33SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
34                       GBool aaA) {
35  fontFile = fontFileA;
36  fontFile->incRefCnt();
37  mat[0] = matA[0];
38  mat[1] = matA[1];
39  mat[2] = matA[2];
40  mat[3] = matA[3];
41  aa = aaA;
42
43  cache = NULL;
44  cacheTags = NULL;
45
46  xMin = yMin = xMax = yMax = 0;
47}
48
49void SplashFont::initCache() {
50  int i;
51
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;
56  if (aa) {
57    glyphSize = glyphW * glyphH;
58  } else {
59    glyphSize = ((glyphW + 7) >> 3) * glyphH;
60  }
61
62  // set up the glyph pixmap cache
63  cacheAssoc = 8;
64  if (glyphSize <= 256) {
65    cacheSets = 8;
66  } else if (glyphSize <= 512) {
67    cacheSets = 4;
68  } else if (glyphSize <= 1024) {
69    cacheSets = 2;
70  } else {
71    cacheSets = 1;
72  }
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);
78  }
79}
80
81SplashFont::~SplashFont() {
82  fontFile->decRefCnt();
83  if (cache) {
84    gfree(cache);
85  }
86  if (cacheTags) {
87    gfree(cacheTags);
88  }
89}
90
91GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
92                           SplashGlyphBitmap *bitmap) {
93  SplashGlyphBitmap bitmap2;
94  int size;
95  Guchar *p;
96  int i, j, k;
97
98  // no fractional coordinates for large glyphs or non-anti-aliased
99  // glyphs
100  if (!aa || glyphH > 50) {
101    xFrac = yFrac = 0;
102  }
103
104  // check the cache
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) {
116        if (k != j &&
117            (cacheTags[i+k].mru & 0x7fffffff) <
118              (cacheTags[i+j].mru & 0x7fffffff)) {
119          ++cacheTags[i+k].mru;
120        }
121      }
122      cacheTags[i+j].mru = 0x80000000;
123      bitmap->aa = aa;
124      bitmap->data = cache + (i+j) * glyphSize;
125      bitmap->freeData = gFalse;
126      return gTrue;
127    }
128  }
129
130  // generate the glyph bitmap
131  if (!makeGlyph(c, xFrac, yFrac, &bitmap2)) {
132    return gFalse;
133  }
134
135  // if the glyph doesn't fit in the bounding box, return a temporary
136  // uncached bitmap
137  if (bitmap2.w > glyphW || bitmap2.h > glyphH) {
138    *bitmap = bitmap2;
139    return gTrue;
140  }
141
142  // insert glyph pixmap in cache
143  if (aa) {
144    size = bitmap2.w * bitmap2.h;
145  } else {
146    size = ((bitmap2.w + 7) >> 3) * bitmap2.h;
147  }
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);
161    } else {
162      ++cacheTags[i+j].mru;
163    }
164  }
165  *bitmap = bitmap2;
166  bitmap->data = p;
167  bitmap->freeData = gFalse;
168  if (bitmap2.freeData) {
169    gfree(bitmap2.data);
170  }
171  return gTrue;
172}
Note: See TracBrowser for help on using the repository browser.