2 * Copyright (C) 2009 Red Hat, Inc.
3 * Copyright (C) 2009 Keith Stribley <devel@thanlwinsoft.org>
5 * This is part of HarfBuzz, a text shaping library.
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25 * Red Hat Author(s): Behdad Esfahbod
28 #include "hb-private.h"
32 #include "hb-font-private.h"
34 #include FT_TRUETYPE_TABLES_H
40 hb_ft_get_glyph (hb_font_t
*font HB_UNUSED
,
41 hb_face_t
*face HB_UNUSED
,
42 const void *user_data
,
43 hb_codepoint_t unicode
,
44 hb_codepoint_t variation_selector
)
46 FT_Face ft_face
= (FT_Face
) user_data
;
48 #ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
49 if (unlikely (variation_selector
)) {
50 hb_codepoint_t glyph
= FT_Face_GetCharVariantIndex (ft_face
, unicode
, variation_selector
);
56 return FT_Get_Char_Index (ft_face
, unicode
);
60 hb_ft_get_glyph_advance (hb_font_t
*font HB_UNUSED
,
61 hb_face_t
*face HB_UNUSED
,
62 const void *user_data
,
64 hb_position_t
*x_advance
,
65 hb_position_t
*y_advance
)
67 FT_Face ft_face
= (FT_Face
) user_data
;
68 int load_flags
= FT_LOAD_DEFAULT
;
70 /* TODO: load_flags, embolden, etc */
72 if (likely (!FT_Load_Glyph (ft_face
, glyph
, load_flags
)))
74 *x_advance
= ft_face
->glyph
->advance
.x
;
75 *y_advance
= ft_face
->glyph
->advance
.y
;
80 hb_ft_get_glyph_extents (hb_font_t
*font HB_UNUSED
,
81 hb_face_t
*face HB_UNUSED
,
82 const void *user_data
,
84 hb_glyph_extents_t
*extents
)
86 FT_Face ft_face
= (FT_Face
) user_data
;
87 int load_flags
= FT_LOAD_DEFAULT
;
89 /* TODO: load_flags, embolden, etc */
91 if (likely (!FT_Load_Glyph (ft_face
, glyph
, load_flags
)))
93 /* XXX: A few negations should be in order here, not sure. */
94 extents
->x_bearing
= ft_face
->glyph
->metrics
.horiBearingX
;
95 extents
->y_bearing
= ft_face
->glyph
->metrics
.horiBearingY
;
96 extents
->width
= ft_face
->glyph
->metrics
.width
;
97 extents
->height
= ft_face
->glyph
->metrics
.height
;
102 hb_ft_get_contour_point (hb_font_t
*font HB_UNUSED
,
103 hb_face_t
*face HB_UNUSED
,
104 const void *user_data
,
105 unsigned int point_index
,
106 hb_codepoint_t glyph
,
110 FT_Face ft_face
= (FT_Face
) user_data
;
111 int load_flags
= FT_LOAD_DEFAULT
;
113 /* TODO: load_flags, embolden, etc */
115 if (unlikely (FT_Load_Glyph (ft_face
, glyph
, load_flags
)))
118 if (unlikely (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
))
121 if (unlikely (point_index
>= (unsigned int) ft_face
->glyph
->outline
.n_points
))
124 *x
= ft_face
->glyph
->outline
.points
[point_index
].x
;
125 *y
= ft_face
->glyph
->outline
.points
[point_index
].y
;
131 hb_ft_get_kerning (hb_font_t
*font HB_UNUSED
,
132 hb_face_t
*face HB_UNUSED
,
133 const void *user_data
,
134 hb_codepoint_t first_glyph
,
135 hb_codepoint_t second_glyph
)
137 FT_Face ft_face
= (FT_Face
) user_data
;
140 /* TODO: Kern type? */
141 if (FT_Get_Kerning (ft_face
, first_glyph
, second_glyph
, FT_KERNING_DEFAULT
, &kerning
))
147 static hb_font_funcs_t ft_ffuncs
= {
148 HB_REFERENCE_COUNT_INVALID
, /* ref_count */
149 TRUE
, /* immutable */
152 hb_ft_get_glyph_advance
,
153 hb_ft_get_glyph_extents
,
154 hb_ft_get_contour_point
,
160 hb_ft_get_font_funcs (void)
167 get_table (hb_tag_t tag
, void *user_data
)
169 FT_Face ft_face
= (FT_Face
) user_data
;
174 if (unlikely (tag
== HB_TAG_NONE
))
177 error
= FT_Load_Sfnt_Table (ft_face
, tag
, 0, NULL
, &length
);
181 /* TODO Use FT_Memory? */
182 buffer
= (FT_Byte
*) malloc (length
);
186 error
= FT_Load_Sfnt_Table (ft_face
, tag
, 0, buffer
, &length
);
190 return hb_blob_create ((const char *) buffer
, length
,
191 HB_MEMORY_MODE_WRITABLE
,
197 hb_ft_face_create (FT_Face ft_face
,
198 hb_destroy_func_t destroy
)
202 if (ft_face
->stream
->read
== NULL
) {
205 blob
= hb_blob_create ((const char *) ft_face
->stream
->base
,
206 (unsigned int) ft_face
->stream
->size
,
207 /* TODO: Check FT_FACE_FLAG_EXTERNAL_STREAM? */
208 HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE
,
210 face
= hb_face_create_for_data (blob
, ft_face
->face_index
);
211 hb_blob_destroy (blob
);
213 face
= hb_face_create_for_tables (get_table
, destroy
, ft_face
);
220 hb_ft_face_finalize (FT_Face ft_face
)
222 hb_face_destroy ((hb_face_t
*) ft_face
->generic
.data
);
226 hb_ft_face_create_cached (FT_Face ft_face
)
228 if (unlikely (!ft_face
->generic
.data
|| ft_face
->generic
.finalizer
!= (FT_Generic_Finalizer
) hb_ft_face_finalize
))
230 if (ft_face
->generic
.finalizer
)
231 ft_face
->generic
.finalizer (ft_face
);
233 ft_face
->generic
.data
= hb_ft_face_create (ft_face
, NULL
);
234 ft_face
->generic
.finalizer
= (FT_Generic_Finalizer
) hb_ft_face_finalize
;
237 return hb_face_reference ((hb_face_t
*) ft_face
->generic
.data
);
242 hb_ft_font_create (FT_Face ft_face
,
243 hb_destroy_func_t destroy
)
247 font
= hb_font_create ();
248 hb_font_set_funcs (font
,
249 hb_ft_get_font_funcs (),
251 hb_font_set_scale (font
,
252 ((uint64_t) ft_face
->size
->metrics
.x_scale
* (uint64_t) ft_face
->units_per_EM
) >> 16,
253 ((uint64_t) ft_face
->size
->metrics
.y_scale
* (uint64_t) ft_face
->units_per_EM
) >> 16);
254 hb_font_set_ppem (font
,
255 ft_face
->size
->metrics
.x_ppem
,
256 ft_face
->size
->metrics
.y_ppem
);