~ubuntu-branches/ubuntu/saucy/emscripten/saucy-proposed

« back to all changes in this revision

Viewing changes to tests/poppler/splash/SplashFont.cc

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//========================================================================
 
2
//
 
3
// SplashFont.cc
 
4
//
 
5
//========================================================================
 
6
 
 
7
//========================================================================
 
8
//
 
9
// Modified under the Poppler project - http://poppler.freedesktop.org
 
10
//
 
11
// All changes made under the Poppler project to this file are licensed
 
12
// under GPL version 2 or later
 
13
//
 
14
// Copyright (C) 2007-2008, 2010 Albert Astals Cid <aacid@kde.org>
 
15
//
 
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
 
18
//
 
19
//========================================================================
 
20
 
 
21
#include <config.h>
 
22
 
 
23
#ifdef USE_GCC_PRAGMAS
 
24
#pragma implementation
 
25
#endif
 
26
 
 
27
#include <string.h>
 
28
#include "goo/gmem.h"
 
29
#include "SplashMath.h"
 
30
#include "SplashGlyphBitmap.h"
 
31
#include "SplashFontFile.h"
 
32
#include "SplashFont.h"
 
33
 
 
34
//------------------------------------------------------------------------
 
35
 
 
36
struct SplashFontCacheTag {
 
37
  int c;
 
38
  short xFrac, yFrac;           // x and y fractions
 
39
  int mru;                      // valid bit (0x80000000) and MRU index
 
40
  int x, y, w, h;               // offset and size of glyph
 
41
};
 
42
 
 
43
//------------------------------------------------------------------------
 
44
// SplashFont
 
45
//------------------------------------------------------------------------
 
46
 
 
47
SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
 
48
                       SplashCoord *textMatA, GBool aaA) {
 
49
  fontFile = fontFileA;
 
50
  fontFile->incRefCnt();
 
51
  mat[0] = matA[0];
 
52
  mat[1] = matA[1];
 
53
  mat[2] = matA[2];
 
54
  mat[3] = matA[3];
 
55
  textMat[0] = textMatA[0];
 
56
  textMat[1] = textMatA[1];
 
57
  textMat[2] = textMatA[2];
 
58
  textMat[3] = textMatA[3];
 
59
  aa = aaA;
 
60
 
 
61
  cache = NULL;
 
62
  cacheTags = NULL;
 
63
 
 
64
  xMin = yMin = xMax = yMax = 0;
 
65
}
 
66
 
 
67
void SplashFont::initCache() {
 
68
  int i;
 
69
 
 
70
  // this should be (max - min + 1), but we add some padding to
 
71
  // deal with rounding errors
 
72
  glyphW = xMax - xMin + 3;
 
73
  glyphH = yMax - yMin + 3;
 
74
  if (aa) {
 
75
    glyphSize = glyphW * glyphH;
 
76
  } else {
 
77
    glyphSize = ((glyphW + 7) >> 3) * glyphH;
 
78
  }
 
79
 
 
80
  // set up the glyph pixmap cache
 
81
  cacheAssoc = 8;
 
82
  if (glyphSize <= 64) {
 
83
    cacheSets = 32;
 
84
  } else if (glyphSize <= 128) {
 
85
    cacheSets = 16;
 
86
  } else if (glyphSize <= 256) {
 
87
    cacheSets = 8;
 
88
  } else if (glyphSize <= 512) {
 
89
    cacheSets = 4;
 
90
  } else if (glyphSize <= 1024) {
 
91
    cacheSets = 2;
 
92
  } else {
 
93
    cacheSets = 1;
 
94
  }
 
95
  cache = (Guchar *)gmallocn_checkoverflow(cacheSets* cacheAssoc, glyphSize);
 
96
  if (cache != NULL) {
 
97
    cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc,
 
98
                                             sizeof(SplashFontCacheTag));
 
99
    for (i = 0; i < cacheSets * cacheAssoc; ++i) {
 
100
      cacheTags[i].mru = i & (cacheAssoc - 1);
 
101
    }
 
102
  } else {
 
103
    cacheAssoc = 0;
 
104
  }
 
105
}
 
106
 
 
107
SplashFont::~SplashFont() {
 
108
  fontFile->decRefCnt();
 
109
  if (cache) {
 
110
    gfree(cache);
 
111
  }
 
112
  if (cacheTags) {
 
113
    gfree(cacheTags);
 
114
  }
 
115
}
 
116
 
 
117
GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
 
118
                           SplashGlyphBitmap *bitmap, int x0, int y0, SplashClip *clip, SplashClipResult *clipRes) {
 
119
  SplashGlyphBitmap bitmap2;
 
120
  int size;
 
121
  Guchar *p;
 
122
  int i, j, k;
 
123
 
 
124
  // no fractional coordinates for large glyphs or non-anti-aliased
 
125
  // glyphs
 
126
  if (!aa || glyphH > 50) {
 
127
    xFrac = yFrac = 0;
 
128
  }
 
129
 
 
130
  // check the cache
 
131
  i = (c & (cacheSets - 1)) * cacheAssoc;
 
132
  for (j = 0; j < cacheAssoc; ++j) {
 
133
    if ((cacheTags[i+j].mru & 0x80000000) &&
 
134
        cacheTags[i+j].c == c &&
 
135
        (int)cacheTags[i+j].xFrac == xFrac &&
 
136
        (int)cacheTags[i+j].yFrac == yFrac) {
 
137
      bitmap->x = cacheTags[i+j].x;
 
138
      bitmap->y = cacheTags[i+j].y;
 
139
      bitmap->w = cacheTags[i+j].w;
 
140
      bitmap->h = cacheTags[i+j].h;
 
141
      for (k = 0; k < cacheAssoc; ++k) {
 
142
        if (k != j &&
 
143
            (cacheTags[i+k].mru & 0x7fffffff) <
 
144
              (cacheTags[i+j].mru & 0x7fffffff)) {
 
145
          ++cacheTags[i+k].mru;
 
146
        }
 
147
      }
 
148
      cacheTags[i+j].mru = 0x80000000;
 
149
      bitmap->aa = aa;
 
150
      bitmap->data = cache + (i+j) * glyphSize;
 
151
      bitmap->freeData = gFalse;
 
152
 
 
153
      *clipRes = clip->testRect(x0 - bitmap->x,
 
154
                                y0 - bitmap->y,
 
155
                                x0 - bitmap->x + bitmap->w - 1,
 
156
                                y0 - bitmap->y + bitmap->h - 1);
 
157
 
 
158
      return gTrue;
 
159
    }
 
160
  }
 
161
 
 
162
  // generate the glyph bitmap
 
163
  if (!makeGlyph(c, xFrac, yFrac, &bitmap2, x0, y0, clip, clipRes)) {
 
164
    return gFalse;
 
165
  }
 
166
 
 
167
  if (*clipRes == splashClipAllOutside)
 
168
  {
 
169
    bitmap->freeData = gFalse;
 
170
    if (bitmap2.freeData) gfree(bitmap2.data);
 
171
    return gTrue;
 
172
  }
 
173
 
 
174
  // if the glyph doesn't fit in the bounding box, return a temporary
 
175
  // uncached bitmap
 
176
  if (bitmap2.w > glyphW || bitmap2.h > glyphH) {
 
177
    *bitmap = bitmap2;
 
178
    return gTrue;
 
179
  }
 
180
 
 
181
  // insert glyph pixmap in cache
 
182
  if (aa) {
 
183
    size = bitmap2.w * bitmap2.h;
 
184
  } else {
 
185
    size = ((bitmap2.w + 7) >> 3) * bitmap2.h;
 
186
  }
 
187
  p = NULL; // make gcc happy
 
188
  if (cacheAssoc == 0)
 
189
  {
 
190
    // we had problems on the malloc of the cache, so ignore it
 
191
    *bitmap = bitmap2;
 
192
  }
 
193
  else
 
194
  {
 
195
    for (j = 0; j < cacheAssoc; ++j) {
 
196
      if ((cacheTags[i+j].mru & 0x7fffffff) == cacheAssoc - 1) {
 
197
        cacheTags[i+j].mru = 0x80000000;
 
198
        cacheTags[i+j].c = c;
 
199
        cacheTags[i+j].xFrac = (short)xFrac;
 
200
        cacheTags[i+j].yFrac = (short)yFrac;
 
201
        cacheTags[i+j].x = bitmap2.x;
 
202
        cacheTags[i+j].y = bitmap2.y;
 
203
        cacheTags[i+j].w = bitmap2.w;
 
204
        cacheTags[i+j].h = bitmap2.h;
 
205
        p = cache + (i+j) * glyphSize;
 
206
        memcpy(p, bitmap2.data, size);
 
207
      } else {
 
208
        ++cacheTags[i+j].mru;
 
209
      }
 
210
    }
 
211
    *bitmap = bitmap2;
 
212
    bitmap->data = p;
 
213
    bitmap->freeData = gFalse;
 
214
    if (bitmap2.freeData) {
 
215
      gfree(bitmap2.data);
 
216
    }
 
217
  }
 
218
  return gTrue;
 
219
}