| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright © 2009 Red Hat, Inc. | 2 * Copyright © 2009 Red Hat, Inc. |
| 3 * Copyright © 2009 Keith Stribley | 3 * Copyright © 2009 Keith Stribley |
| 4 * Copyright © 2015 Google, Inc. |
| 4 * | 5 * |
| 5 * This is part of HarfBuzz, a text shaping library. | 6 * This is part of HarfBuzz, a text shaping library. |
| 6 * | 7 * |
| 7 * Permission is hereby granted, without written agreement and without | 8 * Permission is hereby granted, without written agreement and without |
| 8 * license or royalty fees, to use, copy, modify, and distribute this | 9 * license or royalty fees, to use, copy, modify, and distribute this |
| 9 * software and its documentation for any purpose, provided that the | 10 * software and its documentation for any purpose, provided that the |
| 10 * above copyright notice and the following two paragraphs appear in | 11 * above copyright notice and the following two paragraphs appear in |
| 11 * all copies of this software. | 12 * all copies of this software. |
| 12 * | 13 * |
| 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 14 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | 16 * 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 | 17 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 17 * DAMAGE. | 18 * DAMAGE. |
| 18 * | 19 * |
| 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 20 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 21 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | 22 * 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 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 24 * | 25 * |
| 25 * Red Hat Author(s): Behdad Esfahbod | 26 * Red Hat Author(s): Behdad Esfahbod |
| 27 * Google Author(s): Behdad Esfahbod |
| 26 */ | 28 */ |
| 27 | 29 |
| 28 #include "hb-private.hh" | 30 #include "hb-private.hh" |
| 29 | 31 |
| 30 #include "hb-ft.h" | 32 #include "hb-ft.h" |
| 31 | 33 |
| 32 #include "hb-font-private.hh" | 34 #include "hb-font-private.hh" |
| 33 | 35 |
| 34 #include FT_ADVANCES_H | 36 #include FT_ADVANCES_H |
| 35 #include FT_TRUETYPE_TABLES_H | 37 #include FT_TRUETYPE_TABLES_H |
| 36 | 38 |
| 37 | 39 |
| 38 | 40 |
| 39 #ifndef HB_DEBUG_FT | 41 #ifndef HB_DEBUG_FT |
| 40 #define HB_DEBUG_FT (HB_DEBUG+0) | 42 #define HB_DEBUG_FT (HB_DEBUG+0) |
| 41 #endif | 43 #endif |
| 42 | 44 |
| 43 | 45 |
| 44 /* TODO: | 46 /* TODO: |
| 45 * | 47 * |
| 46 * In general, this file does a fine job of what it's supposed to do. | 48 * In general, this file does a fine job of what it's supposed to do. |
| 47 * There are, however, things that need more work: | 49 * There are, however, things that need more work: |
| 48 * | 50 * |
| 49 * - We don't handle any load_flags. That definitely has API implications. :( | 51 * - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be bugg
y. |
| 50 * I believe hb_ft_font_create() should take load_flags input. | 52 * Have not investigated. |
| 51 * In particular, FT_Get_Advance() without the NO_HINTING flag seems to be | |
| 52 * buggy. | |
| 53 * | 53 * |
| 54 * FreeType works in 26.6 mode. Clients can decide to use that mode, and ev
erything | 54 * - FreeType works in 26.6 mode. Clients can decide to use that mode, and ev
erything |
| 55 * would work fine. However, we also abuse this API for performing in font-
space, | 55 * would work fine. However, we also abuse this API for performing in font-
space, |
| 56 * but don't pass the correct flags to FreeType. We just abuse the no-hinti
ng mode | 56 * but don't pass the correct flags to FreeType. We just abuse the no-hinti
ng mode |
| 57 * for that, such that no rounding etc happens. As such, we don't set ppem,
and | 57 * for that, such that no rounding etc happens. As such, we don't set ppem,
and |
| 58 * pass NO_HINTING around. This seems to work best, until we go ahead and a
dd a full | 58 * pass NO_HINTING as load_flags. Would be much better to use NO_SCALE, and
scale |
| 59 * load_flags API. | 59 * ourselves, like we do in uniscribe, etc. |
| 60 * | 60 * |
| 61 * - We don't handle / allow for emboldening / obliqueing. | 61 * - We don't handle / allow for emboldening / obliqueing. |
| 62 * | 62 * |
| 63 * - In the future, we should add constructors to create fonts in font space? | 63 * - In the future, we should add constructors to create fonts in font space? |
| 64 * | 64 * |
| 65 * - FT_Load_Glyph() is exteremely costly. Do something about it? | 65 * - FT_Load_Glyph() is exteremely costly. Do something about it? |
| 66 */ | 66 */ |
| 67 | 67 |
| 68 | 68 |
| 69 struct hb_ft_font_t |
| 70 { |
| 71 FT_Face ft_face; |
| 72 int load_flags; |
| 73 bool unref; /* Whether to destroy ft_face when done. */ |
| 74 }; |
| 75 |
| 76 static hb_ft_font_t * |
| 77 _hb_ft_font_create (FT_Face ft_face, bool unref) |
| 78 { |
| 79 hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); |
| 80 |
| 81 if (unlikely (!ft_font)) |
| 82 return NULL; |
| 83 |
| 84 ft_font->ft_face = ft_face; |
| 85 ft_font->unref = unref; |
| 86 |
| 87 ft_font->load_flags = FT_LOAD_DEFAULT; |
| 88 |
| 89 return ft_font; |
| 90 } |
| 91 |
| 92 static void |
| 93 _hb_ft_font_destroy (hb_ft_font_t *ft_font) |
| 94 { |
| 95 if (ft_font->unref) |
| 96 FT_Done_Face (ft_font->ft_face); |
| 97 |
| 98 free (ft_font); |
| 99 } |
| 100 |
| 101 /** |
| 102 * hb_ft_font_set_load_flags: |
| 103 * @font: |
| 104 * @load_flags: |
| 105 * |
| 106 * |
| 107 * |
| 108 * Since: 1.0.5 |
| 109 **/ |
| 110 void |
| 111 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) |
| 112 { |
| 113 if (font->immutable) |
| 114 return; |
| 115 |
| 116 if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) |
| 117 return; |
| 118 |
| 119 hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; |
| 120 |
| 121 ft_font->load_flags = load_flags; |
| 122 } |
| 123 |
| 124 /** |
| 125 * hb_ft_font_get_load_flags: |
| 126 * @font: |
| 127 * |
| 128 * |
| 129 * |
| 130 * Return value: |
| 131 * Since: 1.0.5 |
| 132 **/ |
| 133 int |
| 134 hb_ft_font_get_load_flags (hb_font_t *font) |
| 135 { |
| 136 if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) |
| 137 return 0; |
| 138 |
| 139 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; |
| 140 |
| 141 return ft_font->load_flags; |
| 142 } |
| 143 |
| 144 FT_Face |
| 145 hb_ft_font_get_face (hb_font_t *font) |
| 146 { |
| 147 if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) |
| 148 return NULL; |
| 149 |
| 150 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; |
| 151 |
| 152 return ft_font->ft_face; |
| 153 } |
| 154 |
| 155 |
| 156 |
| 69 static hb_bool_t | 157 static hb_bool_t |
| 70 hb_ft_get_glyph (hb_font_t *font HB_UNUSED, | 158 hb_ft_get_glyph (hb_font_t *font HB_UNUSED, |
| 71 void *font_data, | 159 void *font_data, |
| 72 hb_codepoint_t unicode, | 160 hb_codepoint_t unicode, |
| 73 hb_codepoint_t variation_selector, | 161 hb_codepoint_t variation_selector, |
| 74 hb_codepoint_t *glyph, | 162 hb_codepoint_t *glyph, |
| 75 void *user_data HB_UNUSED) | 163 void *user_data HB_UNUSED) |
| 76 | 164 |
| 77 { | 165 { |
| 166 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 78 unsigned int g; | 167 unsigned int g; |
| 79 FT_Face ft_face = (FT_Face) font_data; | |
| 80 | 168 |
| 81 if (likely (!variation_selector)) | 169 if (likely (!variation_selector)) |
| 82 g = FT_Get_Char_Index (ft_face, unicode); | 170 g = FT_Get_Char_Index (ft_font->ft_face, unicode); |
| 83 else | 171 else |
| 84 g = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector); | 172 g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_select
or); |
| 85 | 173 |
| 86 if (unlikely (!g)) | 174 if (unlikely (!g)) |
| 87 return false; | 175 return false; |
| 88 | 176 |
| 89 *glyph = g; | 177 *glyph = g; |
| 90 return true; | 178 return true; |
| 91 } | 179 } |
| 92 | 180 |
| 93 static hb_position_t | 181 static hb_position_t |
| 94 hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED, | 182 hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED, |
| 95 void *font_data, | 183 void *font_data, |
| 96 hb_codepoint_t glyph, | 184 hb_codepoint_t glyph, |
| 97 void *user_data HB_UNUSED) | 185 void *user_data HB_UNUSED) |
| 98 { | 186 { |
| 99 FT_Face ft_face = (FT_Face) font_data; | 187 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 100 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; | |
| 101 FT_Fixed v; | 188 FT_Fixed v; |
| 102 | 189 |
| 103 if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) | 190 if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v
))) |
| 104 return 0; | 191 return 0; |
| 105 | 192 |
| 106 if (font->x_scale < 0) | 193 if (font->x_scale < 0) |
| 107 v = -v; | 194 v = -v; |
| 108 | 195 |
| 109 return (v + (1<<9)) >> 10; | 196 return (v + (1<<9)) >> 10; |
| 110 } | 197 } |
| 111 | 198 |
| 112 static hb_position_t | 199 static hb_position_t |
| 113 hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED, | 200 hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED, |
| 114 void *font_data, | 201 void *font_data, |
| 115 hb_codepoint_t glyph, | 202 hb_codepoint_t glyph, |
| 116 void *user_data HB_UNUSED) | 203 void *user_data HB_UNUSED) |
| 117 { | 204 { |
| 118 FT_Face ft_face = (FT_Face) font_data; | 205 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 119 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOU
T; | |
| 120 FT_Fixed v; | 206 FT_Fixed v; |
| 121 | 207 |
| 122 if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) | 208 if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | F
T_LOAD_VERTICAL_LAYOUT, &v))) |
| 123 return 0; | 209 return 0; |
| 124 | 210 |
| 125 if (font->y_scale < 0) | 211 if (font->y_scale < 0) |
| 126 v = -v; | 212 v = -v; |
| 127 | 213 |
| 128 /* Note: FreeType's vertical metrics grows downward while other FreeType coord
inates | 214 /* Note: FreeType's vertical metrics grows downward while other FreeType coord
inates |
| 129 * have a Y growing upward. Hence the extra negation. */ | 215 * have a Y growing upward. Hence the extra negation. */ |
| 130 return (-v + (1<<9)) >> 10; | 216 return (-v + (1<<9)) >> 10; |
| 131 } | 217 } |
| 132 | 218 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 143 } | 229 } |
| 144 | 230 |
| 145 static hb_bool_t | 231 static hb_bool_t |
| 146 hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, | 232 hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, |
| 147 void *font_data, | 233 void *font_data, |
| 148 hb_codepoint_t glyph, | 234 hb_codepoint_t glyph, |
| 149 hb_position_t *x, | 235 hb_position_t *x, |
| 150 hb_position_t *y, | 236 hb_position_t *y, |
| 151 void *user_data HB_UNUSED) | 237 void *user_data HB_UNUSED) |
| 152 { | 238 { |
| 153 FT_Face ft_face = (FT_Face) font_data; | 239 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 154 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; | 240 FT_Face ft_face = ft_font->ft_face; |
| 155 | 241 |
| 156 if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) | 242 if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) |
| 157 return false; | 243 return false; |
| 158 | 244 |
| 159 /* Note: FreeType's vertical metrics grows downward while other FreeType coord
inates | 245 /* Note: FreeType's vertical metrics grows downward while other FreeType coord
inates |
| 160 * have a Y growing upward. Hence the extra negation. */ | 246 * have a Y growing upward. Hence the extra negation. */ |
| 161 *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBear
ingX; | 247 *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBear
ingX; |
| 162 *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBear
ingY); | 248 *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBear
ingY); |
| 163 | 249 |
| 164 if (font->x_scale < 0) | 250 if (font->x_scale < 0) |
| 165 *x = -*x; | 251 *x = -*x; |
| 166 if (font->y_scale < 0) | 252 if (font->y_scale < 0) |
| 167 *y = -*y; | 253 *y = -*y; |
| 168 | 254 |
| 169 return true; | 255 return true; |
| 170 } | 256 } |
| 171 | 257 |
| 172 static hb_position_t | 258 static hb_position_t |
| 173 hb_ft_get_glyph_h_kerning (hb_font_t *font, | 259 hb_ft_get_glyph_h_kerning (hb_font_t *font, |
| 174 void *font_data, | 260 void *font_data, |
| 175 hb_codepoint_t left_glyph, | 261 hb_codepoint_t left_glyph, |
| 176 hb_codepoint_t right_glyph, | 262 hb_codepoint_t right_glyph, |
| 177 void *user_data HB_UNUSED) | 263 void *user_data HB_UNUSED) |
| 178 { | 264 { |
| 179 FT_Face ft_face = (FT_Face) font_data; | 265 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 180 FT_Vector kerningv; | 266 FT_Vector kerningv; |
| 181 | 267 |
| 182 FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED
; | 268 FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED
; |
| 183 if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, mode, &kerningv)) | 269 if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv
)) |
| 184 return 0; | 270 return 0; |
| 185 | 271 |
| 186 return kerningv.x; | 272 return kerningv.x; |
| 187 } | 273 } |
| 188 | 274 |
| 189 static hb_position_t | 275 static hb_position_t |
| 190 hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, | 276 hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, |
| 191 void *font_data HB_UNUSED, | 277 void *font_data HB_UNUSED, |
| 192 hb_codepoint_t top_glyph HB_UNUSED, | 278 hb_codepoint_t top_glyph HB_UNUSED, |
| 193 hb_codepoint_t bottom_glyph HB_UNUSED, | 279 hb_codepoint_t bottom_glyph HB_UNUSED, |
| 194 void *user_data HB_UNUSED) | 280 void *user_data HB_UNUSED) |
| 195 { | 281 { |
| 196 /* FreeType API doesn't support vertical kerning */ | 282 /* FreeType API doesn't support vertical kerning */ |
| 197 return 0; | 283 return 0; |
| 198 } | 284 } |
| 199 | 285 |
| 200 static hb_bool_t | 286 static hb_bool_t |
| 201 hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED, | 287 hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED, |
| 202 void *font_data, | 288 void *font_data, |
| 203 hb_codepoint_t glyph, | 289 hb_codepoint_t glyph, |
| 204 hb_glyph_extents_t *extents, | 290 hb_glyph_extents_t *extents, |
| 205 void *user_data HB_UNUSED) | 291 void *user_data HB_UNUSED) |
| 206 { | 292 { |
| 207 FT_Face ft_face = (FT_Face) font_data; | 293 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 208 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; | 294 FT_Face ft_face = ft_font->ft_face; |
| 209 | 295 |
| 210 if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) | 296 if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) |
| 211 return false; | 297 return false; |
| 212 | 298 |
| 213 extents->x_bearing = ft_face->glyph->metrics.horiBearingX; | 299 extents->x_bearing = ft_face->glyph->metrics.horiBearingX; |
| 214 extents->y_bearing = ft_face->glyph->metrics.horiBearingY; | 300 extents->y_bearing = ft_face->glyph->metrics.horiBearingY; |
| 215 extents->width = ft_face->glyph->metrics.width; | 301 extents->width = ft_face->glyph->metrics.width; |
| 216 extents->height = -ft_face->glyph->metrics.height; | 302 extents->height = -ft_face->glyph->metrics.height; |
| 217 return true; | 303 return true; |
| 218 } | 304 } |
| 219 | 305 |
| 220 static hb_bool_t | 306 static hb_bool_t |
| 221 hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED, | 307 hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED, |
| 222 void *font_data, | 308 void *font_data, |
| 223 hb_codepoint_t glyph, | 309 hb_codepoint_t glyph, |
| 224 unsigned int point_index, | 310 unsigned int point_index, |
| 225 hb_position_t *x, | 311 hb_position_t *x, |
| 226 hb_position_t *y, | 312 hb_position_t *y, |
| 227 void *user_data HB_UNUSED) | 313 void *user_data HB_UNUSED) |
| 228 { | 314 { |
| 229 FT_Face ft_face = (FT_Face) font_data; | 315 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 230 int load_flags = FT_LOAD_DEFAULT; | 316 FT_Face ft_face = ft_font->ft_face; |
| 231 | 317 |
| 232 if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) | 318 if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) |
| 233 return false; | 319 return false; |
| 234 | 320 |
| 235 if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)) | 321 if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)) |
| 236 return false; | 322 return false; |
| 237 | 323 |
| 238 if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points)) | 324 if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points)) |
| 239 return false; | 325 return false; |
| 240 | 326 |
| 241 *x = ft_face->glyph->outline.points[point_index].x; | 327 *x = ft_face->glyph->outline.points[point_index].x; |
| 242 *y = ft_face->glyph->outline.points[point_index].y; | 328 *y = ft_face->glyph->outline.points[point_index].y; |
| 243 | 329 |
| 244 return true; | 330 return true; |
| 245 } | 331 } |
| 246 | 332 |
| 247 static hb_bool_t | 333 static hb_bool_t |
| 248 hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED, | 334 hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED, |
| 249 void *font_data, | 335 void *font_data, |
| 250 hb_codepoint_t glyph, | 336 hb_codepoint_t glyph, |
| 251 char *name, unsigned int size, | 337 char *name, unsigned int size, |
| 252 void *user_data HB_UNUSED) | 338 void *user_data HB_UNUSED) |
| 253 { | 339 { |
| 254 FT_Face ft_face = (FT_Face) font_data; | 340 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 255 | 341 |
| 256 hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size); | 342 hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size); |
| 257 if (ret && (size && !*name)) | 343 if (ret && (size && !*name)) |
| 258 ret = false; | 344 ret = false; |
| 259 | 345 |
| 260 return ret; | 346 return ret; |
| 261 } | 347 } |
| 262 | 348 |
| 263 static hb_bool_t | 349 static hb_bool_t |
| 264 hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, | 350 hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, |
| 265 void *font_data, | 351 void *font_data, |
| 266 const char *name, int len, /* -1 means nul-terminated
*/ | 352 const char *name, int len, /* -1 means nul-terminated
*/ |
| 267 hb_codepoint_t *glyph, | 353 hb_codepoint_t *glyph, |
| 268 void *user_data HB_UNUSED) | 354 void *user_data HB_UNUSED) |
| 269 { | 355 { |
| 270 FT_Face ft_face = (FT_Face) font_data; | 356 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 357 FT_Face ft_face = ft_font->ft_face; |
| 271 | 358 |
| 272 if (len < 0) | 359 if (len < 0) |
| 273 *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name); | 360 *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name); |
| 274 else { | 361 else { |
| 275 /* Make a nul-terminated version. */ | 362 /* Make a nul-terminated version. */ |
| 276 char buf[128]; | 363 char buf[128]; |
| 277 len = MIN (len, (int) sizeof (buf) - 1); | 364 len = MIN (len, (int) sizeof (buf) - 1); |
| 278 strncpy (buf, name, len); | 365 strncpy (buf, name, len); |
| 279 buf[len] = '\0'; | 366 buf[len] = '\0'; |
| 280 *glyph = FT_Get_Name_Index (ft_face, buf); | 367 *glyph = FT_Get_Name_Index (ft_face, buf); |
| 281 } | 368 } |
| 282 | 369 |
| 283 if (*glyph == 0) | 370 if (*glyph == 0) |
| 284 { | 371 { |
| 285 /* Check whether the given name was actually the name of glyph 0. */ | 372 /* Check whether the given name was actually the name of glyph 0. */ |
| 286 char buf[128]; | 373 char buf[128]; |
| 287 if (!FT_Get_Glyph_Name(ft_face, 0, buf, sizeof (buf)) && | 374 if (!FT_Get_Glyph_Name(ft_face, 0, buf, sizeof (buf)) && |
| 288 len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len)) | 375 len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len)) |
| 289 return true; | 376 return true; |
| 290 } | 377 } |
| 291 | 378 |
| 292 return *glyph != 0; | 379 return *glyph != 0; |
| 293 } | 380 } |
| 294 | 381 |
| 295 | 382 |
| 296 static hb_font_funcs_t * | 383 static void |
| 297 _hb_ft_get_font_funcs (void) | 384 _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) |
| 298 { | 385 { |
| 299 static const hb_font_funcs_t ft_ffuncs = { | 386 static const hb_font_funcs_t ft_ffuncs = { |
| 300 HB_OBJECT_HEADER_STATIC, | 387 HB_OBJECT_HEADER_STATIC, |
| 301 | 388 |
| 302 true, /* immutable */ | 389 true, /* immutable */ |
| 303 | 390 |
| 304 { | 391 { |
| 305 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name, | 392 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name, |
| 306 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS | 393 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS |
| 307 #undef HB_FONT_FUNC_IMPLEMENT | 394 #undef HB_FONT_FUNC_IMPLEMENT |
| 308 } | 395 } |
| 309 }; | 396 }; |
| 310 | 397 |
| 311 return const_cast<hb_font_funcs_t *> (&ft_ffuncs); | 398 hb_font_set_funcs (font, |
| 399 » » const_cast<hb_font_funcs_t *> (&ft_ffuncs), |
| 400 » » _hb_ft_font_create (ft_face, unref), |
| 401 » » (hb_destroy_func_t) _hb_ft_font_destroy); |
| 312 } | 402 } |
| 313 | 403 |
| 314 | 404 |
| 315 static hb_blob_t * | 405 static hb_blob_t * |
| 316 reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) | 406 reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) |
| 317 { | 407 { |
| 318 FT_Face ft_face = (FT_Face) user_data; | 408 FT_Face ft_face = (FT_Face) user_data; |
| 319 FT_Byte *buffer; | 409 FT_Byte *buffer; |
| 320 FT_ULong length = 0; | 410 FT_ULong length = 0; |
| 321 FT_Error error; | 411 FT_Error error; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 340 } | 430 } |
| 341 | 431 |
| 342 /** | 432 /** |
| 343 * hb_ft_face_create: | 433 * hb_ft_face_create: |
| 344 * @ft_face: (destroy destroy) (scope notified): | 434 * @ft_face: (destroy destroy) (scope notified): |
| 345 * @destroy: | 435 * @destroy: |
| 346 * | 436 * |
| 347 * | 437 * |
| 348 * | 438 * |
| 349 * Return value: (transfer full): | 439 * Return value: (transfer full): |
| 350 * Since: 1.0 | 440 * Since: 0.9.2 |
| 351 **/ | 441 **/ |
| 352 hb_face_t * | 442 hb_face_t * |
| 353 hb_ft_face_create (FT_Face ft_face, | 443 hb_ft_face_create (FT_Face ft_face, |
| 354 hb_destroy_func_t destroy) | 444 hb_destroy_func_t destroy) |
| 355 { | 445 { |
| 356 hb_face_t *face; | 446 hb_face_t *face; |
| 357 | 447 |
| 358 if (ft_face->stream->read == NULL) { | 448 if (ft_face->stream->read == NULL) { |
| 359 hb_blob_t *blob; | 449 hb_blob_t *blob; |
| 360 | 450 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 hb_face_destroy ((hb_face_t *) ft_face->generic.data); | 486 hb_face_destroy ((hb_face_t *) ft_face->generic.data); |
| 397 } | 487 } |
| 398 | 488 |
| 399 /** | 489 /** |
| 400 * hb_ft_face_create_cached: | 490 * hb_ft_face_create_cached: |
| 401 * @ft_face: | 491 * @ft_face: |
| 402 * | 492 * |
| 403 * | 493 * |
| 404 * | 494 * |
| 405 * Return value: (transfer full): | 495 * Return value: (transfer full): |
| 406 * Since: 1.0 | 496 * Since: 0.9.2 |
| 407 **/ | 497 **/ |
| 408 hb_face_t * | 498 hb_face_t * |
| 409 hb_ft_face_create_cached (FT_Face ft_face) | 499 hb_ft_face_create_cached (FT_Face ft_face) |
| 410 { | 500 { |
| 411 if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Gene
ric_Finalizer) hb_ft_face_finalize)) | 501 if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Gene
ric_Finalizer) hb_ft_face_finalize)) |
| 412 { | 502 { |
| 413 if (ft_face->generic.finalizer) | 503 if (ft_face->generic.finalizer) |
| 414 ft_face->generic.finalizer (ft_face); | 504 ft_face->generic.finalizer (ft_face); |
| 415 | 505 |
| 416 ft_face->generic.data = hb_ft_face_create (ft_face, NULL); | 506 ft_face->generic.data = hb_ft_face_create (ft_face, NULL); |
| 417 ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize; | 507 ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize; |
| 418 } | 508 } |
| 419 | 509 |
| 420 return hb_face_reference ((hb_face_t *) ft_face->generic.data); | 510 return hb_face_reference ((hb_face_t *) ft_face->generic.data); |
| 421 } | 511 } |
| 422 | 512 |
| 423 static void | |
| 424 _do_nothing (void) | |
| 425 { | |
| 426 } | |
| 427 | |
| 428 | 513 |
| 429 /** | 514 /** |
| 430 * hb_ft_font_create: | 515 * hb_ft_font_create: |
| 431 * @ft_face: (destroy destroy) (scope notified): | 516 * @ft_face: (destroy destroy) (scope notified): |
| 432 * @destroy: | 517 * @destroy: |
| 433 * | 518 * |
| 434 * | 519 * |
| 435 * | 520 * |
| 436 * Return value: (transfer full): | 521 * Return value: (transfer full): |
| 437 * Since: 1.0 | 522 * Since: 0.9.2 |
| 438 **/ | 523 **/ |
| 439 hb_font_t * | 524 hb_font_t * |
| 440 hb_ft_font_create (FT_Face ft_face, | 525 hb_ft_font_create (FT_Face ft_face, |
| 441 hb_destroy_func_t destroy) | 526 hb_destroy_func_t destroy) |
| 442 { | 527 { |
| 443 hb_font_t *font; | 528 hb_font_t *font; |
| 444 hb_face_t *face; | 529 hb_face_t *face; |
| 445 | 530 |
| 446 face = hb_ft_face_create (ft_face, destroy); | 531 face = hb_ft_face_create (ft_face, destroy); |
| 447 font = hb_font_create (face); | 532 font = hb_font_create (face); |
| 448 hb_face_destroy (face); | 533 hb_face_destroy (face); |
| 449 hb_font_set_funcs (font, | 534 _hb_ft_font_set_funcs (font, ft_face, false); |
| 450 » » _hb_ft_get_font_funcs (), | |
| 451 » » ft_face, (hb_destroy_func_t) _do_nothing); | |
| 452 hb_font_set_scale (font, | 535 hb_font_set_scale (font, |
| 453 (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16), | 536 (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16), |
| 454 (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16)); | 537 (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16)); |
| 455 #if 0 /* hb-ft works in no-hinting model */ | 538 #if 0 /* hb-ft works in no-hinting model */ |
| 456 hb_font_set_ppem (font, | 539 hb_font_set_ppem (font, |
| 457 ft_face->size->metrics.x_ppem, | 540 ft_face->size->metrics.x_ppem, |
| 458 ft_face->size->metrics.y_ppem); | 541 ft_face->size->metrics.y_ppem); |
| 459 #endif | 542 #endif |
| 460 | 543 |
| 461 return font; | 544 return font; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 if (font->x_scale < 0 || font->y_scale < 0) | 638 if (font->x_scale < 0 || font->y_scale < 0) |
| 556 { | 639 { |
| 557 FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, | 640 FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, |
| 558 0, font->y_scale < 0 ? -1 : +1}; | 641 0, font->y_scale < 0 ? -1 : +1}; |
| 559 FT_Set_Transform (ft_face, &matrix, NULL); | 642 FT_Set_Transform (ft_face, &matrix, NULL); |
| 560 } | 643 } |
| 561 | 644 |
| 562 ft_face->generic.data = blob; | 645 ft_face->generic.data = blob; |
| 563 ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; | 646 ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; |
| 564 | 647 |
| 565 hb_font_set_funcs (font, | 648 _hb_ft_font_set_funcs (font, ft_face, true); |
| 566 » » _hb_ft_get_font_funcs (), | 649 hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); |
| 567 » » ft_face, | |
| 568 » » (hb_destroy_func_t) FT_Done_Face); | |
| 569 } | 650 } |
| 570 | |
| 571 FT_Face | |
| 572 hb_ft_font_get_face (hb_font_t *font) | |
| 573 { | |
| 574 if (font->destroy == (hb_destroy_func_t) FT_Done_Face || | |
| 575 font->destroy == (hb_destroy_func_t) _do_nothing) | |
| 576 return (FT_Face) font->user_data; | |
| 577 | |
| 578 return NULL; | |
| 579 } | |
| OLD | NEW |