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

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

First import

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  SplashCoord 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.