1 //========================================================================
5 //========================================================================
9 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
17 #include FT_INTERNAL_OBJECTS_H // needed for FT_New_Size decl
19 #include "SplashMath.h"
20 #include "SplashGlyphBitmap.h"
21 #include "SplashPath.h"
22 #include "SplashFTFontEngine.h"
23 #include "SplashFTFontFile.h"
24 #include "SplashFTFont.h"
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)((SplashCoord
)1.2 * size
);
118 // compute the transform matrix
120 matrix
.xx
= (FT_Fixed
)((mat
[0] / size
).getRaw());
121 matrix
.yx
= (FT_Fixed
)((mat
[1] / size
).getRaw());
122 matrix
.xy
= (FT_Fixed
)((mat
[2] / size
).getRaw());
123 matrix
.yy
= (FT_Fixed
)((mat
[3] / size
).getRaw());
125 matrix
.xx
= (FT_Fixed
)((mat
[0] / size
) * 65536);
126 matrix
.yx
= (FT_Fixed
)((mat
[1] / size
) * 65536);
127 matrix
.xy
= (FT_Fixed
)((mat
[2] / size
) * 65536);
128 matrix
.yy
= (FT_Fixed
)((mat
[3] / size
) * 65536);
132 SplashFTFont::~SplashFTFont() {
135 GBool
SplashFTFont::getGlyph(int c
, int xFrac
, int yFrac
,
136 SplashGlyphBitmap
*bitmap
) {
137 return SplashFont::getGlyph(c
, xFrac
, 0, bitmap
);
140 GBool
SplashFTFont::makeGlyph(int c
, int xFrac
, int yFrac
,
141 SplashGlyphBitmap
*bitmap
) {
142 SplashFTFontFile
*ff
;
150 ff
= (SplashFTFontFile
*)fontFile
;
152 ff
->face
->size
= sizeObj
;
153 offset
.x
= (FT_Pos
)(int)((SplashCoord
)xFrac
* splashFontFractionMul
* 64);
155 FT_Set_Transform(ff
->face
, &matrix
, &offset
);
156 slot
= ff
->face
->glyph
;
158 if (ff
->codeToGID
&& c
< ff
->codeToGIDLen
) {
159 gid
= (FT_UInt
)ff
->codeToGID
[c
];
164 // if we have the FT2 bytecode interpreter, autohinting won't be used
165 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
166 if (FT_Load_Glyph(ff
->face
, gid
,
167 aa
? FT_LOAD_NO_BITMAP
: FT_LOAD_DEFAULT
)) {
171 // FT2's autohinting doesn't always work very well (especially with
172 // font subsets), so turn it off if anti-aliasing is enabled; if
173 // anti-aliasing is disabled, this seems to be a tossup - some fonts
174 // look better with hinting, some without, so leave hinting on
175 if (FT_Load_Glyph(ff
->face
, gid
,
176 aa
? FT_LOAD_NO_HINTING
| FT_LOAD_NO_BITMAP
177 : FT_LOAD_DEFAULT
)) {
181 if (FT_Render_Glyph(slot
, aa
? ft_render_mode_normal
182 : ft_render_mode_mono
)) {
186 bitmap
->x
= -slot
->bitmap_left
;
187 bitmap
->y
= slot
->bitmap_top
;
188 bitmap
->w
= slot
->bitmap
.width
;
189 bitmap
->h
= slot
->bitmap
.rows
;
194 rowSize
= (bitmap
->w
+ 7) >> 3;
196 bitmap
->data
= (Guchar
*)gmalloc(rowSize
* bitmap
->h
);
197 bitmap
->freeData
= gTrue
;
198 for (i
= 0, p
= bitmap
->data
, q
= slot
->bitmap
.buffer
;
200 ++i
, p
+= rowSize
, q
+= slot
->bitmap
.pitch
) {
201 memcpy(p
, q
, rowSize
);
207 struct SplashFTFontPath
{
212 SplashPath
*SplashFTFont::getGlyphPath(int c
) {
213 static FT_Outline_Funcs outlineFuncs
= {
220 SplashFTFontFile
*ff
;
221 SplashFTFontPath path
;
226 ff
= (SplashFTFontFile
*)fontFile
;
227 ff
->face
->size
= sizeObj
;
228 FT_Set_Transform(ff
->face
, &matrix
, NULL
);
229 slot
= ff
->face
->glyph
;
230 if (ff
->codeToGID
&& c
< ff
->codeToGIDLen
) {
231 gid
= ff
->codeToGID
[c
];
235 if (FT_Load_Glyph(ff
->face
, gid
, FT_LOAD_NO_BITMAP
)) {
238 if (FT_Get_Glyph(slot
, &glyph
)) {
241 path
.path
= new SplashPath();
242 path
.needClose
= gFalse
;
243 FT_Outline_Decompose(&((FT_OutlineGlyph
)glyph
)->outline
,
244 &outlineFuncs
, &path
);
245 if (path
.needClose
) {
248 FT_Done_Glyph(glyph
);
252 static int glyphPathMoveTo(FT_Vector
*pt
, void *path
) {
253 SplashFTFontPath
*p
= (SplashFTFontPath
*)path
;
257 p
->needClose
= gFalse
;
259 p
->path
->moveTo(pt
->x
/ 64.0, -pt
->y
/ 64.0);
263 static int glyphPathLineTo(FT_Vector
*pt
, void *path
) {
264 SplashFTFontPath
*p
= (SplashFTFontPath
*)path
;
266 p
->path
->lineTo(pt
->x
/ 64.0, -pt
->y
/ 64.0);
267 p
->needClose
= gTrue
;
271 static int glyphPathConicTo(FT_Vector
*ctrl
, FT_Vector
*pt
, void *path
) {
272 SplashFTFontPath
*p
= (SplashFTFontPath
*)path
;
273 SplashCoord x0
, y0
, x1
, y1
, x2
, y2
, x3
, y3
, xc
, yc
;
275 if (!p
->path
->getCurPt(&x0
, &y0
)) {
279 yc
= -ctrl
->y
/ 64.0;
283 // A second-order Bezier curve is defined by two endpoints, p0 and
284 // p3, and one control point, pc:
286 // p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3
288 // A third-order Bezier curve is defined by the same two endpoints,
289 // p0 and p3, and two control points, p1 and p2:
291 // p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3
293 // Applying some algebra, we can convert a second-order curve to a
294 // third-order curve:
296 // p1 = (1/3) * (p0 + 2pc)
297 // p2 = (1/3) * (2pc + p3)
299 x1
= (SplashCoord
)(1.0 / 3.0) * (x0
+ (SplashCoord
)2 * xc
);
300 y1
= (SplashCoord
)(1.0 / 3.0) * (y0
+ (SplashCoord
)2 * yc
);
301 x2
= (SplashCoord
)(1.0 / 3.0) * ((SplashCoord
)2 * xc
+ x3
);
302 y2
= (SplashCoord
)(1.0 / 3.0) * ((SplashCoord
)2 * yc
+ y3
);
304 p
->path
->curveTo(x1
, y1
, x2
, y2
, x3
, y3
);
305 p
->needClose
= gTrue
;
309 static int glyphPathCubicTo(FT_Vector
*ctrl1
, FT_Vector
*ctrl2
,
310 FT_Vector
*pt
, void *path
) {
311 SplashFTFontPath
*p
= (SplashFTFontPath
*)path
;
313 p
->path
->curveTo(ctrl1
->x
/ 64.0, -ctrl1
->y
/ 64.0,
314 ctrl2
->x
/ 64.0, -ctrl2
->y
/ 64.0,
315 pt
->x
/ 64.0, -pt
->y
/ 64.0);
316 p
->needClose
= gTrue
;
320 #endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H