| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright © 1998-2004 David Turner and Werner Lemberg | 2 * Copyright © 1998-2004 David Turner and Werner Lemberg |
| 3 * Copyright © 2006 Behdad Esfahbod | 3 * Copyright © 2006 Behdad Esfahbod |
| 4 * Copyright © 2007,2008,2009 Red Hat, Inc. | 4 * Copyright © 2007,2008,2009 Red Hat, Inc. |
| 5 * Copyright © 2012,2013 Google, Inc. | 5 * Copyright © 2012,2013 Google, Inc. |
| 6 * | 6 * |
| 7 * This is part of HarfBuzz, a text shaping library. | 7 * This is part of HarfBuzz, a text shaping library. |
| 8 * | 8 * |
| 9 * Permission is hereby granted, without written agreement and without | 9 * Permission is hereby granted, without written agreement and without |
| 10 * license or royalty fees, to use, copy, modify, and distribute this | 10 * license or royalty fees, to use, copy, modify, and distribute this |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 * Google Author(s): Behdad Esfahbod | 28 * Google Author(s): Behdad Esfahbod |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "hb-open-type-private.hh" | 31 #include "hb-open-type-private.hh" |
| 32 #include "hb-ot-layout-private.hh" | 32 #include "hb-ot-layout-private.hh" |
| 33 | 33 |
| 34 #include "hb-ot-layout-gdef-table.hh" | 34 #include "hb-ot-layout-gdef-table.hh" |
| 35 #include "hb-ot-layout-gsub-table.hh" | 35 #include "hb-ot-layout-gsub-table.hh" |
| 36 #include "hb-ot-layout-gpos-table.hh" | 36 #include "hb-ot-layout-gpos-table.hh" |
| 37 #include "hb-ot-layout-jstf-table.hh" | 37 #include "hb-ot-layout-jstf-table.hh" |
| 38 #include "hb-ot-layout-math-table.hh" |
| 38 | 39 |
| 39 #include "hb-ot-map-private.hh" | 40 #include "hb-ot-map-private.hh" |
| 40 | 41 |
| 41 #include <stdlib.h> | 42 #include <stdlib.h> |
| 42 #include <string.h> | 43 #include <string.h> |
| 43 | 44 |
| 44 | 45 |
| 45 HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) | 46 HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) |
| 46 | 47 |
| 47 hb_ot_layout_t * | 48 hb_ot_layout_t * |
| 48 _hb_ot_layout_create (hb_face_t *face) | 49 _hb_ot_layout_create (hb_face_t *face) |
| 49 { | 50 { |
| 50 hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t)
); | 51 hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t)
); |
| 51 if (unlikely (!layout)) | 52 if (unlikely (!layout)) |
| 52 return NULL; | 53 return NULL; |
| 53 | 54 |
| 54 layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (
HB_OT_TAG_GDEF)); | 55 layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (
HB_OT_TAG_GDEF)); |
| 55 layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob); | 56 layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob); |
| 56 | 57 |
| 57 layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (
HB_OT_TAG_GSUB)); | 58 layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (
HB_OT_TAG_GSUB)); |
| 58 layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob); | 59 layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob); |
| 59 | 60 |
| 60 layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (
HB_OT_TAG_GPOS)); | 61 layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (
HB_OT_TAG_GPOS)); |
| 61 layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob); | 62 layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob); |
| 62 | 63 |
| 64 /* The MATH table is rarely used, so only try and load it in _get_math. */ |
| 65 layout->math_blob = NULL; |
| 66 layout->math = NULL; |
| 67 |
| 63 { | 68 { |
| 64 /* | 69 /* |
| 65 * The ugly business of blacklisting individual fonts' tables happen here! | 70 * The ugly business of blacklisting individual fonts' tables happen here! |
| 66 * See this thread for why we finally had to bend in and do this: | 71 * See this thread for why we finally had to bend in and do this: |
| 67 * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html | 72 * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html |
| 68 */ | 73 */ |
| 69 unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob); | 74 unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob); |
| 70 unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob); | 75 unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob); |
| 71 unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob); | 76 unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob); |
| 72 if (0 | 77 if (0 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 layout->gsub_accels[i].fini (); | 175 layout->gsub_accels[i].fini (); |
| 171 for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) | 176 for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) |
| 172 layout->gpos_accels[i].fini (); | 177 layout->gpos_accels[i].fini (); |
| 173 | 178 |
| 174 free (layout->gsub_accels); | 179 free (layout->gsub_accels); |
| 175 free (layout->gpos_accels); | 180 free (layout->gpos_accels); |
| 176 | 181 |
| 177 hb_blob_destroy (layout->gdef_blob); | 182 hb_blob_destroy (layout->gdef_blob); |
| 178 hb_blob_destroy (layout->gsub_blob); | 183 hb_blob_destroy (layout->gsub_blob); |
| 179 hb_blob_destroy (layout->gpos_blob); | 184 hb_blob_destroy (layout->gpos_blob); |
| 185 hb_blob_destroy (layout->math_blob); |
| 180 | 186 |
| 181 free (layout); | 187 free (layout); |
| 182 } | 188 } |
| 183 | 189 |
| 184 static inline const OT::GDEF& | 190 static inline const OT::GDEF& |
| 185 _get_gdef (hb_face_t *face) | 191 _get_gdef (hb_face_t *face) |
| 186 { | 192 { |
| 187 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF
); | 193 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF
); |
| 188 return *hb_ot_layout_from_face (face)->gdef; | 194 return *hb_ot_layout_from_face (face)->gdef; |
| 189 } | 195 } |
| 190 static inline const OT::GSUB& | 196 static inline const OT::GSUB& |
| 191 _get_gsub (hb_face_t *face) | 197 _get_gsub (hb_face_t *face) |
| 192 { | 198 { |
| 193 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB
); | 199 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB
); |
| 194 return *hb_ot_layout_from_face (face)->gsub; | 200 return *hb_ot_layout_from_face (face)->gsub; |
| 195 } | 201 } |
| 196 static inline const OT::GPOS& | 202 static inline const OT::GPOS& |
| 197 _get_gpos (hb_face_t *face) | 203 _get_gpos (hb_face_t *face) |
| 198 { | 204 { |
| 199 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS
); | 205 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS
); |
| 200 return *hb_ot_layout_from_face (face)->gpos; | 206 return *hb_ot_layout_from_face (face)->gpos; |
| 201 } | 207 } |
| 208 static inline const OT::MATH& |
| 209 _get_math (hb_face_t *face) |
| 210 { |
| 211 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH
); |
| 212 |
| 213 hb_ot_layout_t * layout = hb_ot_layout_from_face (face); |
| 214 |
| 215 retry: |
| 216 const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math); |
| 217 |
| 218 if (unlikely (!math)) |
| 219 { |
| 220 hb_blob_t *blob = OT::Sanitizer<OT::MATH>::sanitize (face->reference_table (
HB_OT_TAG_MATH)); |
| 221 math = OT::Sanitizer<OT::MATH>::lock_instance (blob); |
| 222 if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math)) |
| 223 { |
| 224 hb_blob_destroy (blob); |
| 225 goto retry; |
| 226 } |
| 227 layout->math_blob = blob; |
| 228 } |
| 229 |
| 230 return *math; |
| 231 } |
| 202 | 232 |
| 203 | 233 |
| 204 /* | 234 /* |
| 205 * GDEF | 235 * GDEF |
| 206 */ | 236 */ |
| 207 | 237 |
| 208 hb_bool_t | 238 hb_bool_t |
| 209 hb_ot_layout_has_glyph_classes (hb_face_t *face) | 239 hb_ot_layout_has_glyph_classes (hb_face_t *face) |
| 210 { | 240 { |
| 211 return _get_gdef (face).has_glyph_classes (); | 241 return _get_gdef (face).has_glyph_classes (); |
| (...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1183 apply (proxy, plan, font, buffer); | 1213 apply (proxy, plan, font, buffer); |
| 1184 } | 1214 } |
| 1185 | 1215 |
| 1186 HB_INTERNAL void | 1216 HB_INTERNAL void |
| 1187 hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, | 1217 hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, |
| 1188 const OT::SubstLookup &lookup, | 1218 const OT::SubstLookup &lookup, |
| 1189 const hb_ot_layout_lookup_accelerator_t &accel) | 1219 const hb_ot_layout_lookup_accelerator_t &accel) |
| 1190 { | 1220 { |
| 1191 apply_string<GSUBProxy> (c, lookup, accel); | 1221 apply_string<GSUBProxy> (c, lookup, accel); |
| 1192 } | 1222 } |
| 1223 |
| 1224 |
| 1225 /* |
| 1226 * MATH |
| 1227 */ |
| 1228 /* TODO Move this to hb-ot-math.cc and separate it from hb_ot_layout_t. */ |
| 1229 |
| 1230 /** |
| 1231 * hb_ot_math_has_data: |
| 1232 * @face: #hb_face_t to test |
| 1233 * |
| 1234 * This function allows to verify the presence of an OpenType MATH table on the |
| 1235 * face. If so, such a table will be loaded into memory and sanitized. You can |
| 1236 * then safely call other functions for math layout and shaping. |
| 1237 * |
| 1238 * Return value: #TRUE if face has a MATH table and #FALSE otherwise |
| 1239 * |
| 1240 * Since: 1.3.3 |
| 1241 **/ |
| 1242 hb_bool_t |
| 1243 hb_ot_math_has_data (hb_face_t *face) |
| 1244 { |
| 1245 return &_get_math (face) != &OT::Null(OT::MATH); |
| 1246 } |
| 1247 |
| 1248 /** |
| 1249 * hb_ot_math_get_constant: |
| 1250 * @font: #hb_font_t from which to retrieve the value |
| 1251 * @constant: #hb_ot_math_constant_t the constant to retrieve |
| 1252 * |
| 1253 * This function returns the requested math constants as a #hb_position_t. |
| 1254 * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, |
| 1255 * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or |
| 1256 * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is |
| 1257 * actually an integer between 0 and 100 representing that percentage. |
| 1258 * |
| 1259 * Return value: the requested constant or 0 |
| 1260 * |
| 1261 * Since: 1.3.3 |
| 1262 **/ |
| 1263 hb_position_t |
| 1264 hb_ot_math_get_constant (hb_font_t *font, |
| 1265 hb_ot_math_constant_t constant) |
| 1266 { |
| 1267 const OT::MATH &math = _get_math (font->face); |
| 1268 return math.get_constant(constant, font); |
| 1269 } |
| 1270 |
| 1271 /** |
| 1272 * hb_ot_math_get_glyph_italics_correction: |
| 1273 * @font: #hb_font_t from which to retrieve the value |
| 1274 * @glyph: glyph index from which to retrieve the value |
| 1275 * |
| 1276 * Return value: the italics correction of the glyph or 0 |
| 1277 * |
| 1278 * Since: 1.3.3 |
| 1279 **/ |
| 1280 hb_position_t |
| 1281 hb_ot_math_get_glyph_italics_correction (hb_font_t *font, |
| 1282 hb_codepoint_t glyph) |
| 1283 { |
| 1284 const OT::MATH &math = _get_math (font->face); |
| 1285 return math.get_math_glyph_info().get_italics_correction (glyph, font); |
| 1286 } |
| 1287 |
| 1288 /** |
| 1289 * hb_ot_math_get_glyph_top_accent_attachment: |
| 1290 * @font: #hb_font_t from which to retrieve the value |
| 1291 * @glyph: glyph index from which to retrieve the value |
| 1292 * |
| 1293 * Return value: the top accent attachment of the glyph or 0 |
| 1294 * |
| 1295 * Since: 1.3.3 |
| 1296 **/ |
| 1297 hb_position_t |
| 1298 hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, |
| 1299 hb_codepoint_t glyph) |
| 1300 { |
| 1301 const OT::MATH &math = _get_math (font->face); |
| 1302 return math.get_math_glyph_info().get_top_accent_attachment (glyph, font); |
| 1303 } |
| 1304 |
| 1305 /** |
| 1306 * hb_ot_math_is_glyph_extended_shape: |
| 1307 * @font: a #hb_font_t to test |
| 1308 * @glyph: a glyph index to test |
| 1309 * |
| 1310 * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise |
| 1311 * |
| 1312 * Since: 1.3.3 |
| 1313 **/ |
| 1314 hb_bool_t |
| 1315 hb_ot_math_is_glyph_extended_shape (hb_face_t *face, |
| 1316 hb_codepoint_t glyph) |
| 1317 { |
| 1318 const OT::MATH &math = _get_math (face); |
| 1319 return math.get_math_glyph_info().is_extended_shape (glyph); |
| 1320 } |
| 1321 |
| 1322 /** |
| 1323 * hb_ot_math_get_glyph_kerning: |
| 1324 * @font: #hb_font_t from which to retrieve the value |
| 1325 * @glyph: glyph index from which to retrieve the value |
| 1326 * @kern: the #hb_ot_math_kern_t from which to retrieve the value |
| 1327 * @correction_height: the correction height to use to determine the kerning. |
| 1328 * |
| 1329 * This function tries to retrieve the MathKern table for the specified font, |
| 1330 * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the |
| 1331 * MathKern table to find one value that is greater or equal to specified |
| 1332 * correction_height. If one is found the corresponding value from the list of |
| 1333 * kerns is returned and otherwise the last kern value is returned. |
| 1334 * |
| 1335 * Return value: requested kerning or 0 |
| 1336 * |
| 1337 * Since: 1.3.3 |
| 1338 **/ |
| 1339 hb_position_t |
| 1340 hb_ot_math_get_glyph_kerning (hb_font_t *font, |
| 1341 hb_codepoint_t glyph, |
| 1342 hb_ot_math_kern_t kern, |
| 1343 hb_position_t correction_height) |
| 1344 { |
| 1345 const OT::MATH &math = _get_math (font->face); |
| 1346 return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height,
font); |
| 1347 } |
| 1348 |
| 1349 /** |
| 1350 * hb_ot_math_get_glyph_variants: |
| 1351 * @font: #hb_font_t from which to retrieve the values |
| 1352 * @glyph: index of the glyph to stretch |
| 1353 * @direction: direction of the stretching |
| 1354 * @start_offset: offset of the first variant to retrieve |
| 1355 * @variants_count: maximum number of variants to retrieve after start_offset |
| 1356 * (IN) and actual number of variants retrieved (OUT) |
| 1357 * @variants: array of size at least @variants_count to store the result |
| 1358 * |
| 1359 * This function tries to retrieve the MathGlyphConstruction for the specified |
| 1360 * font, glyph and direction. Note that only the value of |
| 1361 * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list |
| 1362 * of size variants as an array of hb_ot_math_glyph_variant_t structs. |
| 1363 * |
| 1364 * Return value: the total number of size variants available or 0 |
| 1365 * |
| 1366 * Since: 1.3.3 |
| 1367 **/ |
| 1368 unsigned int |
| 1369 hb_ot_math_get_glyph_variants (hb_font_t *font, |
| 1370 hb_codepoint_t glyph, |
| 1371 hb_direction_t direction, |
| 1372 unsigned int start_offset, |
| 1373 unsigned int *variants_count, /* IN/OUT */ |
| 1374 hb_ot_math_glyph_variant_t *variants /* OUT */) |
| 1375 { |
| 1376 const OT::MATH &math = _get_math (font->face); |
| 1377 return math.get_math_variants().get_glyph_variants (glyph, direction, font, |
| 1378 start_offset, |
| 1379 variants_count, |
| 1380 variants); |
| 1381 } |
| 1382 |
| 1383 /** |
| 1384 * hb_ot_math_get_min_connector_overlap: |
| 1385 * @font: #hb_font_t from which to retrieve the value |
| 1386 * @direction: direction of the stretching |
| 1387 * |
| 1388 * This function tries to retrieve the MathVariants table for the specified |
| 1389 * font and returns the minimum overlap of connecting glyphs to draw a glyph |
| 1390 * assembly in the specified direction. Note that only the value of |
| 1391 * #HB_DIRECTION_IS_HORIZONTAL is considered. |
| 1392 * |
| 1393 * Return value: requested min connector overlap or 0 |
| 1394 * |
| 1395 * Since: 1.3.3 |
| 1396 **/ |
| 1397 hb_position_t |
| 1398 hb_ot_math_get_min_connector_overlap (hb_font_t *font, |
| 1399 hb_direction_t direction) |
| 1400 { |
| 1401 const OT::MATH &math = _get_math (font->face); |
| 1402 return math.get_math_variants().get_min_connector_overlap (direction, font); |
| 1403 } |
| 1404 |
| 1405 /** |
| 1406 * hb_ot_math_get_glyph_assembly: |
| 1407 * @font: #hb_font_t from which to retrieve the values |
| 1408 * @glyph: index of the glyph to stretch |
| 1409 * @direction: direction of the stretching |
| 1410 * @start_offset: offset of the first glyph part to retrieve |
| 1411 * @parts_count: maximum number of glyph parts to retrieve after start_offset |
| 1412 * (IN) and actual number of parts retrieved (OUT) |
| 1413 * @parts: array of size at least @parts_count to store the result |
| 1414 * @italics_correction: italic correction of the glyph assembly |
| 1415 * |
| 1416 * This function tries to retrieve the GlyphAssembly for the specified font, |
| 1417 * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL |
| 1418 * is considered. It provides the information necessary to draw the glyph |
| 1419 * assembly as an array of #hb_ot_math_glyph_part_t. |
| 1420 * |
| 1421 * Return value: the total number of parts in the glyph assembly |
| 1422 * |
| 1423 * Since: 1.3.3 |
| 1424 **/ |
| 1425 unsigned int |
| 1426 hb_ot_math_get_glyph_assembly (hb_font_t *font, |
| 1427 hb_codepoint_t glyph, |
| 1428 hb_direction_t direction, |
| 1429 unsigned int start_offset, |
| 1430 unsigned int *parts_count, /* IN/OUT */ |
| 1431 hb_ot_math_glyph_part_t *parts, /* OUT */ |
| 1432 hb_position_t *italics_correction /* OUT */) |
| 1433 { |
| 1434 const OT::MATH &math = _get_math (font->face); |
| 1435 return math.get_math_variants().get_glyph_parts (glyph, direction, font, |
| 1436 start_offset, |
| 1437 parts_count, |
| 1438 parts, |
| 1439 italics_correction); |
| 1440 } |
| OLD | NEW |