1 //========================================================================
5 //========================================================================
9 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
15 #include "freetype/ftoutln.h"
16 #include "freetype/internal/ftobjs.h" // needed for FT_New_Size decl
18 #include "SplashMath.h"
19 #include "SplashGlyphBitmap.h"
20 #include "SplashPath.h"
21 #include "SplashFTFontEngine.h"
22 #include "SplashFTFontFile.h"
23 #include "SplashFTFont.h"
25 //------------------------------------------------------------------------
27 static int glyphPathMoveTo(FT_Vector *pt, void *path);
28 static int glyphPathLineTo(FT_Vector *pt, void *path);
29 static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path);
30 static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
31 FT_Vector *pt, void *path);
33 //------------------------------------------------------------------------
35 //------------------------------------------------------------------------
37 SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA):
38 SplashFont(fontFileA, matA, fontFileA->engine->aa)
41 SplashCoord size, div;
44 face = fontFileA->face;
45 if (FT_New_Size(face, &sizeObj)) {
49 size = splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]);
50 if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
54 div = face->bbox.xMax > 20000 ? 65536 : 1;
56 // transform the four corners of the font bounding box -- the min
57 // and max values form the bounding box of the transformed font
58 x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMin) /
59 (div * face->units_per_EM));
61 y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMin) /
62 (div * face->units_per_EM));
64 x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMax) /
65 (div * face->units_per_EM));
68 } else if (x > xMax) {
71 y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMax) /
72 (div * face->units_per_EM));
75 } else if (y > yMax) {
78 x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMin) /
79 (div * face->units_per_EM));
82 } else if (x > xMax) {
85 y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMin) /
86 (div * face->units_per_EM));
89 } else if (y > yMax) {
92 x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMax) /
93 (div * face->units_per_EM));
96 } else if (x > xMax) {
99 y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMax) /
100 (div * face->units_per_EM));
103 } else if (y > yMax) {
106 // This is a kludge: some buggy PDF generators embed fonts with
107 // zero bounding boxes.
114 yMax = (int)(1.2 * size);
117 // compute the transform matrix
118 matrix.xx = (FT_Fixed)((mat[0] / size) * 65536);
119 matrix.yx = (FT_Fixed)((mat[1] / size) * 65536);
120 matrix.xy = (FT_Fixed)((mat[2] / size) * 65536);
121 matrix.yy = (FT_Fixed)((mat[3] / size) * 65536);
124 SplashFTFont::~SplashFTFont() {
127 GBool SplashFTFont::getGlyph(int c, int xFrac, int yFrac,
128 SplashGlyphBitmap *bitmap) {
129 return SplashFont::getGlyph(c, xFrac, 0, bitmap);
132 GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
133 SplashGlyphBitmap *bitmap) {
134 SplashFTFontFile *ff;
142 ff = (SplashFTFontFile *)fontFile;
144 ff->face->size = sizeObj;
145 offset.x = (FT_Pos)(xFrac * splashFontFractionMul * 64);
147 FT_Set_Transform(ff->face, &matrix, &offset);
148 slot = ff->face->glyph;
150 if (ff->codeToGID && c < ff->codeToGIDLen) {
151 gid = (FT_UInt)ff->codeToGID[c];
156 // if we have the FT2 bytecode interpreter, autohinting won't be used
157 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
158 if (FT_Load_Glyph(ff->face, gid,
159 aa ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT)) {
163 // FT2's autohinting doesn't always work very well (especially with
164 // font subsets), so turn it off if anti-aliasing is enabled; if
165 // anti-aliasing is disabled, this seems to be a tossup - some fonts
166 // look better with hinting, some without, so leave hinting on
167 if (FT_Load_Glyph(ff->face, gid,
168 aa ? FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP
169 : FT_LOAD_DEFAULT)) {
173 if (FT_Render_Glyph(slot, aa ? ft_render_mode_normal
174 : ft_render_mode_mono)) {
178 bitmap->x = -slot->bitmap_left;
179 bitmap->y = slot->bitmap_top;
180 bitmap->w = slot->bitmap.width;
181 bitmap->h = slot->bitmap.rows;
186 rowSize = (bitmap->w + 7) >> 3;
188 bitmap->data = (Guchar *)gmalloc(rowSize * bitmap->h);
189 bitmap->freeData = gTrue;
190 for (i = 0, p = bitmap->data, q = slot->bitmap.buffer;
192 ++i, p += rowSize, q += slot->bitmap.pitch) {
193 memcpy(p, q, rowSize);
199 SplashPath *SplashFTFont::getGlyphPath(int c) {
200 static FT_Outline_Funcs outlineFuncs = {
207 SplashFTFontFile *ff;
213 ff = (SplashFTFontFile *)fontFile;
214 ff->face->size = sizeObj;
215 FT_Set_Transform(ff->face, &matrix, NULL);
216 slot = ff->face->glyph;
217 if (ff->codeToGID && c < ff->codeToGIDLen) {
218 gid = ff->codeToGID[c];
222 if (FT_Load_Glyph(ff->face, gid, FT_LOAD_DEFAULT)) {
225 if (FT_Get_Glyph(slot, &glyph)) {
228 path = new SplashPath();
229 FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
230 &outlineFuncs, path);
234 static int glyphPathMoveTo(FT_Vector *pt, void *path) {
235 ((SplashPath *)path)->moveTo(pt->x / 64.0, -pt->y / 64.0);
239 static int glyphPathLineTo(FT_Vector *pt, void *path) {
240 ((SplashPath *)path)->lineTo(pt->x / 64.0, -pt->y / 64.0);
244 static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path) {
245 SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
247 if (!((SplashPath *)path)->getCurPt(&x0, &y0)) {
251 yc = -ctrl->y / 64.0;
255 // A second-order Bezier curve is defined by two endpoints, p0 and
256 // p3, and one control point, pc:
258 // p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3
260 // A third-order Bezier curve is defined by the same two endpoints,
261 // p0 and p3, and two control points, p1 and p2:
263 // p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3
265 // Applying some algebra, we can convert a second-order curve to a
266 // third-order curve:
268 // p1 = (1/3) * (p0 + 2pc)
269 // p2 = (1/3) * (2pc + p3)
271 x1 = (1.0 / 3.0) * (x0 + 2 * xc);
272 y1 = (1.0 / 3.0) * (y0 + 2 * yc);
273 x2 = (1.0 / 3.0) * (2 * xc + x3);
274 y2 = (1.0 / 3.0) * (2 * yc + y3);
276 ((SplashPath *)path)->curveTo(x1, y1, x2, y2, x3, y3);
280 static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
281 FT_Vector *pt, void *path) {
282 ((SplashPath *)path)->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0,
283 ctrl2->x / 64.0, -ctrl2->y / 64.0,
284 pt->x / 64.0, -pt->y / 64.0);
288 #endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H