1 //========================================================================
5 //========================================================================
9 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
16 #include "SplashMath.h"
17 #include "SplashGlyphBitmap.h"
18 #include "SplashPath.h"
19 #include "SplashFTFontEngine.h"
20 #include "SplashFTFontFile.h"
21 #include "SplashFTFont.h"
24 #include FT_INTERNAL_OBJECTS_H // needed for FT_New_Size decl
26 //------------------------------------------------------------------------
28 static int glyphPathMoveTo(FT_Vector *pt, void *path);
29 static int glyphPathLineTo(FT_Vector *pt, void *path);
30 static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path);
31 static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
32 FT_Vector *pt, void *path);
34 //------------------------------------------------------------------------
36 //------------------------------------------------------------------------
38 SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA):
39 SplashFont(fontFileA, matA, fontFileA->engine->aa)
42 SplashCoord size, div;
45 face = fontFileA->face;
46 if (FT_New_Size(face, &sizeObj)) {
50 size = splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]);
51 if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
55 div = face->bbox.xMax > 20000 ? 65536 : 1;
57 // transform the four corners of the font bounding box -- the min
58 // and max values form the bounding box of the transformed font
59 x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMin) /
60 (div * face->units_per_EM));
62 y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMin) /
63 (div * face->units_per_EM));
65 x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMax) /
66 (div * face->units_per_EM));
69 } else if (x > xMax) {
72 y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMax) /
73 (div * face->units_per_EM));
76 } else if (y > yMax) {
79 x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMin) /
80 (div * face->units_per_EM));
83 } else if (x > xMax) {
86 y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMin) /
87 (div * face->units_per_EM));
90 } else if (y > yMax) {
93 x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMax) /
94 (div * face->units_per_EM));
97 } else if (x > xMax) {
100 y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMax) /
101 (div * face->units_per_EM));
104 } else if (y > yMax) {
107 // This is a kludge: some buggy PDF generators embed fonts with
108 // zero bounding boxes.
115 yMax = (int)(1.2 * size);
118 // compute the transform matrix
119 matrix.xx = (FT_Fixed)((mat[0] / size) * 65536);
120 matrix.yx = (FT_Fixed)((mat[1] / size) * 65536);
121 matrix.xy = (FT_Fixed)((mat[2] / size) * 65536);
122 matrix.yy = (FT_Fixed)((mat[3] / size) * 65536);
125 SplashFTFont::~SplashFTFont() {
128 GBool SplashFTFont::getGlyph(int c, int xFrac, int yFrac,
129 SplashGlyphBitmap *bitmap) {
130 return SplashFont::getGlyph(c, xFrac, 0, bitmap);
133 GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
134 SplashGlyphBitmap *bitmap) {
135 SplashFTFontFile *ff;
143 ff = (SplashFTFontFile *)fontFile;
145 ff->face->size = sizeObj;
146 offset.x = (FT_Pos)(xFrac * splashFontFractionMul * 64);
148 FT_Set_Transform(ff->face, &matrix, &offset);
149 slot = ff->face->glyph;
151 if (ff->codeToGID && c < ff->codeToGIDLen) {
152 gid = (FT_UInt)ff->codeToGID[c];
157 // if we have the FT2 bytecode interpreter, autohinting won't be used
158 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
159 if (FT_Load_Glyph(ff->face, gid,
160 aa ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT)) {
164 // FT2's autohinting doesn't always work very well (especially with
165 // font subsets), so turn it off if anti-aliasing is enabled; if
166 // anti-aliasing is disabled, this seems to be a tossup - some fonts
167 // look better with hinting, some without, so leave hinting on
168 if (FT_Load_Glyph(ff->face, gid,
169 aa ? FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP
170 : FT_LOAD_DEFAULT)) {
174 if (FT_Render_Glyph(slot, aa ? ft_render_mode_normal
175 : ft_render_mode_mono)) {
179 bitmap->x = -slot->bitmap_left;
180 bitmap->y = slot->bitmap_top;
181 bitmap->w = slot->bitmap.width;
182 bitmap->h = slot->bitmap.rows;
187 rowSize = (bitmap->w + 7) >> 3;
189 bitmap->data = (Guchar *)gmalloc(rowSize * bitmap->h);
190 bitmap->freeData = gTrue;
191 for (i = 0, p = bitmap->data, q = slot->bitmap.buffer;
193 ++i, p += rowSize, q += slot->bitmap.pitch) {
194 memcpy(p, q, rowSize);
200 SplashPath *SplashFTFont::getGlyphPath(int c) {
201 static FT_Outline_Funcs outlineFuncs = {
208 SplashFTFontFile *ff;
214 ff = (SplashFTFontFile *)fontFile;
215 ff->face->size = sizeObj;
216 FT_Set_Transform(ff->face, &matrix, NULL);
217 slot = ff->face->glyph;
218 if (ff->codeToGID && c < ff->codeToGIDLen) {
219 gid = ff->codeToGID[c];
223 if (FT_Load_Glyph(ff->face, gid, FT_LOAD_DEFAULT)) {
226 if (FT_Get_Glyph(slot, &glyph)) {
229 path = new SplashPath();
230 FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
231 &outlineFuncs, path);
235 static int glyphPathMoveTo(FT_Vector *pt, void *path) {
236 ((SplashPath *)path)->moveTo(pt->x / 64.0, -pt->y / 64.0);
240 static int glyphPathLineTo(FT_Vector *pt, void *path) {
241 ((SplashPath *)path)->lineTo(pt->x / 64.0, -pt->y / 64.0);
245 static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path) {
246 SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
248 if (!((SplashPath *)path)->getCurPt(&x0, &y0)) {
252 yc = -ctrl->y / 64.0;
256 // A second-order Bezier curve is defined by two endpoints, p0 and
257 // p3, and one control point, pc:
259 // p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3
261 // A third-order Bezier curve is defined by the same two endpoints,
262 // p0 and p3, and two control points, p1 and p2:
264 // p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3
266 // Applying some algebra, we can convert a second-order curve to a
267 // third-order curve:
269 // p1 = (1/3) * (p0 + 2pc)
270 // p2 = (1/3) * (2pc + p3)
272 x1 = (1.0 / 3.0) * (x0 + 2 * xc);
273 y1 = (1.0 / 3.0) * (y0 + 2 * yc);
274 x2 = (1.0 / 3.0) * (2 * xc + x3);
275 y2 = (1.0 / 3.0) * (2 * yc + y3);
277 ((SplashPath *)path)->curveTo(x1, y1, x2, y2, x3, y3);
281 static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
282 FT_Vector *pt, void *path) {
283 ((SplashPath *)path)->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0,
284 ctrl2->x / 64.0, -ctrl2->y / 64.0,
285 pt->x / 64.0, -pt->y / 64.0);
289 #endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H