1160 DEFINE_SIZE_UNION (2, format); |
1167 DEFINE_SIZE_UNION (2, format); |
1161 }; |
1168 }; |
1162 |
1169 |
1163 |
1170 |
1164 /* |
1171 /* |
|
1172 * Item Variation Store |
|
1173 */ |
|
1174 |
|
1175 struct VarRegionAxis |
|
1176 { |
|
1177 inline float evaluate (int coord) const |
|
1178 { |
|
1179 int start = startCoord, peak = peakCoord, end = endCoord; |
|
1180 |
|
1181 /* TODO Move these to sanitize(). */ |
|
1182 if (unlikely (start > peak || peak > end)) |
|
1183 return 1.; |
|
1184 if (unlikely (start < 0 && end > 0 && peak != 0)) |
|
1185 return 1.; |
|
1186 |
|
1187 if (peak == 0 || coord == peak) |
|
1188 return 1.; |
|
1189 |
|
1190 if (coord <= start || end <= coord) |
|
1191 return 0.; |
|
1192 |
|
1193 /* Interpolate */ |
|
1194 if (coord < peak) |
|
1195 return float (coord - start) / (peak - start); |
|
1196 else |
|
1197 return float (end - coord) / (end - peak); |
|
1198 } |
|
1199 |
|
1200 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1201 { |
|
1202 TRACE_SANITIZE (this); |
|
1203 return_trace (c->check_struct (this)); |
|
1204 /* TODO Handle invalid start/peak/end configs, so we don't |
|
1205 * have to do that at runtime. */ |
|
1206 } |
|
1207 |
|
1208 public: |
|
1209 F2DOT14 startCoord; |
|
1210 F2DOT14 peakCoord; |
|
1211 F2DOT14 endCoord; |
|
1212 public: |
|
1213 DEFINE_SIZE_STATIC (6); |
|
1214 }; |
|
1215 |
|
1216 struct VarRegionList |
|
1217 { |
|
1218 inline float evaluate (unsigned int region_index, |
|
1219 int *coords, unsigned int coord_len) const |
|
1220 { |
|
1221 if (unlikely (region_index >= regionCount)) |
|
1222 return 0.; |
|
1223 |
|
1224 const VarRegionAxis *axes = axesZ + (region_index * axisCount); |
|
1225 |
|
1226 float v = 1.; |
|
1227 unsigned int count = MIN (coord_len, (unsigned int) axisCount); |
|
1228 for (unsigned int i = 0; i < count; i++) |
|
1229 { |
|
1230 float factor = axes[i].evaluate (coords[i]); |
|
1231 if (factor == 0.) |
|
1232 return 0.; |
|
1233 v *= factor; |
|
1234 } |
|
1235 return v; |
|
1236 } |
|
1237 |
|
1238 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1239 { |
|
1240 TRACE_SANITIZE (this); |
|
1241 return_trace (c->check_struct (this) && |
|
1242 c->check_array (axesZ, axesZ[0].static_size, |
|
1243 (unsigned int) axisCount * (unsigned int) regionCount)); |
|
1244 } |
|
1245 |
|
1246 protected: |
|
1247 USHORT axisCount; |
|
1248 USHORT regionCount; |
|
1249 VarRegionAxis axesZ[VAR]; |
|
1250 public: |
|
1251 DEFINE_SIZE_ARRAY (4, axesZ); |
|
1252 }; |
|
1253 |
|
1254 struct VarData |
|
1255 { |
|
1256 inline unsigned int get_row_size (void) const |
|
1257 { return shortCount + regionIndices.len; } |
|
1258 |
|
1259 inline unsigned int get_size (void) const |
|
1260 { return itemCount * get_row_size (); } |
|
1261 |
|
1262 inline float get_delta (unsigned int inner, |
|
1263 int *coords, unsigned int coord_count, |
|
1264 const VarRegionList ®ions) const |
|
1265 { |
|
1266 if (unlikely (inner >= itemCount)) |
|
1267 return 0.; |
|
1268 |
|
1269 unsigned int count = regionIndices.len; |
|
1270 unsigned int scount = shortCount; |
|
1271 |
|
1272 const BYTE *bytes = &StructAfter<BYTE> (regionIndices); |
|
1273 const BYTE *row = bytes + inner * (scount + count); |
|
1274 |
|
1275 float delta = 0.; |
|
1276 unsigned int i = 0; |
|
1277 |
|
1278 const SHORT *scursor = reinterpret_cast<const SHORT *> (row); |
|
1279 for (; i < scount; i++) |
|
1280 { |
|
1281 float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count); |
|
1282 delta += scalar * *scursor++; |
|
1283 } |
|
1284 const INT8 *bcursor = reinterpret_cast<const INT8 *> (scursor); |
|
1285 for (; i < count; i++) |
|
1286 { |
|
1287 float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count); |
|
1288 delta += scalar * *bcursor++; |
|
1289 } |
|
1290 |
|
1291 return delta; |
|
1292 } |
|
1293 |
|
1294 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1295 { |
|
1296 TRACE_SANITIZE (this); |
|
1297 return_trace (c->check_struct (this) && |
|
1298 regionIndices.sanitize(c) && |
|
1299 shortCount <= regionIndices.len && |
|
1300 c->check_array (&StructAfter<BYTE> (regionIndices), |
|
1301 get_row_size (), itemCount)); |
|
1302 } |
|
1303 |
|
1304 protected: |
|
1305 USHORT itemCount; |
|
1306 USHORT shortCount; |
|
1307 ArrayOf<USHORT> regionIndices; |
|
1308 BYTE bytesX[VAR]; |
|
1309 public: |
|
1310 DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX); |
|
1311 }; |
|
1312 |
|
1313 struct VariationStore |
|
1314 { |
|
1315 inline float get_delta (unsigned int outer, unsigned int inner, |
|
1316 int *coords, unsigned int coord_count) const |
|
1317 { |
|
1318 if (unlikely (outer >= dataSets.len)) |
|
1319 return 0.; |
|
1320 |
|
1321 return (this+dataSets[outer]).get_delta (inner, |
|
1322 coords, coord_count, |
|
1323 this+regions); |
|
1324 } |
|
1325 |
|
1326 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1327 { |
|
1328 TRACE_SANITIZE (this); |
|
1329 return_trace (c->check_struct (this) && |
|
1330 format == 1 && |
|
1331 regions.sanitize (c, this) && |
|
1332 dataSets.sanitize (c, this)); |
|
1333 } |
|
1334 |
|
1335 protected: |
|
1336 USHORT format; |
|
1337 OffsetTo<VarRegionList, ULONG> regions; |
|
1338 OffsetArrayOf<VarData, ULONG> dataSets; |
|
1339 public: |
|
1340 DEFINE_SIZE_ARRAY (8, dataSets); |
|
1341 }; |
|
1342 |
|
1343 /* |
|
1344 * Feature Variations |
|
1345 */ |
|
1346 |
|
1347 struct ConditionFormat1 |
|
1348 { |
|
1349 friend struct Condition; |
|
1350 |
|
1351 private: |
|
1352 inline bool evaluate (const int *coords, unsigned int coord_len) const |
|
1353 { |
|
1354 int coord = axisIndex < coord_len ? coords[axisIndex] : 0; |
|
1355 return filterRangeMinValue <= coord && coord <= filterRangeMaxValue; |
|
1356 } |
|
1357 |
|
1358 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1359 { |
|
1360 TRACE_SANITIZE (this); |
|
1361 return_trace (c->check_struct (this)); |
|
1362 } |
|
1363 |
|
1364 protected: |
|
1365 USHORT format; /* Format identifier--format = 1 */ |
|
1366 USHORT axisIndex; |
|
1367 F2DOT14 filterRangeMinValue; |
|
1368 F2DOT14 filterRangeMaxValue; |
|
1369 public: |
|
1370 DEFINE_SIZE_STATIC (8); |
|
1371 }; |
|
1372 |
|
1373 struct Condition |
|
1374 { |
|
1375 inline bool evaluate (const int *coords, unsigned int coord_len) const |
|
1376 { |
|
1377 switch (u.format) { |
|
1378 case 1: return u.format1.evaluate (coords, coord_len); |
|
1379 default:return false; |
|
1380 } |
|
1381 } |
|
1382 |
|
1383 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1384 { |
|
1385 TRACE_SANITIZE (this); |
|
1386 if (!u.format.sanitize (c)) return_trace (false); |
|
1387 switch (u.format) { |
|
1388 case 1: return_trace (u.format1.sanitize (c)); |
|
1389 default:return_trace (true); |
|
1390 } |
|
1391 } |
|
1392 |
|
1393 protected: |
|
1394 union { |
|
1395 USHORT format; /* Format identifier */ |
|
1396 ConditionFormat1 format1; |
|
1397 } u; |
|
1398 public: |
|
1399 DEFINE_SIZE_UNION (2, format); |
|
1400 }; |
|
1401 |
|
1402 struct ConditionSet |
|
1403 { |
|
1404 inline bool evaluate (const int *coords, unsigned int coord_len) const |
|
1405 { |
|
1406 unsigned int count = conditions.len; |
|
1407 for (unsigned int i = 0; i < count; i++) |
|
1408 if (!(this+conditions.array[i]).evaluate (coords, coord_len)) |
|
1409 return false; |
|
1410 return true; |
|
1411 } |
|
1412 |
|
1413 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1414 { |
|
1415 TRACE_SANITIZE (this); |
|
1416 return_trace (conditions.sanitize (c, this)); |
|
1417 } |
|
1418 |
|
1419 protected: |
|
1420 OffsetArrayOf<Condition, ULONG> conditions; |
|
1421 public: |
|
1422 DEFINE_SIZE_ARRAY (2, conditions); |
|
1423 }; |
|
1424 |
|
1425 struct FeatureTableSubstitutionRecord |
|
1426 { |
|
1427 friend struct FeatureTableSubstitution; |
|
1428 |
|
1429 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
|
1430 { |
|
1431 TRACE_SANITIZE (this); |
|
1432 return_trace (c->check_struct (this) && feature.sanitize (c, base)); |
|
1433 } |
|
1434 |
|
1435 protected: |
|
1436 USHORT featureIndex; |
|
1437 OffsetTo<Feature, ULONG> feature; |
|
1438 public: |
|
1439 DEFINE_SIZE_STATIC (6); |
|
1440 }; |
|
1441 |
|
1442 struct FeatureTableSubstitution |
|
1443 { |
|
1444 inline const Feature *find_substitute (unsigned int feature_index) const |
|
1445 { |
|
1446 unsigned int count = substitutions.len; |
|
1447 for (unsigned int i = 0; i < count; i++) |
|
1448 { |
|
1449 const FeatureTableSubstitutionRecord &record = substitutions.array[i]; |
|
1450 if (record.featureIndex == feature_index) |
|
1451 return &(this+record.feature); |
|
1452 } |
|
1453 return NULL; |
|
1454 } |
|
1455 |
|
1456 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1457 { |
|
1458 TRACE_SANITIZE (this); |
|
1459 return_trace (version.sanitize (c) && |
|
1460 likely (version.major == 1) && |
|
1461 substitutions.sanitize (c, this)); |
|
1462 } |
|
1463 |
|
1464 protected: |
|
1465 FixedVersion<> version; /* Version--0x00010000u */ |
|
1466 ArrayOf<FeatureTableSubstitutionRecord> |
|
1467 substitutions; |
|
1468 public: |
|
1469 DEFINE_SIZE_ARRAY (6, substitutions); |
|
1470 }; |
|
1471 |
|
1472 struct FeatureVariationRecord |
|
1473 { |
|
1474 friend struct FeatureVariations; |
|
1475 |
|
1476 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
|
1477 { |
|
1478 TRACE_SANITIZE (this); |
|
1479 return_trace (conditions.sanitize (c, base) && |
|
1480 substitutions.sanitize (c, base)); |
|
1481 } |
|
1482 |
|
1483 protected: |
|
1484 OffsetTo<ConditionSet, ULONG> |
|
1485 conditions; |
|
1486 OffsetTo<FeatureTableSubstitution, ULONG> |
|
1487 substitutions; |
|
1488 public: |
|
1489 DEFINE_SIZE_STATIC (8); |
|
1490 }; |
|
1491 |
|
1492 struct FeatureVariations |
|
1493 { |
|
1494 static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu; |
|
1495 |
|
1496 inline bool find_index (const int *coords, unsigned int coord_len, |
|
1497 unsigned int *index) const |
|
1498 { |
|
1499 unsigned int count = varRecords.len; |
|
1500 for (unsigned int i = 0; i < count; i++) |
|
1501 { |
|
1502 const FeatureVariationRecord &record = varRecords.array[i]; |
|
1503 if ((this+record.conditions).evaluate (coords, coord_len)) |
|
1504 { |
|
1505 *index = i; |
|
1506 return true; |
|
1507 } |
|
1508 } |
|
1509 *index = NOT_FOUND_INDEX; |
|
1510 return false; |
|
1511 } |
|
1512 |
|
1513 inline const Feature *find_substitute (unsigned int variations_index, |
|
1514 unsigned int feature_index) const |
|
1515 { |
|
1516 const FeatureVariationRecord &record = varRecords[variations_index]; |
|
1517 return (this+record.substitutions).find_substitute (feature_index); |
|
1518 } |
|
1519 |
|
1520 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1521 { |
|
1522 TRACE_SANITIZE (this); |
|
1523 return_trace (version.sanitize (c) && |
|
1524 likely (version.major == 1) && |
|
1525 varRecords.sanitize (c, this)); |
|
1526 } |
|
1527 |
|
1528 protected: |
|
1529 FixedVersion<> version; /* Version--0x00010000u */ |
|
1530 ArrayOf<FeatureVariationRecord, ULONG> |
|
1531 varRecords; |
|
1532 public: |
|
1533 DEFINE_SIZE_ARRAY (8, varRecords); |
|
1534 }; |
|
1535 |
|
1536 |
|
1537 /* |
1165 * Device Tables |
1538 * Device Tables |
1166 */ |
1539 */ |
1167 |
1540 |
1168 struct Device |
1541 struct HintingDevice |
1169 { |
1542 { |
|
1543 friend struct Device; |
|
1544 |
|
1545 private: |
1170 |
1546 |
1171 inline hb_position_t get_x_delta (hb_font_t *font) const |
1547 inline hb_position_t get_x_delta (hb_font_t *font) const |
1172 { return get_delta (font->x_ppem, font->x_scale); } |
1548 { return get_delta (font->x_ppem, font->x_scale); } |
1173 |
1549 |
1174 inline hb_position_t get_y_delta (hb_font_t *font) const |
1550 inline hb_position_t get_y_delta (hb_font_t *font) const |
1233 USHORT deltaValue[VAR]; /* Array of compressed data */ |
1609 USHORT deltaValue[VAR]; /* Array of compressed data */ |
1234 public: |
1610 public: |
1235 DEFINE_SIZE_ARRAY (6, deltaValue); |
1611 DEFINE_SIZE_ARRAY (6, deltaValue); |
1236 }; |
1612 }; |
1237 |
1613 |
|
1614 struct VariationDevice |
|
1615 { |
|
1616 friend struct Device; |
|
1617 |
|
1618 private: |
|
1619 |
|
1620 inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const |
|
1621 { return font->em_scalef_x (get_delta (font, store)); } |
|
1622 |
|
1623 inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const |
|
1624 { return font->em_scalef_y (get_delta (font, store)); } |
|
1625 |
|
1626 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1627 { |
|
1628 TRACE_SANITIZE (this); |
|
1629 return_trace (c->check_struct (this)); |
|
1630 } |
|
1631 |
|
1632 private: |
|
1633 |
|
1634 inline float get_delta (hb_font_t *font, const VariationStore &store) const |
|
1635 { |
|
1636 return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords); |
|
1637 } |
|
1638 |
|
1639 protected: |
|
1640 USHORT outerIndex; |
|
1641 USHORT innerIndex; |
|
1642 USHORT deltaFormat; /* Format identifier for this table: 0x0x8000 */ |
|
1643 public: |
|
1644 DEFINE_SIZE_STATIC (6); |
|
1645 }; |
|
1646 |
|
1647 struct DeviceHeader |
|
1648 { |
|
1649 protected: |
|
1650 USHORT reserved1; |
|
1651 USHORT reserved2; |
|
1652 public: |
|
1653 USHORT format; /* Format identifier */ |
|
1654 public: |
|
1655 DEFINE_SIZE_STATIC (6); |
|
1656 }; |
|
1657 |
|
1658 struct Device |
|
1659 { |
|
1660 inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const |
|
1661 { |
|
1662 switch (u.b.format) |
|
1663 { |
|
1664 case 1: case 2: case 3: |
|
1665 return u.hinting.get_x_delta (font); |
|
1666 case 0x8000: |
|
1667 return u.variation.get_x_delta (font, store); |
|
1668 default: |
|
1669 return 0; |
|
1670 } |
|
1671 } |
|
1672 inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const |
|
1673 { |
|
1674 switch (u.b.format) |
|
1675 { |
|
1676 case 1: case 2: case 3: |
|
1677 return u.hinting.get_y_delta (font); |
|
1678 case 0x8000: |
|
1679 return u.variation.get_y_delta (font, store); |
|
1680 default: |
|
1681 return 0; |
|
1682 } |
|
1683 } |
|
1684 |
|
1685 inline bool sanitize (hb_sanitize_context_t *c) const |
|
1686 { |
|
1687 TRACE_SANITIZE (this); |
|
1688 if (!u.b.format.sanitize (c)) return_trace (false); |
|
1689 switch (u.b.format) { |
|
1690 case 1: case 2: case 3: |
|
1691 return_trace (u.hinting.sanitize (c)); |
|
1692 case 0x8000: |
|
1693 return_trace (u.variation.sanitize (c)); |
|
1694 default: |
|
1695 return_trace (true); |
|
1696 } |
|
1697 } |
|
1698 |
|
1699 protected: |
|
1700 union { |
|
1701 DeviceHeader b; |
|
1702 HintingDevice hinting; |
|
1703 VariationDevice variation; |
|
1704 } u; |
|
1705 public: |
|
1706 DEFINE_SIZE_UNION (6, b); |
|
1707 }; |
|
1708 |
1238 |
1709 |
1239 } /* namespace OT */ |
1710 } /* namespace OT */ |
1240 |
1711 |
1241 |
1712 |
1242 #endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */ |
1713 #endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */ |