source: trunk/poppler/mypoppler/splash/SplashFTFont.cc @ 27

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

poppler updated to version 0.5.2, also needed changes to be compatible with new poppler

File size: 9.6 KB
Line 
1//========================================================================
2//
3// SplashFTFont.cc
4//
5//========================================================================
6
7#include <config.h>
8
9#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
10
11#ifdef USE_GCC_PRAGMAS
12#pragma implementation
13#endif
14
15#define MAKE_VERSION( a,b,c ) (((a) << 16) | ((b) << 8) | (c))
16
17#define FREETYPE_VERSION \
18        MAKE_VERSION(FREETYPE_MAJOR,FREETYPE_MINOR,FREETYPE_PATCH)
19
20#include <ft2build.h>
21#include FT_OUTLINE_H
22#include FT_SIZES_H
23#include FT_GLYPH_H
24#include "goo/gmem.h"
25#include "SplashMath.h"
26#include "SplashGlyphBitmap.h"
27#include "SplashPath.h"
28#include "SplashFTFontEngine.h"
29#include "SplashFTFontFile.h"
30#include "SplashFTFont.h"
31
32//------------------------------------------------------------------------
33
34#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
35static int glyphPathMoveTo(const FT_Vector *pt, void *path);
36static int glyphPathLineTo(const FT_Vector *pt, void *path);
37static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt, void *path);
38static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2,
39                            const FT_Vector *pt, void *path);
40#else
41static int glyphPathMoveTo(FT_Vector *pt, void *path);
42static int glyphPathLineTo(FT_Vector *pt, void *path);
43static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path);
44static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
45                            FT_Vector *pt, void *path);
46#endif
47
48//------------------------------------------------------------------------
49// SplashFTFont
50//------------------------------------------------------------------------
51
52SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA):
53  SplashFont(fontFileA, matA, fontFileA->engine->aa)
54{
55  FT_Face face;
56  double size, div;
57  int x, y;
58
59  face = fontFileA->face;
60  if (FT_New_Size(face, &sizeObj)) {
61    return;
62  }
63  face->size = sizeObj;
64  size = splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]);
65  if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
66    return;
67  }
68
69  div = face->bbox.xMax > 20000 ? 65536 : 1;
70
71  // transform the four corners of the font bounding box -- the min
72  // and max values form the bounding box of the transformed font
73  x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMin) /
74            (div * face->units_per_EM));
75  xMin = xMax = x;
76  y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMin) /
77            (div * face->units_per_EM));
78  yMin = yMax = y;
79  x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMax) /
80            (div * face->units_per_EM));
81  if (x < xMin) {
82    xMin = x;
83  } else if (x > xMax) {
84    xMax = x;
85  }
86  y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMax) /
87            (div * face->units_per_EM));
88  if (y < yMin) {
89    yMin = y;
90  } else if (y > yMax) {
91    yMax = y;
92  }
93  x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMin) /
94            (div * face->units_per_EM));
95  if (x < xMin) {
96    xMin = x;
97  } else if (x > xMax) {
98    xMax = x;
99  }
100  y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMin) /
101            (div * face->units_per_EM));
102  if (y < yMin) {
103    yMin = y;
104  } else if (y > yMax) {
105    yMax = y;
106  }
107  x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMax) /
108            (div * face->units_per_EM));
109  if (x < xMin) {
110    xMin = x;
111  } else if (x > xMax) {
112    xMax = x;
113  }
114  y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMax) /
115            (div * face->units_per_EM));
116  if (y < yMin) {
117    yMin = y;
118  } else if (y > yMax) {
119    yMax = y;
120  }
121  // This is a kludge: some buggy PDF generators embed fonts with
122  // zero bounding boxes.
123  if (xMax == xMin) {
124    xMin = 0;
125    xMax = (int)size;
126  }
127  if (yMax == yMin) {
128    yMin = 0;
129    yMax = (int)((SplashCoord)1.2 * size);
130  }
131
132  // compute the transform matrix
133#if USE_FIXEDPOINT
134  matrix.xx = (FT_Fixed)((mat[0] / size).getRaw());
135  matrix.yx = (FT_Fixed)((mat[1] / size).getRaw());
136  matrix.xy = (FT_Fixed)((mat[2] / size).getRaw());
137  matrix.yy = (FT_Fixed)((mat[3] / size).getRaw());
138#else
139  matrix.xx = (FT_Fixed)((mat[0] / size) * 65536);
140  matrix.yx = (FT_Fixed)((mat[1] / size) * 65536);
141  matrix.xy = (FT_Fixed)((mat[2] / size) * 65536);
142  matrix.yy = (FT_Fixed)((mat[3] / size) * 65536);
143#endif
144}
145
146SplashFTFont::~SplashFTFont() {
147}
148
149GBool SplashFTFont::getGlyph(int c, int xFrac, int yFrac,
150                             SplashGlyphBitmap *bitmap) {
151  return SplashFont::getGlyph(c, xFrac, 0, bitmap);
152}
153
154GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
155                              SplashGlyphBitmap *bitmap) {
156  SplashFTFontFile *ff;
157  FT_Vector offset;
158  FT_GlyphSlot slot;
159  FT_UInt gid;
160  int rowSize;
161  Guchar *p, *q;
162  int i;
163
164  ff = (SplashFTFontFile *)fontFile;
165
166  ff->face->size = sizeObj;
167  offset.x = (FT_Pos)(int)((SplashCoord)xFrac * splashFontFractionMul * 64);
168  offset.y = 0;
169  FT_Set_Transform(ff->face, &matrix, &offset);
170  slot = ff->face->glyph;
171
172  if (ff->codeToGID && c < ff->codeToGIDLen) {
173    gid = (FT_UInt)ff->codeToGID[c];
174  } else {
175    gid = (FT_UInt)c;
176  }
177
178  // if we have the FT2 bytecode interpreter, autohinting won't be used
179#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
180  if (FT_Load_Glyph(ff->face, gid,
181                    aa ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT)) {
182    return gFalse;
183  }
184#else
185  // FT2's autohinting doesn't always work very well (especially with
186  // font subsets), so turn it off if anti-aliasing is enabled; if
187  // anti-aliasing is disabled, this seems to be a tossup - some fonts
188  // look better with hinting, some without, so leave hinting on
189  if (FT_Load_Glyph(ff->face, gid,
190                    aa ? FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP
191                       : FT_LOAD_DEFAULT)) {
192    return gFalse;
193  }
194#endif
195  if (FT_Render_Glyph(slot, aa ? ft_render_mode_normal
196                               : ft_render_mode_mono)) {
197    return gFalse;
198  }
199
200  bitmap->x = -slot->bitmap_left;
201  bitmap->y = slot->bitmap_top;
202  bitmap->w = slot->bitmap.width;
203  bitmap->h = slot->bitmap.rows;
204  bitmap->aa = aa;
205  if (aa) {
206    rowSize = bitmap->w;
207  } else {
208    rowSize = (bitmap->w + 7) >> 3;
209  }
210  bitmap->data = (Guchar *)gmalloc(rowSize * bitmap->h);
211  bitmap->freeData = gTrue;
212  for (i = 0, p = bitmap->data, q = slot->bitmap.buffer;
213       i < bitmap->h;
214       ++i, p += rowSize, q += slot->bitmap.pitch) {
215    memcpy(p, q, rowSize);
216  }
217
218  return gTrue;
219}
220
221struct SplashFTFontPath {
222  SplashPath *path;
223  GBool needClose;
224};
225
226SplashPath *SplashFTFont::getGlyphPath(int c) {
227  static FT_Outline_Funcs outlineFuncs = {
228    &glyphPathMoveTo,
229    &glyphPathLineTo,
230    &glyphPathConicTo,
231    &glyphPathCubicTo,
232    0, 0
233  };
234  SplashFTFontFile *ff;
235  SplashFTFontPath path;
236  FT_GlyphSlot slot;
237  FT_UInt gid;
238  FT_Glyph glyph;
239
240  ff = (SplashFTFontFile *)fontFile;
241  ff->face->size = sizeObj;
242  FT_Set_Transform(ff->face, &matrix, NULL);
243  slot = ff->face->glyph;
244  if (ff->codeToGID && c < ff->codeToGIDLen) {
245    gid = ff->codeToGID[c];
246  } else {
247    gid = (FT_UInt)c;
248  }
249  if (FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP)) {
250    return NULL;
251  }
252  if (FT_Get_Glyph(slot, &glyph)) {
253    return NULL;
254  }
255  path.path = new SplashPath();
256  path.needClose = gFalse;
257  FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
258                       &outlineFuncs, &path);
259  if (path.needClose) {
260    path.path->close();
261  }
262  FT_Done_Glyph(glyph);
263  return path.path;
264}
265
266#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
267static int glyphPathMoveTo(const FT_Vector *pt, void *path)
268#else
269static int glyphPathMoveTo(FT_Vector *pt, void *path)
270#endif
271{
272  SplashFTFontPath *p = (SplashFTFontPath *)path;
273
274  if (p->needClose) {
275    p->path->close();
276    p->needClose = gFalse;
277  }
278  p->path->moveTo(pt->x / 64.0, -pt->y / 64.0);
279  return 0;
280}
281
282#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
283static int glyphPathLineTo(const FT_Vector *pt, void *path)
284#else
285static int glyphPathLineTo(FT_Vector *pt, void *path)
286#endif
287{
288  SplashFTFontPath *p = (SplashFTFontPath *)path;
289
290  p->path->lineTo(pt->x / 64.0, -pt->y / 64.0);
291  p->needClose = gTrue;
292  return 0;
293}
294
295#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
296static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt, void *path)
297#else
298static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path)
299#endif
300{
301  SplashFTFontPath *p = (SplashFTFontPath *)path;
302  SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
303
304  if (!p->path->getCurPt(&x0, &y0)) {
305    return 0;
306  }
307  xc = ctrl->x / 64.0;
308  yc = -ctrl->y / 64.0;
309  x3 = pt->x / 64.0;
310  y3 = -pt->y / 64.0;
311
312  // A second-order Bezier curve is defined by two endpoints, p0 and
313  // p3, and one control point, pc:
314  //
315  //     p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3
316  //
317  // A third-order Bezier curve is defined by the same two endpoints,
318  // p0 and p3, and two control points, p1 and p2:
319  //
320  //     p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3
321  //
322  // Applying some algebra, we can convert a second-order curve to a
323  // third-order curve:
324  //
325  //     p1 = (1/3) * (p0 + 2pc)
326  //     p2 = (1/3) * (2pc + p3)
327
328  x1 = (SplashCoord)(1.0 / 3.0) * (x0 + (SplashCoord)2 * xc);
329  y1 = (SplashCoord)(1.0 / 3.0) * (y0 + (SplashCoord)2 * yc);
330  x2 = (SplashCoord)(1.0 / 3.0) * ((SplashCoord)2 * xc + x3);
331  y2 = (SplashCoord)(1.0 / 3.0) * ((SplashCoord)2 * yc + y3);
332
333  p->path->curveTo(x1, y1, x2, y2, x3, y3);
334  p->needClose = gTrue;
335  return 0;
336}
337
338#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
339static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2, const FT_Vector *pt, void *path)
340#else
341static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2, FT_Vector *pt, void *path)
342#endif
343{
344  SplashFTFontPath *p = (SplashFTFontPath *)path;
345
346  p->path->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0,
347                   ctrl2->x / 64.0, -ctrl2->y / 64.0,
348                   pt->x / 64.0, -pt->y / 64.0);
349  p->needClose = gTrue;
350  return 0;
351}
352
353#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
Note: See TracBrowser for help on using the repository browser.