ReactOS 0.4.17-dev-934-g091855f
opentype.c
Go to the documentation of this file.
1/*
2 * Methods for dealing with opentype font tables
3 *
4 * Copyright 2014 Aric Stewart for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#define COBJMACROS
22
23#include <stdint.h>
24#include "dwrite_private.h"
25
27
28#define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
29#define MS_HHEA_TAG DWRITE_MAKE_OPENTYPE_TAG('h','h','e','a')
30#define MS_OTTO_TAG DWRITE_MAKE_OPENTYPE_TAG('O','T','T','O')
31#define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
32#define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
33#define MS_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f')
34#define MS_GDEF_TAG DWRITE_MAKE_OPENTYPE_TAG('G','D','E','F')
35#define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
36#define MS_GLYF_TAG DWRITE_MAKE_OPENTYPE_TAG('g','l','y','f')
37#define MS_CFF__TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F',' ')
38#define MS_CFF2_TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F','2')
39#define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
40#define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
41#define MS_SVG__TAG DWRITE_MAKE_OPENTYPE_TAG('S','V','G',' ')
42#define MS_SBIX_TAG DWRITE_MAKE_OPENTYPE_TAG('s','b','i','x')
43#define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p')
44#define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C')
45#define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
46#define MS_META_TAG DWRITE_MAKE_OPENTYPE_TAG('m','e','t','a')
47#define MS_KERN_TAG DWRITE_MAKE_OPENTYPE_TAG('k','e','r','n')
48#define MS_FVAR_TAG DWRITE_MAKE_OPENTYPE_TAG('f','v','a','r')
49
50/* 'sbix' formats */
51#define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ')
52#define MS_JPG__TAG DWRITE_MAKE_OPENTYPE_TAG('j','p','g',' ')
53#define MS_TIFF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','i','f','f')
54
55#define MS_WOFF_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','F')
56#define MS_WOF2_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','2')
57
58/* 'meta' tags */
59#define MS_DLNG_TAG DWRITE_MAKE_OPENTYPE_TAG('d','l','n','g')
60#define MS_SLNG_TAG DWRITE_MAKE_OPENTYPE_TAG('s','l','n','g')
61
62#ifdef WORDS_BIGENDIAN
63#define GET_BE_WORD(x) (x)
64#define GET_BE_DWORD(x) (x)
65#define GET_BE_FIXED(x) (x / 65536.0f)
66#else
67#define GET_BE_WORD(x) RtlUshortByteSwap(x)
68#define GET_BE_DWORD(x) RtlUlongByteSwap(x)
69#define GET_BE_FIXED(x) ((int32_t)GET_BE_DWORD(x) / 65536.0f)
70#endif
71
72#define GLYPH_CONTEXT_MAX_LENGTH 64
73#define SHAPE_MAX_NESTING_LEVEL 6
74
76{
82};
83
85{
91};
92
94{
99};
100
102{
106};
107
109{
113};
114
116{
120
122{
124};
125
127{
131};
132
133/* PANOSE is 10 bytes in size, need to pack the structure properly */
134#include "pshpack2.h"
136{
155};
156
158{
166};
167
169{
179};
180
181struct tt_os2
182{
208 /* According to the Apple spec, original version didn't have the below fields,
209 * version numbers were taken from the OpenType spec.
210 */
211 /* version 0 (TrueType 1.5) */
217 /* version 1 (TrueType 1.66) */
220 /* version 2 (OpenType 1.2) */
226};
227
229{
245};
246
248{
253};
254
256{
260};
261
263{
268};
269
270struct maxp
271{
274};
275
277{
281};
282
284{
297};
298
300{
313};
314
316{
319};
320
322{
326};
327
340
342{
349};
350
352{
357};
358
360{
364};
365
367{
372};
373
375{
379};
380
382{
387};
388
390{
393};
394
396{
399};
400
402{
403 uint16_t lookup_order; /* Reserved */
407};
408
410{
413};
414
416{
420};
421
423{
426};
427
429{
432};
433
435{
442};
443
445{
453};
454
456{
461};
462
464{
468};
469
471{
475};
476
478{
482};
483
485{
491};
492
494{
495 LOOKUP_FLAG_RTL = 0x1, /* Only used for GPOS cursive attachments. */
496
500 LOOKUP_FLAG_IGNORE_MASK = 0xe, /* Combined LOOKUP_FLAG_IGNORE_* flags. */
501
504};
505
507{
511};
512
514{
518
523
524 GLYPH_PROP_MARK_ATTACH_CLASS_MASK = 0xff00, /* Used with LOOKUP_FLAG_MARK_ATTACHMENT_TYPE. */
526};
527
529{
539};
540
542{
551};
552
554{
563};
564
566{
573
575{
579};
580
582{
586};
587
589{
594};
595
597{
602};
603
605{
610};
611
613{
618};
619
621{
624};
625
627{
631};
632
634{
639};
640
642{
645};
646
648{
652};
653
655{
658};
659
661{
666};
667
668#define GLYPH_NOT_COVERED (~0u)
669
671{
675};
676
678{
682};
683
685{
689};
690
692{
697};
698
700{
705};
706
708{
714};
715
717{
720};
721
723{
726};
727
729{
736};
737
739{
749};
750
752{
756};
757
759{
764};
765
767{
773};
774
776{
781};
782
784{
787};
788
790{
793};
794
796{
799};
800
802{
809};
810
812{
819};
820
822{
829};
830
832{
835};
836
838{
842};
843
844#include "poppack.h"
845
847{
860
862{
897
899{
1019
1020/* Names are indexed with TT_NAME_MAC_LANGUAGE_ID values */
1021static const char name_mac_langid_to_locale[][10] = {
1022 "en-US",
1023 "fr-FR",
1024 "de-DE",
1025 "it-IT",
1026 "nl-NL",
1027 "sv-SE",
1028 "es-ES",
1029 "da-DA",
1030 "pt-PT",
1031 "no-NO",
1032 "he-IL",
1033 "ja-JP",
1034 "ar-AR",
1035 "fi-FI",
1036 "el-GR",
1037 "is-IS",
1038 "mt-MT",
1039 "tr-TR",
1040 "hr-HR",
1041 "zh-HK",
1042 "ur-PK",
1043 "hi-IN",
1044 "th-TH",
1045 "ko-KR",
1046 "lt-LT",
1047 "pl-PL",
1048 "hu-HU",
1049 "et-EE",
1050 "lv-LV",
1051 "se-NO",
1052 "fo-FO",
1053 "fa-IR",
1054 "ru-RU",
1055 "zh-CN",
1056 "nl-BE",
1057 "gd-GB",
1058 "sq-AL",
1059 "ro-RO",
1060 "cs-CZ",
1061 "sk-SK",
1062 "sl-SI",
1063 "",
1064 "sr-Latn",
1065 "mk-MK",
1066 "bg-BG",
1067 "uk-UA",
1068 "be-BY",
1069 "uz-Latn",
1070 "kk-KZ",
1071 "az-Cyrl-AZ",
1072 "az-AZ",
1073 "hy-AM",
1074 "ka-GE",
1075 "",
1076 "",
1077 "tg-TJ",
1078 "tk-TM",
1079 "mn-Mong",
1080 "mn-MN",
1081 "ps-AF",
1082 "ku-Arab",
1083 "",
1084 "sd-Arab",
1085 "bo-CN",
1086 "ne-NP",
1087 "sa-IN",
1088 "mr-IN",
1089 "bn-IN",
1090 "as-IN",
1091 "gu-IN",
1092 "pa-Arab",
1093 "or-IN",
1094 "ml-IN",
1095 "kn-IN",
1096 "ta-LK",
1097 "te-IN",
1098 "si-LK",
1099 "",
1100 "km-KH",
1101 "lo-LA",
1102 "vi-VN",
1103 "id-ID",
1104 "",
1105 "ms-MY",
1106 "ms-Arab",
1107 "am-ET",
1108 "ti-ET",
1109 "",
1110 "",
1111 "sw-KE",
1112 "rw-RW",
1113 "",
1114 "",
1115 "",
1116 "",
1117 "",
1118 "",
1119 "",
1120 "",
1121 "",
1122 "",
1123 "",
1124 "",
1125 "",
1126 "",
1127 "",
1128 "",
1129 "",
1130 "",
1131 "",
1132 "",
1133 "",
1134 "",
1135 "",
1136 "",
1137 "",
1138 "",
1139 "",
1140 "",
1141 "",
1142 "",
1143 "",
1144 "",
1145 "",
1146 "",
1147 "",
1148 "",
1149 "",
1150 "cy-GB",
1151 "eu-ES",
1152 "ca-ES",
1153 "",
1154 "",
1155 "",
1156 "",
1157 "tt-RU",
1158 "ug-CN",
1159 "",
1160 "",
1161 "",
1162 "gl-ES",
1163 "af-ZA",
1164 "br-FR",
1165 "iu-Latn-CA",
1166 "gd-GB",
1167 "",
1168 "ga-IE",
1169 "",
1170 "",
1171 "kl-GL",
1172 "az-Latn"
1173};
1174
1176{
1201
1203{
1204 (UINT16)-1, /* DWRITE_INFORMATIONAL_STRING_NONE is not used */
1224};
1225
1226/* CPAL table */
1228{
1235};
1236
1238{
1243};
1244
1245/* COLR table */
1247{
1253};
1254
1256{
1260};
1261
1263{
1266};
1267
1269{
1273};
1274
1276{
1282};
1283
1285{
1294};
1295
1297{
1304};
1305
1306static const void *table_read_ensure(const struct dwrite_fonttable *table, unsigned int offset, unsigned int size)
1307{
1308 if (size > table->size || offset > table->size - size)
1309 return NULL;
1310
1311 return table->data + offset;
1312}
1313
1314static WORD table_read_be_word(const struct dwrite_fonttable *table, unsigned int offset)
1315{
1316 const WORD *ptr = table_read_ensure(table, offset, sizeof(*ptr));
1317 return ptr ? GET_BE_WORD(*ptr) : 0;
1318}
1319
1320static DWORD table_read_be_dword(const struct dwrite_fonttable *table, unsigned int offset)
1321{
1322 const DWORD *ptr = table_read_ensure(table, offset, sizeof(*ptr));
1323 return ptr ? GET_BE_DWORD(*ptr) : 0;
1324}
1325
1326static float table_read_be_fixed(const struct dwrite_fonttable *table, unsigned int offset)
1327{
1328 return (int32_t)table_read_be_dword(table, offset) / 65536.0;
1329}
1330
1331static DWORD table_read_dword(const struct dwrite_fonttable *table, unsigned int offset)
1332{
1333 const DWORD *ptr = table_read_ensure(table, offset, sizeof(*ptr));
1334 return ptr ? *ptr : 0;
1335}
1336
1338{
1339 return (type == DWRITE_FONT_FACE_TYPE_CFF) ||
1343}
1344
1346 DWRITE_FONT_FACE_TYPE *face_type);
1347
1349 DWRITE_FONT_FACE_TYPE *face_type)
1350{
1351 const struct ttc_header *header;
1352 void *context;
1353 HRESULT hr;
1354
1355 hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&header, 0, sizeof(header), &context);
1356 if (FAILED(hr))
1357 return hr;
1358
1359 if (header->tag == MS_TTCF_TAG)
1360 {
1361 *font_count = GET_BE_DWORD(header->num_fonts);
1364 }
1365
1366 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1367
1369}
1370
1372 DWRITE_FONT_FACE_TYPE *face_type)
1373{
1374 const DWORD *header;
1375 void *context;
1376 HRESULT hr;
1377
1378 hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&header, 0, sizeof(*header), &context);
1379 if (FAILED(hr))
1380 return hr;
1381
1382 if (GET_BE_DWORD(*header) == 0x10000) {
1383 *font_count = 1;
1385 *face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE;
1386 }
1387
1388 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1389
1391}
1392
1394 DWRITE_FONT_FACE_TYPE *face_type)
1395{
1396 const DWORD *header;
1397 void *context;
1398 HRESULT hr;
1399
1400 hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&header, 0, sizeof(*header), &context);
1401 if (FAILED(hr))
1402 return hr;
1403
1404 if (GET_BE_DWORD(*header) == MS_OTTO_TAG) {
1405 *font_count = 1;
1407 *face_type = DWRITE_FONT_FACE_TYPE_CFF;
1408 }
1409
1410 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1411
1413}
1414
1416 DWRITE_FONT_FACE_TYPE *face_type)
1417{
1418#include "pshpack1.h"
1419 /* Specified in Adobe TechNote #5178 */
1420 struct pfm_header {
1421 WORD dfVersion;
1422 DWORD dfSize;
1423 char data0[95];
1424 DWORD dfDevice;
1425 char data1[12];
1426 };
1427#include "poppack.h"
1428 struct type1_header {
1429 WORD tag;
1430 char data[14];
1431 };
1432 const struct type1_header *header;
1433 void *context;
1434 HRESULT hr;
1435
1436 hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&header, 0, sizeof(*header), &context);
1437 if (FAILED(hr))
1438 return hr;
1439
1440 /* tag is followed by plain text section */
1441 if (header->tag == 0x8001 &&
1442 (!memcmp(header->data, "%!PS-AdobeFont", 14) ||
1443 !memcmp(header->data, "%!FontType", 10))) {
1444 *font_count = 1;
1446 *face_type = DWRITE_FONT_FACE_TYPE_TYPE1;
1447 }
1448
1449 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1450
1451 /* let's see if it's a .pfm metrics file */
1453 const struct pfm_header *pfm_header;
1454 UINT64 filesize;
1455 DWORD offset;
1456 BOOL header_checked;
1457
1458 hr = IDWriteFontFileStream_GetFileSize(stream, &filesize);
1459 if (FAILED(hr))
1460 return hr;
1461
1462 hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&pfm_header, 0, sizeof(*pfm_header), &context);
1463 if (FAILED(hr))
1464 return hr;
1465
1466 offset = pfm_header->dfDevice;
1467 header_checked = pfm_header->dfVersion == 0x100 && pfm_header->dfSize == filesize;
1468 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1469
1470 /* as a last test check static string in PostScript information section */
1471 if (header_checked) {
1472 static const char postscript[] = "PostScript";
1473 char *devtype_name;
1474
1475 hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&devtype_name, offset, sizeof(postscript), &context);
1476 if (FAILED(hr))
1477 return hr;
1478
1479 if (!memcmp(devtype_name, postscript, sizeof(postscript))) {
1480 *font_count = 1;
1482 *face_type = DWRITE_FONT_FACE_TYPE_TYPE1;
1483 }
1484
1485 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1486 }
1487 }
1488
1490}
1491
1494{
1495 static dwrite_fontfile_analyzer fontfile_analyzers[] = {
1500 NULL
1501 };
1502 dwrite_fontfile_analyzer *analyzer = fontfile_analyzers;
1504 HRESULT hr;
1505
1506 if (!face_type)
1507 face_type = &face;
1508
1510 *face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1511 *face_count = 0;
1512
1513 while (*analyzer) {
1514 hr = (*analyzer)(stream, face_count, file_type, face_type);
1515 if (FAILED(hr))
1516 return hr;
1517
1518 if (hr == S_OK)
1519 break;
1520
1521 analyzer++;
1522 }
1523
1524 *supported = is_face_type_supported(*face_type);
1525 return S_OK;
1526}
1527
1529 void **table_context, UINT32 *table_size, BOOL *found)
1530{
1531 void *table_directory_context, *sfnt_context;
1532 const struct ot_table_record *table_record = NULL;
1533 const struct ot_table_dir *table_dir = NULL;
1534 UINT32 table_offset = 0;
1535 UINT16 table_count;
1536 HRESULT hr;
1537
1538 if (found) *found = FALSE;
1539 if (table_size) *table_size = 0;
1540
1541 *table_data = NULL;
1542 *table_context = NULL;
1543
1545 {
1546 const struct ttc_header *ttc_header;
1547 void * ttc_context;
1548
1549 hr = IDWriteFontFileStream_ReadFileFragment(stream_desc->stream, (const void **)&ttc_header, 0,
1550 sizeof(*ttc_header), &ttc_context);
1551 if (SUCCEEDED(hr))
1552 {
1553 if (stream_desc->face_index >= GET_BE_DWORD(ttc_header->num_fonts))
1554 hr = E_INVALIDARG;
1555 else
1556 {
1557 table_offset = GET_BE_DWORD(ttc_header->offsets[stream_desc->face_index]);
1558 hr = IDWriteFontFileStream_ReadFileFragment(stream_desc->stream, (const void **)&table_dir, table_offset,
1559 sizeof(*table_dir), &sfnt_context);
1560 }
1561 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, ttc_context);
1562 }
1563 }
1564 else
1565 hr = IDWriteFontFileStream_ReadFileFragment(stream_desc->stream, (const void **)&table_dir, 0,
1566 sizeof(*table_dir), &sfnt_context);
1567
1568 if (FAILED(hr))
1569 return hr;
1570
1571 table_count = GET_BE_WORD(table_dir->numTables);
1572 table_offset += sizeof(*table_dir);
1573
1574 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, sfnt_context);
1575
1576 hr = IDWriteFontFileStream_ReadFileFragment(stream_desc->stream, (const void **)&table_record, table_offset,
1577 table_count * sizeof(*table_record), &table_directory_context);
1578 if (hr == S_OK)
1579 {
1580 UINT16 i;
1581
1582 for (i = 0; i < table_count; ++i)
1583 {
1584 if (table_record->tag == tag)
1585 {
1586 UINT32 offset = GET_BE_DWORD(table_record->offset);
1587 UINT32 length = GET_BE_DWORD(table_record->length);
1588
1589 if (found)
1590 *found = TRUE;
1591 if (table_size)
1592 *table_size = length;
1593 hr = IDWriteFontFileStream_ReadFileFragment(stream_desc->stream, table_data, offset,
1594 length, table_context);
1595 break;
1596 }
1597 table_record++;
1598 }
1599
1600 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, table_directory_context);
1601 }
1602
1603 return hr;
1604}
1605
1607 struct dwrite_fonttable *table)
1608{
1609 return opentype_try_get_font_table(stream_desc, tag, (const void **)&table->data, &table->context, &table->size, &table->exists);
1610}
1611
1612/**********
1613 * CMAP
1614 **********/
1615
1616static UINT16 opentype_cmap_format0_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
1617{
1618 const UINT8 *glyphs = cmap->data;
1619 return (ch < 0xff) ? glyphs[ch] : 0;
1620}
1621
1622static unsigned int opentype_cmap_format0_get_ranges(const struct dwrite_cmap *cmap, unsigned int count,
1623 DWRITE_UNICODE_RANGE *ranges)
1624{
1625 if (count > 0)
1626 {
1627 ranges->first = 0;
1628 ranges->last = 255;
1629 }
1630
1631 return 1;
1632}
1633
1635{
1636 const struct dwrite_cmap *cmap;
1637 unsigned int ch;
1638};
1639
1640static int __cdecl cmap_format4_compare_range(const void *a, const void *b)
1641{
1642 const struct cmap_format4_compare_context *key = a;
1643 const UINT16 *end = b;
1644 unsigned int idx;
1645
1646 if (key->ch > GET_BE_WORD(*end))
1647 return 1;
1648
1649 idx = end - key->cmap->u.format4.ends;
1650 if (key->ch < GET_BE_WORD(key->cmap->u.format4.starts[idx]))
1651 return -1;
1652
1653 return 0;
1654}
1655
1656static UINT16 opentype_cmap_format4_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
1657{
1658 struct cmap_format4_compare_context key = { .cmap = cmap, .ch = ch };
1659 unsigned int glyph, idx, range_offset;
1660 const UINT16 *end_found;
1661
1662 /* Look up range. */
1663 end_found = bsearch(&key, cmap->u.format4.ends, cmap->u.format4.seg_count, sizeof(*cmap->u.format4.ends),
1665 if (!end_found)
1666 return 0;
1667
1668 idx = end_found - cmap->u.format4.ends;
1669
1670 range_offset = GET_BE_WORD(cmap->u.format4.id_range_offset[idx]);
1671
1672 if (!range_offset)
1673 {
1674 glyph = ch + GET_BE_WORD(cmap->u.format4.id_delta[idx]);
1675 }
1676 else
1677 {
1678 unsigned int index = range_offset / 2 + (ch - GET_BE_WORD(cmap->u.format4.starts[idx])) + idx - cmap->u.format4.seg_count;
1679 if (index >= cmap->u.format4.glyph_id_array_len)
1680 return 0;
1681 glyph = GET_BE_WORD(cmap->u.format4.glyph_id_array[index]);
1682 if (!glyph)
1683 return 0;
1684 glyph += GET_BE_WORD(cmap->u.format4.id_delta[idx]);
1685 }
1686
1687 return glyph & 0xffff;
1688}
1689
1690static unsigned int opentype_cmap_format4_get_ranges(const struct dwrite_cmap *cmap, unsigned int count,
1691 DWRITE_UNICODE_RANGE *ranges)
1692{
1693 unsigned int i;
1694
1695 count = min(count, cmap->u.format4.seg_count);
1696
1697 for (i = 0; i < count; ++i)
1698 {
1699 ranges[i].first = GET_BE_WORD(cmap->u.format4.starts[i]);
1700 ranges[i].last = GET_BE_WORD(cmap->u.format4.ends[i]);
1701 }
1702
1703 return cmap->u.format4.seg_count;
1704}
1705
1707{
1708 const UINT16 *glyphs = cmap->data;
1709 if (ch < cmap->u.format6_10.first || ch > cmap->u.format6_10.last) return 0;
1710 return glyphs[ch - cmap->u.format6_10.first];
1711}
1712
1713static unsigned int opentype_cmap_format6_10_get_ranges(const struct dwrite_cmap *cmap, unsigned int count,
1714 DWRITE_UNICODE_RANGE *ranges)
1715{
1716 if (count > 0)
1717 {
1718 ranges->first = cmap->u.format6_10.first;
1719 ranges->last = cmap->u.format6_10.last;
1720 }
1721
1722 return 1;
1723}
1724
1725static int __cdecl cmap_format12_13_compare_group(const void *a, const void *b)
1726{
1727 const unsigned int *ch = a;
1728 const UINT32 *group = b;
1729
1730 if (*ch > GET_BE_DWORD(group[1]))
1731 return 1;
1732
1733 if (*ch < GET_BE_DWORD(group[0]))
1734 return -1;
1735
1736 return 0;
1737}
1738
1739static UINT16 opentype_cmap_format12_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
1740{
1741 const UINT32 *groups = cmap->data;
1742 const UINT32 *group_found;
1743
1744 if (!(group_found = bsearch(&ch, groups, cmap->u.format12_13.group_count, 3 * sizeof(*groups),
1746 return 0;
1747
1748 return GET_BE_DWORD(group_found[0]) <= GET_BE_DWORD(group_found[1]) ?
1749 GET_BE_DWORD(group_found[2]) + (ch - GET_BE_DWORD(group_found[0])) : 0;
1750}
1751
1752static unsigned int opentype_cmap_format12_13_get_ranges(const struct dwrite_cmap *cmap, unsigned int count,
1753 DWRITE_UNICODE_RANGE *ranges)
1754{
1755 unsigned int i, group_count = cmap->u.format12_13.group_count;
1756 const UINT32 *groups = cmap->data;
1757
1758 count = min(count, group_count);
1759
1760 for (i = 0; i < count; ++i)
1761 {
1762 ranges[i].first = GET_BE_DWORD(groups[3 * i]);
1763 ranges[i].last = GET_BE_DWORD(groups[3 * i + 1]);
1764 }
1765
1766 return group_count;
1767}
1768
1769static UINT16 opentype_cmap_format13_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
1770{
1771 const UINT32 *groups = cmap->data;
1772 const UINT32 *group_found;
1773
1774 if (!(group_found = bsearch(&ch, groups, cmap->u.format12_13.group_count, 3 * sizeof(*groups),
1776 return 0;
1777
1778 return GET_BE_DWORD(group_found[2]);
1779}
1780
1781static UINT16 opentype_cmap_dummy_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
1782{
1783 return 0;
1784}
1785
1786static unsigned int opentype_cmap_dummy_get_ranges(const struct dwrite_cmap *cmap, unsigned int count,
1787 DWRITE_UNICODE_RANGE *ranges)
1788{
1789 return 0;
1790}
1791
1793{
1794 UINT16 glyph;
1795
1796 if (!cmap->get_glyph) return 0;
1797 glyph = cmap->get_glyph(cmap, ch);
1798 if (!glyph && cmap->symbol && ch <= 0xff)
1799 glyph = cmap->get_glyph(cmap, ch + 0xf000);
1800 return glyph;
1801}
1802
1803static int __cdecl cmap_header_compare(const void *a, const void *b)
1804{
1805 const UINT16 *key = a;
1806 const UINT16 *record = b;
1807
1808 /* Platform. */
1809 if (key[0] < GET_BE_WORD(record[0])) return -1;
1810 if (key[0] > GET_BE_WORD(record[0])) return 1;
1811 /* Encoding. */
1812 if (key[1] < GET_BE_WORD(record[1])) return -1;
1813 if (key[1] > GET_BE_WORD(record[1])) return 1;
1814
1815 return 0;
1816}
1817
1818void dwrite_cmap_init(struct dwrite_cmap *cmap, IDWriteFontFile *file, unsigned int face_index,
1819 DWRITE_FONT_FACE_TYPE face_type)
1820{
1821 static const UINT16 encodings[][2] =
1822 {
1823 { 3, 0 }, /* MS Symbol encoding is preferred. */
1824 { 3, 10 },
1825 { 0, 6 },
1826 { 0, 4 },
1827 { 3, 1 },
1828 { 0, 3 },
1829 { 0, 2 },
1830 { 0, 1 },
1831 { 0, 0 },
1832 };
1833 const struct cmap_encoding_record *records, *found_record = NULL;
1834 unsigned int length, offset, format, count, f, i, num_records;
1835 struct file_stream_desc stream_desc;
1836 struct dwrite_fonttable table;
1837 const UINT16 *pair = NULL;
1838 HRESULT hr;
1839
1840 if (cmap->data) return;
1841
1842 /* For fontface stream is already available and preset. */
1843 if (!cmap->stream && FAILED(hr = get_filestream_from_file(file, &cmap->stream)))
1844 {
1845 WARN("Failed to get file stream, hr %#lx.\n", hr);
1846 goto failed;
1847 }
1848
1849 stream_desc.stream = cmap->stream;
1850 stream_desc.face_type = face_type;
1851 stream_desc.face_index = face_index;
1852
1853 opentype_get_font_table(&stream_desc, MS_CMAP_TAG, &table);
1854 if (!table.exists)
1855 goto failed;
1856 cmap->table_context = table.context;
1857
1858 num_records = table_read_be_word(&table, 2);
1859 records = table_read_ensure(&table, 4, sizeof(*records) * num_records);
1860
1861 for (i = 0; i < ARRAY_SIZE(encodings); ++i)
1862 {
1863 pair = encodings[i];
1864 if ((found_record = bsearch(pair, records, num_records, sizeof(*records), cmap_header_compare)))
1865 break;
1866 }
1867
1868 if (!found_record)
1869 {
1870 WARN("No suitable cmap table were found.\n");
1871 goto failed;
1872 }
1873
1874 /* Symbol encoding. */
1875 cmap->symbol = pair[0] == 3 && pair[1] == 0;
1876 offset = GET_BE_DWORD(found_record->offset);
1877
1879
1880 switch (format)
1881 {
1882 case 0:
1883 cmap->data = table_read_ensure(&table, offset + 6, 256);
1886 break;
1887 case 4:
1889 cmap->u.format4.seg_count = count = table_read_be_word(&table, offset + 6) / 2;
1890 cmap->u.format4.ends = table_read_ensure(&table, offset + 14, count * 2);
1891 cmap->u.format4.starts = cmap->u.format4.ends + count + 1;
1892 cmap->u.format4.id_delta = cmap->u.format4.starts + count;
1893 cmap->u.format4.id_range_offset = cmap->u.format4.id_delta + count;
1894 cmap->u.format4.glyph_id_array = cmap->data = cmap->u.format4.id_range_offset + count;
1895 cmap->u.format4.glyph_id_array_len = (length - 16 - 8 * count) / 2;
1898 break;
1899 case 6:
1900 case 10:
1901 /* Format 10 uses 4 byte fields. */
1902 f = format == 6 ? 1 : 2;
1903 cmap->u.format6_10.first = table_read_be_word(&table, offset + f * 6);
1905 cmap->u.format6_10.last = cmap->u.format6_10.first + count;
1906 cmap->data = table_read_ensure(&table, offset + f * 10, count * 2);
1909 break;
1910 case 12:
1911 case 13:
1912 cmap->u.format12_13.group_count = count = table_read_be_dword(&table, offset + 12);
1913 cmap->data = table_read_ensure(&table, offset + 16, count * 3 * 4);
1916 break;
1917 default:
1918 WARN("Unhandled subtable format %u.\n", format);
1919 }
1920
1921failed:
1922
1923 if (!cmap->data)
1924 {
1925 /* Dummy implementation, returns 0 unconditionally. */
1926 cmap->data = cmap;
1929 }
1930}
1931
1933{
1934 if (cmap->stream)
1935 {
1936 IDWriteFontFileStream_ReleaseFileFragment(cmap->stream, cmap->table_context);
1937 IDWriteFontFileStream_Release(cmap->stream);
1938 }
1939 cmap->data = NULL;
1940 cmap->stream = NULL;
1941}
1942
1944 unsigned int *count)
1945{
1946 if (!cmap->data)
1947 return E_FAIL;
1948
1949 *count = cmap->get_ranges(cmap, max_count, ranges);
1950
1952}
1953
1954void opentype_get_font_typo_metrics(struct file_stream_desc *stream_desc, unsigned int *ascent, unsigned int *descent)
1955{
1956 struct dwrite_fonttable os2;
1957
1958 opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
1959
1960 *ascent = *descent = 0;
1961
1962 if (os2.size >= FIELD_OFFSET(struct tt_os2, sTypoLineGap))
1963 {
1964 SHORT value = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoDescender));
1965 *ascent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoAscender));
1966 *descent = value < 0 ? -value : 0;
1967 }
1968
1969 if (os2.data)
1970 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context);
1971}
1972
1974{
1975 struct dwrite_fonttable os2, head, post, hhea;
1976
1977 memset(metrics, 0, sizeof(*metrics));
1978
1979 opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
1981 opentype_get_font_table(stream_desc, MS_POST_TAG, &post);
1982 opentype_get_font_table(stream_desc, MS_HHEA_TAG, &hhea);
1983
1984 if (head.data)
1985 {
1986 metrics->designUnitsPerEm = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, unitsPerEm));
1987 metrics->glyphBoxLeft = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, xMin));
1988 metrics->glyphBoxTop = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, yMax));
1989 metrics->glyphBoxRight = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, xMax));
1990 metrics->glyphBoxBottom = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, yMin));
1991 }
1992
1993 if (caret)
1994 {
1995 if (hhea.data)
1996 {
1997 caret->slopeRise = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, caretSlopeRise));
1998 caret->slopeRun = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, caretSlopeRun));
1999 caret->offset = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, caretOffset));
2000 }
2001 else
2002 memset(caret, 0, sizeof(*caret));
2003 }
2004
2005 if (os2.data)
2006 {
2008
2009 metrics->ascent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWinAscent));
2010 /* Some fonts have usWinDescent value stored as signed short, which could be wrongly
2011 interpreted as large unsigned value. */
2012 metrics->descent = abs((SHORT)table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWinDescent)));
2013
2014 /* Line gap is estimated using two sets of ascender/descender values and 'hhea' line gap. */
2015 if (hhea.data)
2016 {
2017 SHORT descender = (SHORT)table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, descender));
2018 INT32 linegap;
2019
2020 linegap = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, ascender)) + abs(descender) +
2021 table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, linegap)) - metrics->ascent - metrics->descent;
2022 metrics->lineGap = linegap > 0 ? linegap : 0;
2023 }
2024
2025 metrics->strikethroughPosition = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, yStrikeoutPosition));
2026 metrics->strikethroughThickness = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, yStrikeoutSize));
2027 metrics->subscriptPositionX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptXOffset));
2028 /* Y offset is stored as positive offset below baseline */
2029 metrics->subscriptPositionY = -table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptYOffset));
2030 metrics->subscriptSizeX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptXSize));
2031 metrics->subscriptSizeY = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptYSize));
2032 metrics->superscriptPositionX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptXOffset));
2033 metrics->superscriptPositionY = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptYOffset));
2034 metrics->superscriptSizeX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptXSize));
2035 metrics->superscriptSizeY = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptYSize));
2036
2037 /* version 2 fields */
2038 if (version >= 2)
2039 {
2040 metrics->capHeight = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sCapHeight));
2041 metrics->xHeight = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sxHeight));
2042 }
2043
2045 {
2046 SHORT descent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoDescender));
2047 metrics->ascent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoAscender));
2048 metrics->descent = descent < 0 ? -descent : 0;
2049 metrics->lineGap = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoLineGap));
2050 metrics->hasTypographicMetrics = TRUE;
2051 }
2052 }
2053 else
2054 {
2055 metrics->strikethroughPosition = metrics->designUnitsPerEm / 3;
2056 if (hhea.data)
2057 {
2058 metrics->ascent = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, ascender));
2059 metrics->descent = abs((SHORT)table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, descender)));
2060 }
2061 }
2062
2063 if (post.data)
2064 {
2065 metrics->underlinePosition = table_read_be_word(&post, FIELD_OFFSET(struct tt_post, underlinePosition));
2066 metrics->underlineThickness = table_read_be_word(&post, FIELD_OFFSET(struct tt_post, underlineThickness));
2067 }
2068
2069 if (metrics->underlineThickness == 0)
2070 metrics->underlineThickness = metrics->designUnitsPerEm / 14;
2071 if (metrics->strikethroughThickness == 0)
2072 metrics->strikethroughThickness = metrics->underlineThickness;
2073
2074 /* estimate missing metrics */
2075 if (metrics->xHeight == 0)
2076 metrics->xHeight = metrics->designUnitsPerEm / 2;
2077 if (metrics->capHeight == 0)
2078 metrics->capHeight = metrics->designUnitsPerEm * 7 / 10;
2079
2080 if (os2.data)
2081 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context);
2082 if (head.data)
2083 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, head.context);
2084 if (post.data)
2085 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, post.context);
2086 if (hhea.data)
2087 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, hhea.context);
2088}
2089
2091{
2092 struct dwrite_fonttable os2, head, post, colr, cpal;
2093 BOOL is_symbol, is_monospaced;
2094
2095 opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
2097
2098 memset(props, 0, sizeof(*props));
2099
2100 /* Default stretch, weight and style to normal */
2104
2105 /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
2106 if (os2.data)
2107 {
2109 USHORT fsSelection = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection));
2110 USHORT usWeightClass = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWeightClass));
2111 USHORT usWidthClass = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWidthClass));
2112 const void *panose;
2113
2114 if (usWidthClass > DWRITE_FONT_STRETCH_UNDEFINED && usWidthClass <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
2115 props->stretch = usWidthClass;
2116
2117 if (usWeightClass >= 1 && usWeightClass <= 9)
2118 usWeightClass *= 100;
2119
2120 if (usWeightClass > DWRITE_FONT_WEIGHT_ULTRA_BLACK)
2122 else if (usWeightClass > 0)
2123 props->weight = usWeightClass;
2124
2125 if (version >= 4 && (fsSelection & OS2_FSSELECTION_OBLIQUE))
2127 else if (fsSelection & OS2_FSSELECTION_ITALIC)
2129 props->lf.lfItalic = !!(fsSelection & OS2_FSSELECTION_ITALIC);
2130
2131 if ((panose = table_read_ensure(&os2, FIELD_OFFSET(struct tt_os2, panose), sizeof(props->panose))))
2132 memcpy(&props->panose, panose, sizeof(props->panose));
2133
2134 /* FONTSIGNATURE */
2135 props->fontsig.fsUsb[0] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange1));
2136 props->fontsig.fsUsb[1] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange2));
2137 props->fontsig.fsUsb[2] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange3));
2138 props->fontsig.fsUsb[3] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange4));
2139
2140 if (version)
2141 {
2142 props->fontsig.fsCsb[0] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulCodePageRange1));
2143 props->fontsig.fsCsb[1] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulCodePageRange2));
2144 }
2145 }
2146 else if (head.data)
2147 {
2148 USHORT macStyle = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, macStyle));
2149
2150 if (macStyle & TT_HEAD_MACSTYLE_CONDENSED)
2152 else if (macStyle & TT_HEAD_MACSTYLE_EXTENDED)
2154
2155 if (macStyle & TT_HEAD_MACSTYLE_BOLD)
2157
2158 if (macStyle & TT_HEAD_MACSTYLE_ITALIC) {
2160 props->lf.lfItalic = 1;
2161 }
2162 }
2163
2164 props->lf.lfWeight = props->weight;
2165
2166 /* FONT_IS_SYMBOL */
2167 if (!(is_symbol = props->panose.familyKind == DWRITE_PANOSE_FAMILY_SYMBOL))
2168 {
2169 struct dwrite_fonttable cmap;
2170 int i, offset, num_tables;
2171
2172 opentype_get_font_table(stream_desc, MS_CMAP_TAG, &cmap);
2173
2174 if (cmap.data)
2175 {
2176 num_tables = table_read_be_word(&cmap, FIELD_OFFSET(struct cmap_header, num_tables));
2178
2179 for (i = 0; !is_symbol && i < num_tables; ++i)
2180 {
2181 WORD platform, encoding;
2182
2183 platform = table_read_be_word(&cmap, offset + i * sizeof(struct cmap_encoding_record) +
2184 FIELD_OFFSET(struct cmap_encoding_record, platformID));
2185 encoding = table_read_be_word(&cmap, offset + i * sizeof(struct cmap_encoding_record) +
2186 FIELD_OFFSET(struct cmap_encoding_record, encodingID));
2187
2190 }
2191
2192 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, cmap.context);
2193 }
2194 }
2195 if (is_symbol)
2196 props->flags |= FONT_IS_SYMBOL;
2197
2198 /* FONT_IS_MONOSPACED, slant angle */
2199 opentype_get_font_table(stream_desc, MS_POST_TAG, &post);
2200 is_monospaced = props->panose.text.proportion == DWRITE_PANOSE_PROPORTION_MONOSPACED;
2201 if (post.data)
2202 {
2203 if (!is_monospaced)
2204 is_monospaced = !!table_read_dword(&post, FIELD_OFFSET(struct tt_post, fixed_pitch));
2205 props->slant_angle = table_read_be_fixed(&post, FIELD_OFFSET(struct tt_post, italicAngle));
2206 }
2207 if (post.context)
2208 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, post.context);
2209
2210 if (is_monospaced)
2211 props->flags |= FONT_IS_MONOSPACED;
2212
2213 /* FONT_IS_COLORED */
2214 opentype_get_font_table(stream_desc, MS_COLR_TAG, &colr);
2215 if (colr.data)
2216 {
2217 opentype_get_font_table(stream_desc, MS_CPAL_TAG, &cpal);
2218 if (cpal.data)
2219 {
2220 props->flags |= FONT_IS_COLORED;
2221 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, cpal.context);
2222 }
2223
2224 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, colr.context);
2225 }
2226
2227 TRACE("stretch %d, weight %d, style %d\n", props->stretch, props->weight, props->style);
2228
2229 if (os2.data)
2230 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context);
2231 if (head.data)
2232 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, head.context);
2233}
2234
2236{
2237 UINT codepage = 0;
2238
2239 switch (platform) {
2241 break;
2243 switch (encoding)
2244 {
2246 codepage = 10000;
2247 break;
2249 codepage = 10001;
2250 break;
2252 codepage = 10002;
2253 break;
2255 codepage = 10003;
2256 break;
2258 codepage = 10004;
2259 break;
2261 codepage = 10005;
2262 break;
2264 codepage = 10006;
2265 break;
2267 codepage = 10007;
2268 break;
2270 codepage = 10008;
2271 break;
2273 codepage = 10021;
2274 break;
2275 default:
2276 FIXME("encoding %u not handled, platform %d.\n", encoding, platform);
2277 break;
2278 }
2279 break;
2281 switch (encoding)
2282 {
2286 break;
2288 codepage = 932;
2289 break;
2291 codepage = 936;
2292 break;
2294 codepage = 950;
2295 break;
2297 codepage = 20949;
2298 break;
2300 codepage = 1361;
2301 break;
2302 default:
2303 FIXME("encoding %u not handled, platform %d.\n", encoding, platform);
2304 break;
2305 }
2306 break;
2307 default:
2308 FIXME("unknown platform %d\n", platform);
2309 }
2310
2311 return codepage;
2312}
2313
2315{
2316 switch (platform)
2317 {
2319 {
2320 const char *locale_name = NULL;
2321
2322 if (lang_id > TT_NAME_MAC_LANGID_AZER_ROMAN)
2323 WARN("invalid mac lang id %d\n", lang_id);
2324 else if (!name_mac_langid_to_locale[lang_id][0])
2325 FIXME("failed to map mac lang id %d to locale name\n", lang_id);
2326 else
2328
2329 if (locale_name)
2330 MultiByteToWideChar(CP_ACP, 0, name_mac_langid_to_locale[lang_id], -1, locale, locale_len);
2331 else
2332 wcscpy(locale, L"en-US");
2333 break;
2334 }
2336 if (!LCIDToLocaleName(MAKELCID(lang_id, SORT_DEFAULT), locale, locale_len, 0))
2337 {
2338 FIXME("failed to get locale name for lcid=0x%08lx\n", MAKELCID(lang_id, SORT_DEFAULT));
2339 wcscpy(locale, L"en-US");
2340 }
2341 break;
2343 wcscpy(locale, L"en-US");
2344 break;
2345 default:
2346 FIXME("unknown platform %d\n", platform);
2347 }
2348}
2349
2351{
2352 const struct name_header *header = (const struct name_header *)table->data;
2353 const struct name_record *record;
2354
2355 record = &header->records[idx];
2356
2357 return GET_BE_WORD(record->platformID) == OPENTYPE_PLATFORM_MAC &&
2359}
2360
2361static BOOL opentype_decode_namerecord(const struct dwrite_fonttable *table, unsigned int idx,
2363{
2364 USHORT lang_id, length, offset, encoding, platform;
2365 const struct name_header *header = (const struct name_header *)table->data;
2366 const struct name_record *record;
2367 unsigned int i, string_offset;
2368 BOOL ret = FALSE;
2369 const void *name;
2370
2372
2373 record = &header->records[idx];
2374
2375 platform = GET_BE_WORD(record->platformID);
2376 lang_id = GET_BE_WORD(record->languageID);
2377 length = GET_BE_WORD(record->length);
2378 offset = GET_BE_WORD(record->offset);
2379 encoding = GET_BE_WORD(record->encodingID);
2380
2381 if (!(name = table_read_ensure(table, string_offset + offset, length)))
2382 return FALSE;
2383
2384 if (lang_id < 0x8000)
2385 {
2387 WCHAR *name_string;
2388 UINT codepage;
2389
2392
2393 if (codepage)
2394 {
2396 name_string = malloc(sizeof(WCHAR) * (len+1));
2397 MultiByteToWideChar(codepage, 0, name, length, name_string, len);
2398 name_string[len] = 0;
2399 }
2400 else
2401 {
2402 length /= sizeof(WCHAR);
2403 name_string = heap_strdupnW(name, length);
2404 for (i = 0; i < length; i++)
2405 name_string[i] = GET_BE_WORD(name_string[i]);
2406 }
2407
2408 TRACE("string %s for locale %s found\n", debugstr_w(name_string), debugstr_w(locale));
2409 add_localizedstring(strings, locale, name_string);
2410 free(name_string);
2411
2412 ret = !wcscmp(locale, L"en-US");
2413 }
2414 else
2415 FIXME("handle NAME format 1\n");
2416
2417 return ret;
2418}
2419
2422{
2423 int i, count, candidate_mac, candidate_mac_en, candidate_unicode;
2424 const struct name_record *records;
2425 BOOL has_english;
2426 WORD format;
2427 HRESULT hr;
2428
2429 if (!table->data)
2430 return E_FAIL;
2431
2433 return hr;
2434
2436
2437 if (format != 0 && format != 1)
2438 FIXME("unsupported NAME format %d\n", format);
2439
2441
2442 if (!(records = table_read_ensure(table, FIELD_OFFSET(struct name_header, records),
2443 count * sizeof(struct name_record))))
2444 {
2445 count = 0;
2446 }
2447
2448 has_english = FALSE;
2449 candidate_unicode = candidate_mac = candidate_mac_en = -1;
2450
2451 for (i = 0; i < count; i++)
2452 {
2453 unsigned short platform;
2454
2455 if (GET_BE_WORD(records[i].nameID) != id)
2456 continue;
2457
2458 platform = GET_BE_WORD(records[i].platformID);
2459 switch (platform)
2460 {
2461 /* Skip Unicode or Mac entries for now, fonts tend to duplicate those
2462 strings as WIN platform entries. If font does not have WIN entry for
2463 this id, we will use Mac or Unicode platform entry while assuming
2464 en-US locale. */
2466 if (candidate_unicode == -1)
2467 candidate_unicode = i;
2468 break;
2470 if (candidate_mac == -1)
2471 candidate_mac = i;
2472 if (candidate_mac_en == -1 && opentype_is_english_namerecord(table, i))
2473 candidate_mac_en = i;
2474 break;
2476 has_english |= opentype_decode_namerecord(table, i, *strings);
2477 break;
2478 default:
2479 FIXME("platform %i not supported\n", platform);
2480 break;
2481 }
2482 }
2483
2484 if (!get_localizedstrings_count(*strings) && candidate_mac != -1)
2485 has_english |= opentype_decode_namerecord(table, candidate_mac, *strings);
2486 if (!get_localizedstrings_count(*strings) && candidate_unicode != -1)
2487 has_english |= opentype_decode_namerecord(table, candidate_unicode, *strings);
2488 if (!has_english && candidate_mac_en != -1)
2489 opentype_decode_namerecord(table, candidate_mac_en, *strings);
2490
2492 {
2493 IDWriteLocalizedStrings_Release(*strings);
2494 *strings = NULL;
2495 }
2496
2497 if (*strings)
2499
2500 return *strings ? S_OK : E_FAIL;
2501}
2502
2504{
2505 WCHAR *ret;
2506
2507 if (!str) str = *ctx;
2508 while (*str && wcschr(L", ", *str)) str++;
2509 if (!*str) return NULL;
2510 ret = str++;
2511 while (*str && !wcschr(L", ", *str)) str++;
2512 if (*str) *str++ = 0;
2513 *ctx = str;
2514
2515 return ret;
2516}
2517
2520{
2521 const struct meta_data_map *maps;
2523 struct dwrite_fonttable meta;
2524 DWORD version, i, count, tag;
2525 HRESULT hr;
2526
2527 *ret = NULL;
2528
2529 switch (id)
2530 {
2532 tag = MS_DLNG_TAG;
2533 break;
2535 tag = MS_SLNG_TAG;
2536 break;
2537 default:
2538 WARN("Unexpected id %d.\n", id);
2539 return S_OK;
2540 }
2541
2543 return hr;
2544
2545 opentype_get_font_table(stream_desc, MS_META_TAG, &meta);
2546
2547 if (meta.data)
2548 {
2549 version = table_read_be_dword(&meta, 0);
2550 if (version != 1)
2551 {
2552 WARN("Unexpected meta table version %ld.\n", version);
2553 goto end;
2554 }
2555
2556 count = table_read_be_dword(&meta, FIELD_OFFSET(struct meta_header, data_maps_count));
2557 if (!(maps = table_read_ensure(&meta, FIELD_OFFSET(struct meta_header, maps),
2558 count * sizeof(struct meta_data_map))))
2559 goto end;
2560
2561 for (i = 0; i < count; ++i)
2562 {
2563 const char *data;
2564
2565 if (maps[i].tag == tag && maps[i].length)
2566 {
2567 DWORD length = GET_BE_DWORD(maps[i].length), j;
2568
2569 if ((data = table_read_ensure(&meta, GET_BE_DWORD(maps[i].offset), length)))
2570 {
2571 WCHAR *ptrW, *ctx, *token;
2572
2573 if (!(ptrW = malloc((length + 1) * sizeof(WCHAR))))
2574 {
2575 hr = E_OUTOFMEMORY;
2576 goto end;
2577 }
2578
2579 /* Data is stored in comma separated list, ASCII range only. */
2580 for (j = 0; j < length; ++j)
2581 ptrW[j] = data[j];
2582 ptrW[length] = 0;
2583
2584 token = meta_get_lng_name(ptrW, &ctx);
2585
2586 while (token)
2587 {
2590 }
2591
2592 free(ptrW);
2593 }
2594 }
2595 }
2596end:
2597 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, meta.context);
2598 }
2599
2600 if (IDWriteLocalizedStrings_GetCount(strings))
2601 *ret = strings;
2602 else
2603 IDWriteLocalizedStrings_Release(strings);
2604
2605 return hr;
2606}
2607
2610{
2611 struct dwrite_fonttable name;
2612
2613 switch (id)
2614 {
2618 break;
2619 default:
2622 if (name.context)
2623 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, name.context);
2624 }
2625
2626 return S_OK;
2627}
2628
2631{
2632 static const unsigned int wws_candidates[] =
2633 {
2637 ~0u,
2638 };
2639 static const unsigned int typographic_candidates[] =
2640 {
2644 ~0u,
2645 };
2646 struct dwrite_fonttable os2, name;
2647 const unsigned int *id;
2648 BOOL try_wws_name;
2649 HRESULT hr;
2650
2651 opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
2653
2654 *names = NULL;
2655
2656 if (family_model == DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC)
2657 {
2658 id = typographic_candidates;
2659 }
2660 else
2661 {
2662 /* FamilyName locating order is WWS Family Name -> Preferred Family Name -> Family Name. If font claims to
2663 have 'Preferred Family Name' in WWS format, then WWS name is not used. */
2664
2665 opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
2666 /* If Preferred Family doesn't conform to WWS model try WWS name. */
2667 try_wws_name = os2.data && !(table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection)) & OS2_FSSELECTION_WWS);
2668 if (os2.context)
2669 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context);
2670
2671 id = wws_candidates;
2672 if (!try_wws_name) id++;
2673 }
2674
2675 while (*id != ~0u)
2676 {
2678 break;
2679 id++;
2680 }
2681
2682 if (name.context)
2683 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, name.context);
2684
2685 return hr;
2686}
2687
2688/* FaceName locating order is WWS Face Name -> Preferred Face Name -> Face Name. If font claims to
2689 have 'Preferred Face Name' in WWS format, then WWS name is not used. */
2691{
2692 struct dwrite_fonttable os2, name;
2693 IDWriteLocalizedStrings *lfnames;
2694 UINT16 fsselection;
2695 HRESULT hr;
2696
2697 opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
2699
2700 *names = NULL;
2701
2702 /* if Preferred Family doesn't conform to WWS model try WWS name */
2703 fsselection = os2.data ? table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection)) : 0;
2704 if (os2.data && !(fsselection & OS2_FSSELECTION_WWS))
2706 else
2707 hr = E_FAIL;
2708
2709 if (FAILED(hr))
2711 if (FAILED(hr))
2713
2714 /* User locale is preferred, with fallback to en-us. */
2715 *lfname = 0;
2717 {
2719 UINT32 index;
2720 BOOL exists;
2721
2722 exists = FALSE;
2724 IDWriteLocalizedStrings_FindLocaleName(lfnames, localeW, &index, &exists);
2725
2726 if (!exists)
2727 IDWriteLocalizedStrings_FindLocaleName(lfnames, L"en-us", &index, &exists);
2728
2729 if (exists) {
2730 UINT32 length = 0;
2731 WCHAR *nameW;
2732
2733 IDWriteLocalizedStrings_GetStringLength(lfnames, index, &length);
2734 nameW = malloc((length + 1) * sizeof(WCHAR));
2735 if (nameW)
2736 {
2737 *nameW = 0;
2738 IDWriteLocalizedStrings_GetString(lfnames, index, nameW, length + 1);
2739 lstrcpynW(lfname, nameW, LF_FACESIZE);
2740 free(nameW);
2741 }
2742 }
2743
2744 IDWriteLocalizedStrings_Release(lfnames);
2745 }
2746
2747 if (os2.context)
2748 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context);
2749 if (name.context)
2750 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, name.context);
2751
2752 return hr;
2753}
2754
2755static const struct ot_langsys *opentype_get_langsys(const struct ot_gsubgpos_table *table, unsigned int script_index,
2756 unsigned int language_index, unsigned int *feature_count)
2757{
2758 unsigned int table_offset, langsys_offset;
2759 const struct ot_langsys *langsys = NULL;
2760
2761 *feature_count = 0;
2762
2763 if (!table->table.data || script_index == ~0u)
2764 return NULL;
2765
2766 /* ScriptTable offset. */
2767 table_offset = table_read_be_word(&table->table, table->script_list + FIELD_OFFSET(struct ot_script_list, scripts) +
2768 script_index * sizeof(struct ot_script_record) + FIELD_OFFSET(struct ot_script_record, script));
2769 if (!table_offset)
2770 return NULL;
2771
2772 if (language_index == ~0u)
2773 langsys_offset = table_read_be_word(&table->table, table->script_list + table_offset);
2774 else
2775 langsys_offset = table_read_be_word(&table->table, table->script_list + table_offset +
2776 FIELD_OFFSET(struct ot_script, langsys) + language_index * sizeof(struct ot_langsys_record) +
2777 FIELD_OFFSET(struct ot_langsys_record, langsys));
2778 langsys_offset += table->script_list + table_offset;
2779
2780 *feature_count = table_read_be_word(&table->table, langsys_offset + FIELD_OFFSET(struct ot_langsys, feature_count));
2781 if (*feature_count)
2782 langsys = table_read_ensure(&table->table, langsys_offset, FIELD_OFFSET(struct ot_langsys, feature_index[*feature_count]));
2783 if (!langsys)
2784 *feature_count = 0;
2785
2786 return langsys;
2787}
2788
2789void opentype_get_typographic_features(struct ot_gsubgpos_table *table, unsigned int script_index,
2790 unsigned int language_index, struct tag_array *t)
2791{
2792 unsigned int i, total_feature_count, script_feature_count;
2793 const struct ot_feature_list *feature_list;
2794 const struct ot_langsys *langsys = NULL;
2795
2796 langsys = opentype_get_langsys(table, script_index, language_index, &script_feature_count);
2797
2798 total_feature_count = table_read_be_word(&table->table, table->feature_list);
2799 if (!total_feature_count)
2800 return;
2801
2802 feature_list = table_read_ensure(&table->table, table->feature_list,
2803 FIELD_OFFSET(struct ot_feature_list, features[total_feature_count]));
2804 if (!feature_list)
2805 return;
2806
2807 for (i = 0; i < script_feature_count; ++i)
2808 {
2809 unsigned int feature_index = GET_BE_WORD(langsys->feature_index[i]);
2810 if (feature_index >= total_feature_count)
2811 continue;
2812
2813 if (!dwrite_array_reserve((void **)&t->tags, &t->capacity, t->count + 1, sizeof(*t->tags)))
2814 return;
2815
2816 t->tags[t->count++] = feature_list->features[feature_index].tag;
2817 }
2818}
2819
2820static unsigned int find_vdmx_group(const struct vdmx_header *hdr)
2821{
2822 WORD num_ratios, i;
2823 const struct vdmx_ratio *ratios = (struct vdmx_ratio *)(hdr + 1);
2824 BYTE dev_x_ratio = 1, dev_y_ratio = 1;
2825 unsigned int group_offset = 0;
2826
2827 num_ratios = GET_BE_WORD(hdr->num_ratios);
2828
2829 for (i = 0; i < num_ratios; i++) {
2830
2831 if (!ratios[i].bCharSet) continue;
2832
2833 if ((ratios[i].xRatio == 0 && ratios[i].yStartRatio == 0 &&
2834 ratios[i].yEndRatio == 0) ||
2835 (ratios[i].xRatio == dev_x_ratio && ratios[i].yStartRatio <= dev_y_ratio &&
2836 ratios[i].yEndRatio >= dev_y_ratio))
2837 {
2838 group_offset = GET_BE_WORD(*((WORD *)(ratios + num_ratios) + i));
2839 break;
2840 }
2841 }
2842
2843 return group_offset;
2844}
2845
2846BOOL opentype_get_vdmx_size(const struct dwrite_fonttable *vdmx, INT emsize, UINT16 *ascent, UINT16 *descent)
2847{
2848 unsigned int num_ratios, num_recs, group_offset, i;
2849 const struct vdmx_header *header;
2850 const struct vdmx_group *group;
2851
2852 if (!vdmx->exists)
2853 return FALSE;
2854
2855 num_ratios = table_read_be_word(vdmx, FIELD_OFFSET(struct vdmx_header, num_ratios));
2856 num_recs = table_read_be_word(vdmx, FIELD_OFFSET(struct vdmx_header, num_recs));
2857
2858 header = table_read_ensure(vdmx, 0, sizeof(*header) + num_ratios * sizeof(struct vdmx_ratio) +
2859 num_recs * sizeof(*group));
2860
2861 if (!header)
2862 return FALSE;
2863
2864 group_offset = find_vdmx_group(header);
2865 if (!group_offset)
2866 return FALSE;
2867
2868 num_recs = table_read_be_word(vdmx, group_offset);
2869 group = table_read_ensure(vdmx, group_offset, FIELD_OFFSET(struct vdmx_group, entries[num_recs]));
2870
2871 if (!group)
2872 return FALSE;
2873
2874 if (emsize < group->startsz || emsize >= group->endsz)
2875 return FALSE;
2876
2877 for (i = 0; i < num_recs; ++i)
2878 {
2879 WORD ppem = GET_BE_WORD(group->entries[i].yPelHeight);
2880 if (ppem > emsize) {
2881 FIXME("interpolate %d\n", emsize);
2882 return FALSE;
2883 }
2884
2885 if (ppem == emsize) {
2886 *ascent = (SHORT)GET_BE_WORD(group->entries[i].yMax);
2887 *descent = -(SHORT)GET_BE_WORD(group->entries[i].yMin);
2888 return TRUE;
2889 }
2890 }
2891
2892 return FALSE;
2893}
2894
2895unsigned int opentype_get_gasp_flags(const struct dwrite_fonttable *gasp, float emsize)
2896{
2897 unsigned int version, num_ranges, i;
2898 const struct gasp_header *table;
2899 WORD flags = 0;
2900
2901 if (!gasp->exists)
2902 return 0;
2903
2905
2907 if (!table)
2908 return 0;
2909
2910 version = GET_BE_WORD(table->version);
2911 if (version > 1)
2912 {
2913 ERR("Unsupported gasp table format version %u.\n", version);
2914 goto done;
2915 }
2916
2917 for (i = 0; i < num_ranges; ++i)
2918 {
2919 flags = GET_BE_WORD(table->ranges[i].flags);
2920 if (emsize <= GET_BE_WORD(table->ranges[i].max_ppem)) break;
2921 }
2922
2923done:
2924 return flags;
2925}
2926
2927unsigned int opentype_get_cpal_palettecount(const struct dwrite_fonttable *cpal)
2928{
2929 return table_read_be_word(cpal, FIELD_OFFSET(struct cpal_header_0, num_palettes));
2930}
2931
2933{
2934 return table_read_be_word(cpal, FIELD_OFFSET(struct cpal_header_0, num_palette_entries));
2935}
2936
2938 unsigned int first_entry_index, unsigned int entry_count, DWRITE_COLOR_F *entries)
2939{
2940 unsigned int num_palettes, num_palette_entries, i;
2941 const struct cpal_color_record *records;
2942 const struct cpal_header_0 *header;
2943 struct d3d_color
2944 {
2945 float r;
2946 float g;
2947 float b;
2948 float a;
2949 } *colors = (void *)entries;
2950
2951 header = table_read_ensure(cpal, 0, sizeof(*header));
2952
2953 if (!cpal->exists || !header)
2954 return DWRITE_E_NOCOLOR;
2955
2956 num_palettes = GET_BE_WORD(header->num_palettes);
2957 if (palette >= num_palettes)
2958 return DWRITE_E_NOCOLOR;
2959
2960 header = table_read_ensure(cpal, 0, FIELD_OFFSET(struct cpal_header_0, color_record_indices[palette]));
2961 if (!header)
2962 return DWRITE_E_NOCOLOR;
2963
2964 num_palette_entries = GET_BE_WORD(header->num_palette_entries);
2965 if (first_entry_index + entry_count > num_palette_entries)
2966 return E_INVALIDARG;
2967
2968 records = table_read_ensure(cpal, GET_BE_DWORD(header->offset_first_color_record),
2969 sizeof(*records) * GET_BE_WORD(header->num_color_records));
2970 if (!records)
2971 return DWRITE_E_NOCOLOR;
2972
2973 first_entry_index += GET_BE_WORD(header->color_record_indices[palette]);
2974
2975 for (i = 0; i < entry_count; ++i)
2976 {
2977 colors[i].r = records[first_entry_index + i].red / 255.0f;
2978 colors[i].g = records[first_entry_index + i].green / 255.0f;
2979 colors[i].b = records[first_entry_index + i].blue / 255.0f;
2980 colors[i].a = records[first_entry_index + i].alpha / 255.0f;
2981 }
2982
2983 return S_OK;
2984}
2985
2986static int __cdecl colr_compare_gid(const void *g, const void *r)
2987{
2988 const struct colr_baseglyph_record *record = r;
2989 UINT16 glyph = *(UINT16*)g, GID = GET_BE_WORD(record->glyph);
2990 int ret = 0;
2991
2992 if (glyph > GID)
2993 ret = 1;
2994 else if (glyph < GID)
2995 ret = -1;
2996
2997 return ret;
2998}
2999
3001{
3002 unsigned int num_baseglyph_records, offset_baseglyph_records;
3003 const struct colr_baseglyph_record *record;
3004 const struct colr_layer_record *layer;
3005 const struct colr_header *header;
3006
3007 memset(ret, 0, sizeof(*ret));
3008 ret->glyph = glyph;
3009 ret->palette_index = 0xffff;
3010
3011 header = table_read_ensure(colr, 0, sizeof(*header));
3012 if (!header)
3013 return S_FALSE;
3014
3015 num_baseglyph_records = GET_BE_WORD(header->num_baseglyph_records);
3016 offset_baseglyph_records = GET_BE_DWORD(header->offset_baseglyph_records);
3018 {
3019 return S_FALSE;
3020 }
3021
3023 sizeof(*record), colr_compare_gid);
3024 if (!record)
3025 return S_FALSE;
3026
3027 ret->first_layer = GET_BE_WORD(record->first_layer_index);
3028 ret->num_layers = GET_BE_WORD(record->num_layers);
3029
3030 if ((layer = table_read_ensure(colr, GET_BE_DWORD(header->offset_layer_records),
3031 (ret->first_layer + ret->layer) * sizeof(*layer))))
3032 {
3033 layer += ret->first_layer + ret->layer;
3034 ret->glyph = GET_BE_WORD(layer->glyph);
3035 ret->palette_index = GET_BE_WORD(layer->palette_index);
3036 }
3037
3038 return S_OK;
3039}
3040
3041void opentype_colr_next_glyph(const struct dwrite_fonttable *colr, struct dwrite_colorglyph *glyph)
3042{
3043 const struct colr_layer_record *layer;
3044 const struct colr_header *header;
3045
3046 /* iterated all the way through */
3047 if (glyph->layer == glyph->num_layers)
3048 return;
3049
3050 if (!(header = table_read_ensure(colr, 0, sizeof(*header))))
3051 return;
3052
3053 glyph->layer++;
3054
3055 if ((layer = table_read_ensure(colr, GET_BE_DWORD(header->offset_layer_records),
3056 (glyph->first_layer + glyph->layer) * sizeof(*layer))))
3057 {
3058 layer += glyph->first_layer + glyph->layer;
3059 glyph->glyph = GET_BE_WORD(layer->glyph);
3060 glyph->palette_index = GET_BE_WORD(layer->palette_index);
3061 }
3062}
3063
3065{
3066 BOOL exists = FALSE;
3067 const void *data;
3068 void *context;
3069 UINT32 size;
3070 HRESULT hr;
3071
3072 hr = IDWriteFontFace5_TryGetFontTable(fontface, tag, &data, &size, &context, &exists);
3073 if (FAILED(hr))
3074 return FALSE;
3075
3076 if (exists)
3077 IDWriteFontFace5_ReleaseFontTable(fontface, context);
3078
3079 return exists;
3080}
3081
3082static unsigned int opentype_get_sbix_formats(IDWriteFontFace5 *fontface)
3083{
3084 unsigned int num_strikes, num_glyphs, i, j, ret = 0;
3085 const struct sbix_header *sbix_header;
3086 struct dwrite_fonttable table;
3087
3088 memset(&table, 0, sizeof(table));
3089 table.exists = TRUE;
3090
3091 if (!get_fontface_table(fontface, MS_MAXP_TAG, &table))
3092 return 0;
3093
3094 num_glyphs = table_read_be_word(&table, FIELD_OFFSET(struct maxp, num_glyphs));
3095
3096 IDWriteFontFace5_ReleaseFontTable(fontface, table.context);
3097
3098 memset(&table, 0, sizeof(table));
3099 table.exists = TRUE;
3100
3101 if (!get_fontface_table(fontface, MS_SBIX_TAG, &table))
3102 return 0;
3103
3104 num_strikes = table_read_be_dword(&table, FIELD_OFFSET(struct sbix_header, num_strikes));
3105 sbix_header = table_read_ensure(&table, 0, FIELD_OFFSET(struct sbix_header, strike_offset[num_strikes]));
3106
3107 if (sbix_header)
3108 {
3109 for (i = 0; i < num_strikes; ++i)
3110 {
3111 unsigned int strike_offset = GET_BE_DWORD(sbix_header->strike_offset[i]);
3112 const struct sbix_strike *strike = table_read_ensure(&table, strike_offset,
3113 FIELD_OFFSET(struct sbix_strike, glyphdata_offsets[num_glyphs + 1]));
3114
3115 if (!strike)
3116 continue;
3117
3118 for (j = 0; j < num_glyphs; j++)
3119 {
3120 unsigned int offset = GET_BE_DWORD(strike->glyphdata_offsets[j]);
3121 unsigned int next_offset = GET_BE_DWORD(strike->glyphdata_offsets[j + 1]);
3122 const struct sbix_glyph_data *glyph_data;
3123
3124 if (offset == next_offset)
3125 continue;
3126
3127 glyph_data = table_read_ensure(&table, strike_offset + offset, sizeof(*glyph_data));
3128 if (!glyph_data)
3129 continue;
3130
3131 switch (glyph_data->graphic_type)
3132 {
3133 case MS_PNG__TAG:
3135 break;
3136 case MS_JPG__TAG:
3138 break;
3139 case MS_TIFF_TAG:
3141 break;
3142 default:
3143 FIXME("unexpected bitmap format %s\n", debugstr_fourcc(GET_BE_DWORD(glyph_data->graphic_type)));
3144 }
3145 }
3146 }
3147 }
3148
3149 IDWriteFontFace5_ReleaseFontTable(fontface, table.context);
3150
3151 return ret;
3152}
3153
3154static unsigned int opentype_get_cblc_formats(IDWriteFontFace5 *fontface)
3155{
3156 const unsigned int format_mask = DWRITE_GLYPH_IMAGE_FORMATS_PNG |
3158 const struct cblc_bitmapsize_table *sizes;
3159 struct dwrite_fonttable cblc = { 0 };
3160 unsigned int num_sizes, i, ret = 0;
3161 const struct cblc_header *header;
3162
3163 cblc.exists = TRUE;
3164 if (!get_fontface_table(fontface, MS_CBLC_TAG, &cblc))
3165 return 0;
3166
3168 sizes = table_read_ensure(&cblc, sizeof(*header), num_sizes * sizeof(*sizes));
3169
3170 if (sizes)
3171 {
3172 for (i = 0; i < num_sizes; ++i)
3173 {
3174 BYTE bpp = sizes[i].bit_depth;
3175
3176 if ((ret & format_mask) == format_mask)
3177 break;
3178
3179 if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8)
3181 else if (bpp == 32)
3183 }
3184 }
3185
3186 IDWriteFontFace5_ReleaseFontTable(fontface, cblc.context);
3187
3188 return ret;
3189}
3190
3192{
3194
3195 if (opentype_has_font_table(fontface, MS_GLYF_TAG))
3197
3198 if (opentype_has_font_table(fontface, MS_CFF__TAG) ||
3201
3202 if (opentype_has_font_table(fontface, MS_COLR_TAG))
3204
3205 if (opentype_has_font_table(fontface, MS_SVG__TAG))
3207
3208 if (opentype_has_font_table(fontface, MS_SBIX_TAG))
3209 ret |= opentype_get_sbix_formats(fontface);
3210
3211 if (opentype_has_font_table(fontface, MS_CBLC_TAG))
3212 ret |= opentype_get_cblc_formats(fontface);
3213
3214 return ret;
3215}
3216
3218{
3220
3221 if (data_size < sizeof(DWORD))
3222 return DWRITE_CONTAINER_TYPE_UNKNOWN;
3223
3224 /* Both WOFF and WOFF2 start with 4 bytes signature. */
3225 signature = *(DWORD *)data;
3226
3227 switch (signature)
3228 {
3229 case MS_WOFF_TAG:
3231 case MS_WOF2_TAG:
3233 default:
3234 return DWRITE_CONTAINER_TYPE_UNKNOWN;
3235 }
3236}
3237
3239{
3240 cache->font->grab_font_table(cache->context, MS_GSUB_TAG, &cache->gsub.table.data, &cache->gsub.table.size,
3241 &cache->gsub.table.context);
3242
3243 if (cache->gsub.table.data)
3244 {
3245 cache->gsub.script_list = table_read_be_word(&cache->gsub.table, FIELD_OFFSET(struct gpos_gsub_header, script_list));
3246 cache->gsub.feature_list = table_read_be_word(&cache->gsub.table, FIELD_OFFSET(struct gpos_gsub_header, feature_list));
3247 cache->gsub.lookup_list = table_read_be_word(&cache->gsub.table, FIELD_OFFSET(struct gpos_gsub_header, lookup_list));
3248 }
3249
3250 cache->font->grab_font_table(cache->context, MS_GPOS_TAG, &cache->gpos.table.data, &cache->gpos.table.size,
3251 &cache->gpos.table.context);
3252
3253 if (cache->gpos.table.data)
3254 {
3255 cache->gpos.script_list = table_read_be_word(&cache->gpos.table,
3256 FIELD_OFFSET(struct gpos_gsub_header, script_list));
3257 cache->gpos.feature_list = table_read_be_word(&cache->gpos.table,
3258 FIELD_OFFSET(struct gpos_gsub_header, feature_list));
3259 cache->gpos.lookup_list = table_read_be_word(&cache->gpos.table,
3260 FIELD_OFFSET(struct gpos_gsub_header, lookup_list));
3261 }
3262
3263 cache->font->grab_font_table(cache->context, MS_GDEF_TAG, &cache->gdef.table.data, &cache->gdef.table.size,
3264 &cache->gdef.table.context);
3265
3266 if (cache->gdef.table.data)
3267 {
3268 unsigned int version = table_read_be_dword(&cache->gdef.table, 0);
3269
3270 cache->gdef.classdef = table_read_be_word(&cache->gdef.table, FIELD_OFFSET(struct gdef_header, classdef));
3271 cache->gdef.markattachclassdef = table_read_be_word(&cache->gdef.table,
3272 FIELD_OFFSET(struct gdef_header, markattach_classdef));
3273 if (version >= 0x00010002)
3274 cache->gdef.markglyphsetdef = table_read_be_word(&cache->gdef.table,
3275 FIELD_OFFSET(struct gdef_header, markglyphsetdef));
3276 }
3277}
3278
3279unsigned int opentype_layout_find_script(const struct scriptshaping_cache *cache, unsigned int kind, DWORD script,
3280 unsigned int *script_index)
3281{
3282 const struct ot_gsubgpos_table *table = kind == MS_GSUB_TAG ? &cache->gsub : &cache->gpos;
3283 UINT16 script_count;
3284 unsigned int i;
3285
3286 *script_index = ~0u;
3287
3288 script_count = table_read_be_word(&table->table, table->script_list);
3289 if (!script_count)
3290 return 0;
3291
3292 for (i = 0; i < script_count; i++)
3293 {
3294 unsigned int tag = table_read_dword(&table->table, table->script_list + FIELD_OFFSET(struct ot_script_list, scripts) +
3295 i * sizeof(struct ot_script_record));
3296 if (!tag)
3297 continue;
3298
3299 if (tag == script)
3300 {
3301 *script_index = i;
3302 return script;
3303 }
3304 }
3305
3306 return 0;
3307}
3308
3309unsigned int opentype_layout_find_language(const struct scriptshaping_cache *cache, unsigned int kind, DWORD language,
3310 unsigned int script_index, unsigned int *language_index)
3311{
3312 const struct ot_gsubgpos_table *table = kind == MS_GSUB_TAG ? &cache->gsub : &cache->gpos;
3313 UINT16 table_offset, lang_count;
3314 unsigned int i;
3315
3316 *language_index = ~0u;
3317
3318 table_offset = table_read_be_word(&table->table, table->script_list + FIELD_OFFSET(struct ot_script_list, scripts) +
3319 script_index * sizeof(struct ot_script_record) + FIELD_OFFSET(struct ot_script_record, script));
3320 if (!table_offset)
3321 return 0;
3322
3323 lang_count = table_read_be_word(&table->table, table->script_list + table_offset +
3324 FIELD_OFFSET(struct ot_script, langsys_count));
3325 for (i = 0; i < lang_count; i++)
3326 {
3327 unsigned int tag = table_read_dword(&table->table, table->script_list + table_offset +
3328 FIELD_OFFSET(struct ot_script, langsys) + i * sizeof(struct ot_langsys_record));
3329
3330 if (tag == language)
3331 {
3332 *language_index = i;
3333 return language;
3334 }
3335 }
3336
3337 /* Try 'defaultLangSys' if it's set. */
3338 if (table_read_be_word(&table->table, table->script_list + table_offset))
3339 return ~0u;
3340
3341 return 0;
3342}
3343
3344static int __cdecl gdef_class_compare_format2(const void *g, const void *r)
3345{
3346 const struct ot_gdef_class_range *range = r;
3347 UINT16 glyph = *(UINT16 *)g;
3348
3349 if (glyph < GET_BE_WORD(range->start_glyph))
3350 return -1;
3351 else if (glyph > GET_BE_WORD(range->end_glyph))
3352 return 1;
3353 else
3354 return 0;
3355}
3356
3358 unsigned int offset, UINT16 glyph)
3359{
3361 unsigned int glyph_class = GDEF_CLASS_UNCLASSIFIED;
3362
3363 if (format == 1)
3364 {
3365 const struct ot_gdef_classdef_format1 *format1;
3366
3369 if (format1)
3370 {
3372 if (glyph >= start_glyph && (glyph - start_glyph) < count)
3373 {
3374 glyph_class = GET_BE_WORD(format1->classes[glyph - start_glyph]);
3375 if (glyph_class > GDEF_CLASS_MAX)
3376 glyph_class = GDEF_CLASS_UNCLASSIFIED;
3377 }
3378 }
3379 }
3380 else if (format == 2)
3381 {
3382 const struct ot_gdef_classdef_format2 *format2;
3383
3386 if (format2)
3387 {
3388 const struct ot_gdef_class_range *range = bsearch(&glyph, format2->ranges, count,
3390 glyph_class = range && glyph <= GET_BE_WORD(range->end_glyph) ?
3394 }
3395 }
3396 else
3397 WARN("Unknown GDEF format %u.\n", format);
3398
3399 return glyph_class;
3400}
3401
3402static unsigned int opentype_set_glyph_props(struct scriptshaping_context *context, unsigned int idx)
3403{
3404 struct scriptshaping_cache *cache = context->cache;
3405 unsigned int glyph_class = 0, props;
3406
3407 if (cache->gdef.classdef)
3408 {
3409 glyph_class = opentype_layout_get_glyph_class(&cache->gdef.table, cache->gdef.classdef,
3410 context->u.buffer.glyphs[idx]);
3411 }
3412
3413 switch (glyph_class)
3414 {
3415 case GDEF_CLASS_BASE:
3417 break;
3420 break;
3421 case GDEF_CLASS_MARK:
3423 if (cache->gdef.markattachclassdef)
3424 {
3425 glyph_class = opentype_layout_get_glyph_class(&cache->gdef.table, cache->gdef.markattachclassdef,
3426 context->u.buffer.glyphs[idx]);
3427 props |= glyph_class << 8;
3428 }
3429 break;
3430 default:
3431 props = 0;
3432 }
3433
3434 context->glyph_infos[idx].props = props;
3435
3436 return props;
3437}
3438
3440{
3441 unsigned int glyph_props = opentype_set_glyph_props(context, idx) & LOOKUP_FLAG_IGNORE_MASK;
3442 context->u.subst.glyph_props[idx].isDiacritic = !!(glyph_props == GLYPH_PROP_MARK);
3443 context->u.subst.glyph_props[idx].isZeroWidthSpace = !!(glyph_props == GLYPH_PROP_MARK);
3444}
3445
3447{
3450 unsigned int *coverage_index;
3451};
3452
3453static int __cdecl coverage_compare_format1(const void *left, const void *right)
3454{
3457 int ret;
3458
3459 ret = context->glyph - glyph;
3460 if (!ret)
3461 *context->coverage_index = (UINT16 *)right - context->table_base;
3462
3463 return ret;
3464}
3465
3466static int __cdecl coverage_compare_format2(const void *g, const void *r)
3467{
3468 const struct ot_coverage_range *range = r;
3469 UINT16 glyph = *(UINT16 *)g;
3470
3471 if (glyph < GET_BE_WORD(range->start_glyph))
3472 return -1;
3473 else if (glyph > GET_BE_WORD(range->end_glyph))
3474 return 1;
3475 else
3476 return 0;
3477}
3478
3479static unsigned int opentype_layout_is_glyph_covered(const struct dwrite_fonttable *table, unsigned int coverage,
3480 UINT16 glyph)
3481{
3483
3484 count = table_read_be_word(table, coverage + 2);
3485
3486 if (format == 1)
3487 {
3488 const struct ot_coverage_format1 *format1 = table_read_ensure(table, coverage,
3491 unsigned int coverage_index = GLYPH_NOT_COVERED;
3492
3493 if (format1)
3494 {
3495 context.glyph = glyph;
3496 context.table_base = format1->glyphs;
3497 context.coverage_index = &coverage_index;
3498
3500 }
3501
3502 return coverage_index;
3503 }
3504 else if (format == 2)
3505 {
3506 const struct ot_coverage_format2 *format2 = table_read_ensure(table, coverage,
3508 if (format2)
3509 {
3510 const struct ot_coverage_range *range = bsearch(&glyph, format2->ranges, count,
3512 return range && glyph <= GET_BE_WORD(range->end_glyph) ?
3513 GET_BE_WORD(range->startcoverage_index) + glyph - GET_BE_WORD(range->start_glyph) :
3515 }
3516 }
3517 else
3518 WARN("Unknown coverage format %u.\n", format);
3519
3520 return -1;
3521}
3522
3523static inline unsigned int dwrite_popcount(unsigned int x)
3524{
3525#if defined(__MINGW32__)
3526 return __builtin_popcount(x);
3527#else
3528 x -= x >> 1 & 0x55555555;
3529 x = (x & 0x33333333) + (x >> 2 & 0x33333333);
3530 return ((x + (x >> 4)) & 0x0f0f0f0f) * 0x01010101 >> 24;
3531#endif
3532}
3533
3534static float opentype_scale_gpos_be_value(WORD value, float emsize, UINT16 upem)
3535{
3536 return (short)GET_BE_WORD(value) * emsize / upem;
3537}
3538
3540{
3541 const struct dwrite_fonttable *table = &context->table->table;
3542 unsigned int start_size, end_size, format, value_word;
3543 unsigned int index, ppem, mask;
3544 int value;
3545
3546 if (!offset)
3547 return 0;
3548
3549 start_size = table_read_be_word(table, offset);
3550 end_size = table_read_be_word(table, offset + FIELD_OFFSET(struct ot_gpos_device_table, end_size));
3551
3552 ppem = context->emsize;
3553 if (ppem < start_size || ppem > end_size)
3554 return 0;
3555
3557
3558 if (format < 1 || format > 3)
3559 return 0;
3560
3561 index = ppem - start_size;
3562
3564 mask = 0xffff >> (16 - (1 << format));
3565
3566 value = (value_word >> ((index % (4 - format)) * (1 << format))) & mask;
3567
3568 if ((unsigned int)value >= ((mask + 1) >> 1))
3569 value -= mask + 1;
3570
3571 return value;
3572}
3573
3574static void opentype_layout_apply_gpos_value(struct scriptshaping_context *context, unsigned int table_offset,
3575 WORD value_format, const WORD *values, unsigned int glyph)
3576{
3577 const struct scriptshaping_cache *cache = context->cache;
3578 DWRITE_GLYPH_OFFSET *offset = &context->offsets[glyph];
3579 float *advance = &context->advances[glyph];
3580
3581 if (!value_format)
3582 return;
3583
3584 if (value_format & GPOS_VALUE_X_PLACEMENT)
3585 {
3586 offset->advanceOffset += opentype_scale_gpos_be_value(*values, context->emsize, cache->upem);
3587 values++;
3588 }
3589 if (value_format & GPOS_VALUE_Y_PLACEMENT)
3590 {
3591 offset->ascenderOffset += opentype_scale_gpos_be_value(*values, context->emsize, cache->upem);
3592 values++;
3593 }
3594 if (value_format & GPOS_VALUE_X_ADVANCE)
3595 {
3597 values++;
3598 }
3599 if (value_format & GPOS_VALUE_Y_ADVANCE)
3600 {
3601 values++;
3602 }
3603 if (value_format & GPOS_VALUE_X_PLACEMENT_DEVICE)
3604 {
3605 offset->advanceOffset += opentype_layout_gpos_get_dev_value(context, table_offset + GET_BE_WORD(*values));
3606 values++;
3607 }
3608 if (value_format & GPOS_VALUE_Y_PLACEMENT_DEVICE)
3609 {
3610 offset->ascenderOffset += opentype_layout_gpos_get_dev_value(context, table_offset + GET_BE_WORD(*values));
3611 values++;
3612 }
3613 if (value_format & GPOS_VALUE_X_ADVANCE_DEVICE)
3614 {
3616 values++;
3617 }
3618 if (value_format & GPOS_VALUE_Y_ADVANCE_DEVICE)
3619 {
3620 values++;
3621 }
3622}
3623
3625{
3626 unsigned short index;
3627 unsigned short type;
3628 unsigned short subtable_count;
3629
3630 unsigned int mask;
3631 unsigned int flags;
3632 unsigned int offset;
3633 unsigned int auto_zwnj : 1;
3634 unsigned int auto_zwj : 1;
3635};
3636
3638{
3639 return context->table == &context->cache->gsub;
3640}
3641
3643{
3644 return context->table == &context->cache->gpos;
3645}
3646
3648 const struct lookup *lookup, unsigned int subtable, unsigned int *lookup_type)
3649{
3650 unsigned int subtable_offset = table_read_be_word(&context->table->table, lookup->offset +
3651 FIELD_OFFSET(struct ot_lookup_table, subtable[subtable]));
3652 const struct ot_gsubgpos_extension_format1 *format1;
3653
3654 subtable_offset += lookup->offset;
3655
3658 {
3660 return subtable_offset;
3661 }
3662
3663 *lookup_type = 0;
3664
3665 if (!(format1 = table_read_ensure(&context->table->table, subtable_offset, sizeof(*format1))))
3666 return 0;
3667
3668 if (GET_BE_WORD(format1->format) != 1)
3669 {
3670 WARN("Unexpected extension table format %#x.\n", format1->format);
3671 return 0;
3672 }
3673
3674 *lookup_type = GET_BE_WORD(format1->lookup_type);
3675 return subtable_offset + GET_BE_DWORD(format1->extension_offset);
3676}
3677
3679{
3680 unsigned int offset;
3681 unsigned int subtable_count;
3682 unsigned int flags;
3683};
3684
3686{
3687 /* First two to fit matching callback result. */
3691};
3692
3693struct match_context;
3695{
3696 const struct match_context *mc;
3697 unsigned int subtable_offset;
3698};
3699
3700typedef BOOL (*p_match_func)(UINT16 glyph, UINT16 glyph_data, const struct match_data *match_data);
3701
3703{
3705 unsigned int backtrack_offset;
3706 unsigned int input_offset;
3707 unsigned int lookahead_offset;
3709 const struct lookup *lookup;
3710};
3711
3713{
3715 unsigned int flags;
3716 unsigned int pos;
3717 unsigned int len;
3718 unsigned int mask;
3721 const struct match_data *match_data;
3722 unsigned int ignore_zwnj;
3723 unsigned int ignore_zwj;
3724};
3725
3726static void glyph_iterator_init(struct scriptshaping_context *context, unsigned int flags, unsigned int pos,
3727 unsigned int len, struct glyph_iterator *iter)
3728{
3729 iter->context = context;
3730 iter->flags = flags;
3731 iter->pos = pos;
3732 iter->len = len;
3733 iter->mask = ~0u;
3734 iter->match_func = NULL;
3735 iter->match_data = NULL;
3736 iter->glyph_data = NULL;
3737 /* Context matching iterators will get these fixed up. */
3739 iter->ignore_zwj = context->auto_zwj;
3740}
3741
3743{
3747};
3748
3749static BOOL opentype_match_glyph_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
3750{
3751 return glyph == glyph_data;
3752}
3753
3754static BOOL opentype_match_class_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
3755{
3756 const struct match_context *mc = data->mc;
3757 UINT16 glyph_class = opentype_layout_get_glyph_class(&mc->context->table->table, data->subtable_offset, glyph);
3758 return glyph_class == glyph_data;
3759}
3760
3761static BOOL opentype_match_coverage_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
3762{
3763 const struct match_context *mc = data->mc;
3764 return opentype_layout_is_glyph_covered(&mc->context->table->table, data->subtable_offset + glyph_data, glyph)
3766}
3767
3768static BOOL opentype_layout_mark_set_covers(const struct scriptshaping_cache *cache, unsigned int set_index,
3769 UINT16 glyph)
3770{
3771 unsigned int format, offset = cache->gdef.markglyphsetdef, coverage_offset, count;
3772
3773 if (!offset)
3774 return FALSE;
3775
3776 format = table_read_be_word(&cache->gdef.table, offset);
3777
3778 if (format == 1)
3779 {
3781 if (!count || set_index >= count)
3782 return FALSE;
3783
3784 coverage_offset = table_read_be_dword(&cache->gdef.table, offset +
3785 FIELD_OFFSET(struct ot_gdef_markglyphsets, offsets[set_index]));
3786 return opentype_layout_is_glyph_covered(&cache->gdef.table, offset + coverage_offset, glyph) != GLYPH_NOT_COVERED;
3787 }
3788 else
3789 WARN("Unexpected MarkGlyphSets format %#x.\n", format);
3790
3791 return FALSE;
3792}
3793
3794static BOOL lookup_is_glyph_match(const struct scriptshaping_context *context, unsigned int idx, unsigned int match_props)
3795{
3796 unsigned int glyph_props = context->glyph_infos[idx].props;
3797 UINT16 glyph = context->u.buffer.glyphs[idx];
3798
3799 if (glyph_props & match_props & LOOKUP_FLAG_IGNORE_MASK)
3800 return FALSE;
3801
3802 if (!(glyph_props & GLYPH_PROP_MARK))
3803 return TRUE;
3804
3805 if (match_props & LOOKUP_FLAG_USE_MARK_FILTERING_SET)
3806 return opentype_layout_mark_set_covers(context->cache, match_props >> 16, glyph);
3807
3808 if (match_props & LOOKUP_FLAG_MARK_ATTACHMENT_TYPE)
3809 return (match_props & LOOKUP_FLAG_MARK_ATTACHMENT_TYPE) == (glyph_props & LOOKUP_FLAG_MARK_ATTACHMENT_TYPE);
3810
3811 return TRUE;
3812}
3813
3815{
3816 unsigned int glyph_props = iter->context->glyph_infos[iter->pos].props & (GLYPH_PROP_IGNORABLE | GLYPH_PROP_HIDDEN);
3817
3818 if (!lookup_is_glyph_match(iter->context, iter->pos, iter->flags))
3819 return ITER_YES;
3820
3821 if (glyph_props == GLYPH_PROP_IGNORABLE && !iter->context->u.buffer.glyph_props[iter->pos].components &&
3822 (iter->ignore_zwnj || !(iter->context->glyph_infos[iter->pos].props & GLYPH_PROP_ZWNJ)) &&
3823 (iter->ignore_zwj || !(iter->context->glyph_infos[iter->pos].props & GLYPH_PROP_ZWJ)))
3824 {
3825 return ITER_MAYBE;
3826 }
3827
3828 return ITER_NO;
3829}
3830
3832{
3833 if (!(iter->mask & iter->context->glyph_infos[iter->pos].mask))
3834 return ITER_NO;
3835
3836 /* Glyph data is used for input, backtrack, and lookahead arrays, swap it here instead of doing that
3837 in all matching functions. */
3838 if (iter->match_func)
3839 return !!iter->match_func(iter->context->u.buffer.glyphs[iter->pos], GET_BE_WORD(*iter->glyph_data), iter->match_data);
3840
3841 return ITER_MAYBE;
3842}
3843
3845{
3847
3848 while (iter->pos + iter->len < iter->context->glyph_count)
3849 {
3850 ++iter->pos;
3851
3853 if (skip == ITER_YES)
3854 continue;
3855
3857 if (match == ITER_YES || (match == ITER_MAYBE && skip == ITER_NO))
3858 {
3859 --iter->len;
3860 if (iter->glyph_data)
3861 ++iter->glyph_data;
3862 return TRUE;
3863 }
3864
3865 if (skip == ITER_NO)
3866 return FALSE;
3867 }
3868
3869 return FALSE;
3870}
3871
3873{
3875
3876 while (iter->pos > iter->len - 1)
3877 {
3878 --iter->pos;
3879
3881 if (skip == ITER_YES)
3882 continue;
3883
3885 if (match == ITER_YES || (match == ITER_MAYBE && skip == ITER_NO))
3886 {
3887 --iter->len;
3888 if (iter->glyph_data)
3889 ++iter->glyph_data;
3890 return TRUE;
3891 }
3892
3893 if (skip == ITER_NO)
3894 return FALSE;
3895 }
3896
3897 return FALSE;
3898}
3899
3901 const struct lookup *lookup, unsigned int subtable_offset)
3902{
3903 const struct dwrite_fonttable *table = &context->table->table;
3904 UINT16 format, value_format, value_len, coverage, glyph;
3905
3906 unsigned int coverage_index;
3907
3908 format = table_read_be_word(table, subtable_offset);
3909
3910 coverage = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gpos_singlepos_format1, coverage));
3911 value_format = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gpos_singlepos_format1, value_format));
3912 value_len = dwrite_popcount(value_format);
3913
3914 glyph = context->u.pos.glyphs[context->cur];
3915
3916 if (format == 1)
3917 {
3918 const struct ot_gpos_singlepos_format1 *format1 = table_read_ensure(table, subtable_offset,
3919 FIELD_OFFSET(struct ot_gpos_singlepos_format1, value[value_len]));
3920
3921 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
3922 if (coverage_index == GLYPH_NOT_COVERED)
3923 return FALSE;
3924
3925 opentype_layout_apply_gpos_value(context, subtable_offset, value_format, format1->value, context->cur);
3926 }
3927 else if (format == 2)
3928 {
3929 WORD value_count = table_read_be_word(table, subtable_offset +
3930 FIELD_OFFSET(struct ot_gpos_singlepos_format2, value_count));
3931 const struct ot_gpos_singlepos_format2 *format2 = table_read_ensure(table, subtable_offset,
3932 FIELD_OFFSET(struct ot_gpos_singlepos_format2, values) + value_count * value_len * sizeof(WORD));
3933
3934 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
3935 if (coverage_index == GLYPH_NOT_COVERED || coverage_index >= value_count)
3936 return FALSE;
3937
3938 opentype_layout_apply_gpos_value(context, subtable_offset, value_format, &format2->values[coverage_index * value_len],
3939 context->cur);
3940 }
3941 else
3942 {
3943 WARN("Unknown single adjustment format %u.\n", format);
3944 return FALSE;
3945 }
3946
3947 context->cur++;
3948
3949 return TRUE;
3950}
3951
3952static int __cdecl gpos_pair_adjustment_compare_format1(const void *g, const void *r)
3953{
3954 const struct ot_gpos_pairvalue *pairvalue = r;
3956 return *(UINT16 *)g - second_glyph;
3957}
3958
3960 const struct lookup *lookup, unsigned int subtable_offset)
3961{
3962 const struct dwrite_fonttable *table = &context->table->table;
3963 unsigned int first_glyph, second_glyph;
3964 struct glyph_iterator iter_pair;
3965 WORD format, coverage;
3966
3967 WORD value_format1, value_format2, value_len1, value_len2;
3968 unsigned int coverage_index;
3969
3970 glyph_iterator_init(context, lookup->flags, context->cur, 1, &iter_pair);
3971 if (!glyph_iterator_next(&iter_pair))
3972 return FALSE;
3973
3974 if (context->is_rtl)
3975 {
3976 first_glyph = iter_pair.pos;
3977 second_glyph = context->cur;
3978 }
3979 else
3980 {
3981 first_glyph = context->cur;
3982 second_glyph = iter_pair.pos;
3983 }
3984
3985 format = table_read_be_word(table, subtable_offset);
3986
3987 coverage = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gpos_pairpos_format1, coverage));
3988 if (!coverage)
3989 return FALSE;
3990
3991 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, context->u.pos.glyphs[first_glyph]);
3992 if (coverage_index == GLYPH_NOT_COVERED)
3993 return FALSE;
3994
3995 if (format == 1)
3996 {
3997 const struct ot_gpos_pairpos_format1 *format1;
3999 pairset_count));
4000 unsigned int pairvalue_len, pairset_offset;
4001 const struct ot_gpos_pairset *pairset;
4002 const WORD *pairvalue;
4004
4005 if (!pairset_count || coverage_index >= pairset_count)
4006 return FALSE;
4007
4008 format1 = table_read_ensure(table, subtable_offset, FIELD_OFFSET(struct ot_gpos_pairpos_format1, pairsets[pairset_count]));
4009 if (!format1)
4010 return FALSE;
4011
4012 /* Ordered paired values. */
4013 pairvalue_count = table_read_be_word(table, subtable_offset + GET_BE_WORD(format1->pairsets[coverage_index]));
4014 if (!pairvalue_count)
4015 return FALSE;
4016
4017 /* Structure length is variable, but does not change across the subtable. */
4018 value_format1 = GET_BE_WORD(format1->value_format1) & 0xff;
4019 value_format2 = GET_BE_WORD(format1->value_format2) & 0xff;
4020
4021 value_len1 = dwrite_popcount(value_format1);
4022 value_len2 = dwrite_popcount(value_format2);
4023 pairvalue_len = FIELD_OFFSET(struct ot_gpos_pairvalue, data) + value_len1 * sizeof(WORD) +
4024 value_len2 * sizeof(WORD);
4025
4026 pairset_offset = subtable_offset + GET_BE_WORD(format1->pairsets[coverage_index]);
4027 pairset = table_read_ensure(table, pairset_offset, pairvalue_len * pairvalue_count);
4028 if (!pairset)
4029 return FALSE;
4030
4031 pairvalue = bsearch(&context->u.pos.glyphs[second_glyph], pairset->pairvalues, pairvalue_count,
4033 if (!pairvalue)
4034 return FALSE;
4035
4036 pairvalue += 1; /* Skip SecondGlyph. */
4037 opentype_layout_apply_gpos_value(context, pairset_offset, value_format1, pairvalue, first_glyph);
4038 opentype_layout_apply_gpos_value(context, pairset_offset, value_format2, pairvalue + value_len1,
4039 second_glyph);
4040
4041 context->cur = iter_pair.pos;
4042 if (value_len2)
4043 context->cur++;
4044 }
4045 else if (format == 2)
4046 {
4047 const struct ot_gpos_pairpos_format2 *format2;
4049 unsigned int class1, class2;
4050 const WCHAR *values;
4051
4052 value_format1 = table_read_be_word(table, subtable_offset +
4054 value_format2 = table_read_be_word(table, subtable_offset +
4056
4059
4060 value_len1 = dwrite_popcount(value_format1);
4061 value_len2 = dwrite_popcount(value_format2);
4062
4063 format2 = table_read_ensure(table, subtable_offset, FIELD_OFFSET(struct ot_gpos_pairpos_format2,
4064 values[class1_count * class2_count * (value_len1 + value_len2)]));
4065 if (!format2)
4066 return FALSE;
4067
4068 class1 = opentype_layout_get_glyph_class(table, subtable_offset + GET_BE_WORD(format2->class_def1),
4069 context->u.pos.glyphs[first_glyph]);
4070 class2 = opentype_layout_get_glyph_class(table, subtable_offset + GET_BE_WORD(format2->class_def2),
4071 context->u.pos.glyphs[second_glyph]);
4072
4073 if (!(class1 < class1_count && class2 < class2_count))
4074 return FALSE;
4075
4076 values = &format2->values[(class1 * class2_count + class2) * (value_len1 + value_len2)];
4077 opentype_layout_apply_gpos_value(context, subtable_offset, value_format1, values, first_glyph);
4078 opentype_layout_apply_gpos_value(context, subtable_offset, value_format2, values + value_len1,
4079 second_glyph);
4080
4081 context->cur = iter_pair.pos;
4082 if (value_len2)
4083 context->cur++;
4084 }
4085 else
4086 {
4087 WARN("Unknown pair adjustment format %u.\n", format);
4088 return FALSE;
4089 }
4090
4091 return TRUE;
4092}
4093
4094static void opentype_layout_gpos_get_anchor(const struct scriptshaping_context *context, unsigned int anchor_offset,
4095 unsigned int glyph_index, float *x, float *y)
4096{
4097 const struct scriptshaping_cache *cache = context->cache;
4098 const struct dwrite_fonttable *table = &context->table->table;
4099
4100 WORD format = table_read_be_word(table, anchor_offset);
4101
4102 *x = *y = 0.0f;
4103
4104 if (format == 1)
4105 {
4106 const struct ot_gpos_anchor_format1 *format1 = table_read_ensure(table, anchor_offset, sizeof(*format1));
4107
4108 if (format1)
4109 {
4110 *x = opentype_scale_gpos_be_value(format1->x_coord, context->emsize, cache->upem);
4111 *y = opentype_scale_gpos_be_value(format1->y_coord, context->emsize, cache->upem);
4112 }
4113 }
4114 else if (format == 2)
4115 {
4116 const struct ot_gpos_anchor_format2 *format2 = table_read_ensure(table, anchor_offset, sizeof(*format2));
4117
4118 if (format2)
4119 {
4120 if (context->measuring_mode != DWRITE_MEASURING_MODE_NATURAL)
4121 FIXME("Use outline anchor point for glyph %u.\n", context->u.pos.glyphs[glyph_index]);
4122
4123 *x = opentype_scale_gpos_be_value(format2->x_coord, context->emsize, cache->upem);
4124 *y = opentype_scale_gpos_be_value(format2->y_coord, context->emsize, cache->upem);
4125 }
4126 }
4127 else if (format == 3)
4128 {
4129 const struct ot_gpos_anchor_format3 *format3 = table_read_ensure(table, anchor_offset, sizeof(*format3));
4130
4131 if (format3)
4132 {
4133 *x = opentype_scale_gpos_be_value(format3->x_coord, context->emsize, cache->upem);
4134 *y = opentype_scale_gpos_be_value(format3->y_coord, context->emsize, cache->upem);
4135
4136 if (context->measuring_mode != DWRITE_MEASURING_MODE_NATURAL)
4137 {
4138 if (format3->x_dev_offset)
4140 if (format3->y_dev_offset)
4142 }
4143 }
4144 }
4145 else
4146 WARN("Unknown anchor format %u.\n", format);
4147}
4148
4151{
4152 context->glyph_infos[idx].props &= ~GLYPH_PROP_ATTACH_TYPE_MASK;
4153 context->glyph_infos[idx].props |= attach_type << 16;
4154}
4155
4157{
4158 return (context->glyph_infos[idx].props >> 16) & 0xff;
4159}
4160
4162 unsigned int new_parent)
4163{
4165 int chain = context->glyph_infos[i].attach_chain;
4166 unsigned int j;
4167
4168 if (!chain || type != GLYPH_ATTACH_CURSIVE)
4169 return;
4170
4171 context->glyph_infos[i].attach_chain = 0;
4172
4173 j = (int)i + chain;
4174 if (j == new_parent)
4175 return;
4176
4178
4179 /* FIXME: handle vertical flow direction */
4180 context->offsets[j].ascenderOffset = -context->offsets[i].ascenderOffset;
4181
4182 context->glyph_infos[j].attach_chain = -chain;
4184}
4185
4187 const struct lookup *lookup, unsigned int subtable_offset)
4188{
4189 const struct dwrite_fonttable *table = &context->table->table;
4190 UINT16 format, glyph;
4191
4192 format = table_read_be_word(table, subtable_offset);
4193 glyph = context->u.pos.glyphs[context->cur];
4194
4195 if (format == 1)
4196 {
4197 WORD coverage_offset = table_read_be_word(table, subtable_offset +
4198 FIELD_OFFSET(struct ot_gpos_cursive_format1, coverage));
4199 unsigned int glyph_index, entry_count, entry_anchor, exit_anchor, child, parent;
4200 float entry_x, entry_y, exit_x, exit_y, delta;
4201 struct glyph_iterator prev_iter;
4202 float y_offset;
4203
4204 if (!coverage_offset)
4205 return FALSE;
4206
4207 entry_count = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gpos_cursive_format1, count));
4208
4209 glyph_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage_offset, glyph);
4210 if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
4211 return FALSE;
4212
4213 entry_anchor = table_read_be_word(table, subtable_offset +
4214 FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2]));
4215 if (!entry_anchor)
4216 return FALSE;
4217
4218 glyph_iterator_init(context, lookup->flags, context->cur, 1, &prev_iter);
4219 if (!glyph_iterator_prev(&prev_iter))
4220 return FALSE;
4221
4222 glyph_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage_offset,
4223 context->u.pos.glyphs[prev_iter.pos]);
4224 if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
4225 return FALSE;
4226
4227 exit_anchor = table_read_be_word(table, subtable_offset +
4228 FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2 + 1]));
4229 if (!exit_anchor)
4230 return FALSE;
4231
4232 opentype_layout_gpos_get_anchor(context, subtable_offset + exit_anchor, prev_iter.pos, &exit_x, &exit_y);
4233 opentype_layout_gpos_get_anchor(context, subtable_offset + entry_anchor, context->cur, &entry_x, &entry_y);
4234
4235 if (context->is_rtl)
4236 {
4237 delta = exit_x + context->offsets[prev_iter.pos].advanceOffset;
4238 context->advances[prev_iter.pos] -= delta;
4239 context->advances[context->cur] = entry_x + context->offsets[context->cur].advanceOffset;
4240 context->offsets[prev_iter.pos].advanceOffset -= delta;
4241 }
4242 else
4243 {
4244 delta = entry_x + context->offsets[context->cur].advanceOffset;
4245 context->advances[prev_iter.pos] = exit_x + context->offsets[prev_iter.pos].advanceOffset;
4246 context->advances[context->cur] -= delta;
4247 context->offsets[context->cur].advanceOffset -= delta;
4248 }
4249
4251 {
4252 y_offset = entry_y - exit_y;
4253 child = prev_iter.pos;
4254 parent = context->cur;
4255 }
4256 else
4257 {
4258 y_offset = exit_y - entry_y;
4259 child = context->cur;
4260 parent = prev_iter.pos;
4261 }
4262
4264
4265 context->offsets[child].ascenderOffset = y_offset;
4266
4268 context->glyph_infos[child].attach_chain = (int)parent - (int)child;
4269 context->has_gpos_attachment = 1;
4270
4271 if (context->glyph_infos[parent].attach_chain == -context->glyph_infos[child].attach_chain)
4272 context->glyph_infos[parent].attach_chain = 0;
4273
4274 context->cur++;
4275 }
4276 else
4277 {
4278 WARN("Unknown cursive attachment format %u.\n", format);
4279 return FALSE;
4280 }
4281
4282 return TRUE;
4283}
4284
4285static BOOL opentype_layout_apply_mark_array(struct scriptshaping_context *context, unsigned int subtable_offset,
4286 unsigned int mark_array, unsigned int mark_index, unsigned int glyph_index, unsigned int anchors_matrix,
4287 unsigned int class_count, unsigned int glyph_pos)
4288{
4289 const struct dwrite_fonttable *table = &context->table->table;
4290 unsigned int mark_class, mark_count, glyph_count;
4291 const struct ot_gpos_mark_record *record;
4292 float mark_x, mark_y, base_x, base_y;
4293 const UINT16 *anchors;
4294
4295 mark_count = table_read_be_word(table, subtable_offset + mark_array);
4296 if (mark_index >= mark_count) return FALSE;
4297
4298 if (!(record = table_read_ensure(table, subtable_offset + mark_array +
4299 FIELD_OFFSET(struct ot_gpos_mark_array, records[mark_index]), sizeof(*record))))
4300 {
4301 return FALSE;
4302 }
4303
4304 mark_class = GET_BE_WORD(record->mark_class);
4305 if (mark_class >= class_count) return FALSE;
4306
4307 glyph_count = table_read_be_word(table, subtable_offset + anchors_matrix);
4308 if (glyph_index >= glyph_count) return FALSE;
4309
4310 /* Anchors data is stored as two dimensional array [glyph_count][class_count], starting with row count field. */
4311 anchors = table_read_ensure(table, subtable_offset + anchors_matrix + 2, glyph_count * class_count * sizeof(*anchors));
4312 if (!anchors) return FALSE;
4313
4314 opentype_layout_gpos_get_anchor(context, subtable_offset + mark_array + GET_BE_WORD(record->mark_anchor),
4315 context->cur, &mark_x, &mark_y);
4316 opentype_layout_gpos_get_anchor(context, subtable_offset + anchors_matrix +
4317 GET_BE_WORD(anchors[glyph_index * class_count + mark_class]), glyph_pos, &base_x, &base_y);
4318
4319 if (context->is_rtl)
4320 context->offsets[context->cur].advanceOffset = mark_x - base_x;
4321 else
4322 context->offsets[context->cur].advanceOffset = base_x - mark_x;
4323 context->offsets[context->cur].ascenderOffset = base_y - mark_y;
4325 context->glyph_infos[context->cur].attach_chain = (int)glyph_pos - (int)context->cur;
4326 context->has_gpos_attachment = 1;
4327
4328 context->cur++;
4329
4330 return TRUE;
4331}
4332
4334 const struct lookup *lookup, unsigned int subtable_offset)
4335{
4336 const struct dwrite_fonttable *table = &context->table->table;
4337 WORD format;
4338
4339 format = table_read_be_word(table, subtable_offset);
4340
4341 if (format == 1)
4342 {
4343 const struct ot_gpos_mark_to_base_format1 *format1;
4344 unsigned int base_index, mark_index;
4345 struct glyph_iterator base_iter;
4346
4347 if (!(format1 = table_read_ensure(table, subtable_offset, sizeof(*format1)))) return FALSE;
4348
4349 mark_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->mark_coverage),
4350 context->u.pos.glyphs[context->cur]);
4351 if (mark_index == GLYPH_NOT_COVERED) return FALSE;
4352
4353 /* Look back for first base glyph. */
4355 if (!glyph_iterator_prev(&base_iter))
4356 return FALSE;
4357
4358 base_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->base_coverage),
4359 context->u.pos.glyphs[base_iter.pos]);
4360 if (base_index == GLYPH_NOT_COVERED) return FALSE;
4361
4362 return opentype_layout_apply_mark_array(context, subtable_offset, GET_BE_WORD(format1->mark_array), mark_index,
4363 base_index, GET_BE_WORD(format1->base_array), GET_BE_WORD(format1->mark_class_count), base_iter.pos);
4364 }
4365 else
4366 {
4367 WARN("Unknown mark-to-base format %u.\n", format);
4368 return FALSE;
4369 }
4370
4371 return TRUE;
4372}
4373
4374static const UINT16 * table_read_array_be_word(const struct dwrite_fonttable *table, unsigned int offset,
4375 unsigned int index, UINT16 *data)
4376{
4377 unsigned int count = table_read_be_word(table, offset);
4378 const UINT16 *array;
4379
4380 if (index != ~0u && index >= count) return NULL;
4381 if (!(array = table_read_ensure(table, offset + 2, count * sizeof(*array)))) return FALSE;
4382 *data = index == ~0u ? count : GET_BE_WORD(array[index]);
4383 return array;
4384}
4385
4387 const struct lookup *lookup, unsigned int subtable_offset)
4388{
4389 const struct dwrite_fonttable *table = &context->table->table;
4390 WORD format;
4391
4392 format = table_read_be_word(table, subtable_offset);
4393
4394 if (format == 1)
4395 {
4396 unsigned int mark_index, lig_index, comp_index, class_count, comp_count;
4397 const struct ot_gpos_mark_to_lig_format1 *format1;
4398 struct glyph_iterator lig_iter;
4399 unsigned int lig_array;
4400 UINT16 lig_attach;
4401
4402 if (!(format1 = table_read_ensure(table, subtable_offset, sizeof(*format1)))) return FALSE;
4403
4404 mark_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->mark_coverage),
4405 context->u.pos.glyphs[context->cur]);
4406 if (mark_index == GLYPH_NOT_COVERED) return FALSE;
4407
4409 if (!glyph_iterator_prev(&lig_iter))
4410 return FALSE;
4411
4412 lig_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->lig_coverage),
4413 context->u.pos.glyphs[lig_iter.pos]);
4414 if (lig_index == GLYPH_NOT_COVERED) return FALSE;
4415
4416 class_count = GET_BE_WORD(format1->mark_class_count);
4417
4418 lig_array = GET_BE_WORD(format1->lig_array);
4419
4420 if (!table_read_array_be_word(table, subtable_offset + lig_array, lig_index, &lig_attach)) return FALSE;
4421
4422 comp_count = table_read_be_word(table, subtable_offset + lig_array + lig_attach);
4423 if (!comp_count) return FALSE;
4424
4425 comp_index = context->u.buffer.glyph_props[lig_iter.pos].components -
4426 context->u.buffer.glyph_props[context->cur].lig_component - 1;
4427 if (comp_index >= comp_count) return FALSE;
4428
4429 return opentype_layout_apply_mark_array(context, subtable_offset, GET_BE_WORD(format1->mark_array), mark_index,
4430 comp_index, lig_array + lig_attach, class_count, lig_iter.pos);
4431 }
4432 else
4433 WARN("Unknown mark-to-ligature format %u.\n", format);
4434
4435 return FALSE;
4436}
4437
4439 const struct lookup *lookup, unsigned int subtable_offset)
4440{
4441 const struct dwrite_fonttable *table = &context->table->table;
4442 WORD format;
4443
4444 format = table_read_be_word(table, subtable_offset);
4445
4446 if (format == 1)
4447 {
4448 const struct ot_gpos_mark_to_mark_format1 *format1;
4449 unsigned int mark1_index, mark2_index;
4450 struct glyph_iterator mark_iter;
4451
4452 if (!(format1 = table_read_ensure(table, subtable_offset, sizeof(*format1)))) return FALSE;
4453
4454 mark1_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->mark1_coverage),
4455 context->u.pos.glyphs[context->cur]);
4456 if (mark1_index == GLYPH_NOT_COVERED) return FALSE;
4457
4459 if (!glyph_iterator_prev(&mark_iter))
4460 return FALSE;
4461
4462 if (!context->u.pos.glyph_props[mark_iter.pos].isDiacritic)
4463 return FALSE;
4464
4465 mark2_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->mark2_coverage),
4466 context->u.pos.glyphs[mark_iter.pos]);
4467 if (mark2_index == GLYPH_NOT_COVERED) return FALSE;
4468
4469 return opentype_layout_apply_mark_array(context, subtable_offset, GET_BE_WORD(format1->mark1_array), mark1_index,
4470 mark2_index, GET_BE_WORD(format1->mark2_array), GET_BE_WORD(format1->mark_class_count), mark_iter.pos);
4471 }
4472 else
4473 {
4474 WARN("Unknown mark-to-mark format %u.\n", format);
4475 return FALSE;
4476 }
4477
4478 return TRUE;
4479}
4480
4482 unsigned int subtable_offset);
4484 unsigned int subtable_offset);
4485
4487{
4488 unsigned int i, lookup_type;
4489 BOOL ret = FALSE;
4490
4491 for (i = 0; i < lookup->subtable_count; ++i)
4492 {
4493 unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup, i, &lookup_type);
4494
4495 switch (lookup_type)
4496 {
4499 break;
4502 break;
4505 break;
4508 break;
4511 break;
4514 break;
4516 ret = opentype_layout_apply_context(context, lookup, subtable_offset);
4517 break;
4520 break;
4522 WARN("Recursive extension lookup.\n");
4523 break;
4524 default:
4525 WARN("Unknown lookup type %u.\n", lookup_type);
4526 }
4527
4528 if (ret)
4529 break;
4530 }
4531
4532 return ret;
4533}
4534
4536{
4538 size_t capacity;
4539 size_t count;
4540};
4541
4542static int __cdecl lookups_sorting_compare(const void *a, const void *b)
4543{
4544 const struct lookup *left = (const struct lookup *)a;
4545 const struct lookup *right = (const struct lookup *)b;
4546 return left->index < right->index ? -1 : left->index > right->index ? 1 : 0;
4547};
4548
4549static BOOL opentype_layout_init_lookup(const struct ot_gsubgpos_table *table, unsigned short lookup_index,
4550 const struct shaping_feature *feature, struct lookup *lookup)
4551{
4552 unsigned short subtable_count, lookup_type, mark_filtering_set;
4553 const struct ot_lookup_table *lookup_table;
4554 unsigned int offset, flags;
4555
4556 if (!(offset = table_read_be_word(&table->table, table->lookup_list +
4557 FIELD_OFFSET(struct ot_lookup_list, lookup[lookup_index]))))
4558 {
4559 return FALSE;
4560 }
4561
4562 offset += table->lookup_list;
4563
4564 if (!(lookup_table = table_read_ensure(&table->table, offset, sizeof(*lookup_table))))
4565 return FALSE;
4566
4567 if (!(subtable_count = GET_BE_WORD(lookup_table->subtable_count)))
4568 return FALSE;
4569
4570 lookup_type = GET_BE_WORD(lookup_table->lookup_type);
4571 flags = GET_BE_WORD(lookup_table->flags);
4572
4574 {
4575 mark_filtering_set = table_read_be_word(&table->table, offset +
4577 flags |= mark_filtering_set << 16;
4578 }
4579
4580 lookup->index = lookup_index;
4582 lookup->flags = flags;
4584 lookup->offset = offset;
4585 if (feature)
4586 {
4587 lookup->mask = feature->mask;
4590 }
4591
4592 return TRUE;
4593}
4594
4595static void opentype_layout_add_lookups(const struct ot_feature_list *feature_list, UINT16 total_lookup_count,
4596 const struct ot_gsubgpos_table *table, struct shaping_feature *feature, struct lookups *lookups)
4597{
4598 UINT16 feature_offset, lookup_count;
4599 unsigned int i;
4600
4601 /* Feature wasn't found */
4602 if (feature->index == 0xffff)
4603 return;
4604
4605 feature_offset = GET_BE_WORD(feature_list->features[feature->index].offset);
4606
4607 lookup_count = table_read_be_word(&table->table, table->feature_list + feature_offset +
4608 FIELD_OFFSET(struct ot_feature, lookup_count));
4609 if (!lookup_count)
4610 return;
4611
4612 if (!dwrite_array_reserve((void **)&lookups->lookups, &lookups->capacity, lookups->count + lookup_count,
4613 sizeof(*lookups->lookups)))
4614 {
4615 return;
4616 }
4617
4618 for (i = 0; i < lookup_count; ++i)
4619 {
4620 UINT16 lookup_index = table_read_be_word(&table->table, table->feature_list + feature_offset +
4621 FIELD_OFFSET(struct ot_feature, lookuplist_index[i]));
4622
4623 if (lookup_index >= total_lookup_count)
4624 continue;
4625
4627 lookups->count++;
4628 }
4629}
4630
4631static void opentype_layout_collect_lookups(struct scriptshaping_context *context, unsigned int script_index,
4632 unsigned int language_index, struct shaping_features *features, const struct ot_gsubgpos_table *table,
4633 struct lookups *lookups)
4634{
4635 unsigned int last_num_lookups = 0, stage, script_feature_count = 0;
4636 UINT16 total_feature_count, total_lookup_count;
4637 struct shaping_feature required_feature = { 0 };
4638 const struct ot_feature_list *feature_list;
4639 const struct ot_langsys *langsys = NULL;
4640 struct shaping_feature *feature;
4641 unsigned int i, j, next_bit;
4642 unsigned int global_bit_shift = 1;
4643 unsigned int global_bit_mask = 2;
4644 UINT16 feature_index;
4645
4646 if (!table->table.data)
4647 return;
4648
4649 if (script_index != ~0u)
4650 {
4651 unsigned int table_offset, langsys_offset;
4652
4653 /* ScriptTable offset. */
4654 table_offset = table_read_be_word(&table->table, table->script_list + FIELD_OFFSET(struct ot_script_list, scripts) +
4655 script_index * sizeof(struct ot_script_record) + FIELD_OFFSET(struct ot_script_record, script));
4656 if (!table_offset)
4657 return;
4658
4659 if (language_index == ~0u)
4660 langsys_offset = table_read_be_word(&table->table, table->script_list + table_offset);
4661 else
4662 langsys_offset = table_read_be_word(&table->table, table->script_list + table_offset +
4663 FIELD_OFFSET(struct ot_script, langsys) + language_index * sizeof(struct ot_langsys_record) +
4664 FIELD_OFFSET(struct ot_langsys_record, langsys));
4665 langsys_offset += table->script_list + table_offset;
4666
4667 script_feature_count = table_read_be_word(&table->table, langsys_offset + FIELD_OFFSET(struct ot_langsys, feature_count));
4668 if (script_feature_count)
4669 langsys = table_read_ensure(&table->table, langsys_offset,
4670 FIELD_OFFSET(struct ot_langsys, feature_index[script_feature_count]));
4671 if (!langsys)
4672 script_feature_count = 0;
4673 }
4674
4675 total_feature_count = table_read_be_word(&table->table, table->feature_list);
4676 if (!total_feature_count)
4677 return;
4678
4679 total_lookup_count = table_read_be_word(&table->table, table->lookup_list);
4680 if (!total_lookup_count)
4681 return;
4682
4683 feature_list = table_read_ensure(&table->table, table->feature_list,
4684 FIELD_OFFSET(struct ot_feature_list, features[total_feature_count]));
4685 if (!feature_list)
4686 return;
4687
4688 /* Required feature. */
4689 required_feature.index = langsys ? GET_BE_WORD(langsys->required_feature_index) : 0xffff;
4690 if (required_feature.index < total_feature_count)
4691 required_feature.tag = feature_list->features[required_feature.index].tag;
4692 required_feature.mask = global_bit_mask;
4693
4694 context->global_mask = global_bit_mask;
4695 next_bit = global_bit_shift + 1;
4696 for (i = 0; i < features->count; ++i)
4697 {
4698 BOOL found = FALSE;
4699 DWORD bits_needed;
4700
4701 feature = &features->features[i];
4702
4703 feature->index = 0xffff;
4704
4705 if ((feature->flags & FEATURE_GLOBAL) && feature->max_value == 1)
4706 bits_needed = 0;
4707 else
4708 {
4709 BitScanReverse(&bits_needed, min(feature->max_value, 256));
4710 bits_needed++;
4711 }
4712
4713 if (!feature->max_value || next_bit + bits_needed > 8 * sizeof (feature->mask))
4714 continue;
4715
4716 if (required_feature.tag == feature->tag)
4717 required_feature.stage = feature->stage;
4718
4719 for (j = 0; j < script_feature_count; ++j)
4720 {
4721 feature_index = GET_BE_WORD(langsys->feature_index[j]);
4722 if (feature_index >= total_feature_count)
4723 continue;
4724 if ((found = feature_list->features[feature_index].tag == feature->tag))
4725 {
4726 feature->index = feature_index;
4727 break;
4728 }
4729 }
4730
4731 if (!found && (features->features[i].flags & FEATURE_GLOBAL_SEARCH))
4732 {
4733 for (j = 0; j < total_feature_count; ++j)
4734 {
4735 if ((found = (feature_list->features[j].tag == feature->tag)))
4736 {
4737 feature->index = j;
4738 break;
4739 }
4740 }
4741 }
4742
4743 if (!found && !(features->features[i].flags & FEATURE_HAS_FALLBACK))
4744 continue;
4745
4746 if (feature->flags & FEATURE_GLOBAL && feature->max_value == 1)
4747 {
4748 feature->shift = global_bit_shift;
4749 feature->mask = global_bit_mask;
4750 }
4751 else
4752 {
4753 feature->shift = next_bit;
4754 feature->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
4755 next_bit += bits_needed;
4756 context->global_mask |= (feature->default_value << feature->shift) & feature->mask;
4757 }
4758 if (!found)
4760 }
4761
4762 for (stage = 0; stage <= features->stage; ++stage)
4763 {
4764 if (required_feature.index != 0xffff && required_feature.stage == stage)
4765 opentype_layout_add_lookups(feature_list, total_lookup_count, table, &required_feature, lookups);
4766
4767 for (i = 0; i < features->count; ++i)
4768 {
4769 if (features->features[i].stage == stage)
4770 opentype_layout_add_lookups(feature_list, total_lookup_count, table, &features->features[i], lookups);
4771 }
4772
4773 /* Sort and merge lookups for current stage. */
4774 if (last_num_lookups < lookups->count)
4775 {
4776 qsort(lookups->lookups + last_num_lookups, lookups->count - last_num_lookups, sizeof(*lookups->lookups),
4778
4779 j = last_num_lookups;
4780 for (i = j + 1; i < lookups->count; ++i)
4781 {
4782 if (lookups->lookups[i].index != lookups->lookups[j].index)
4783 {
4784 lookups->lookups[++j] = lookups->lookups[i];
4785 }
4786 else
4787 {
4788 lookups->lookups[j].mask |= lookups->lookups[i].mask;
4789 lookups->lookups[j].auto_zwnj &= lookups->lookups[i].auto_zwnj;
4790 lookups->lookups[j].auto_zwj &= lookups->lookups[i].auto_zwj;
4791 }
4792 }
4793 lookups->count = j + 1;
4794 }
4795
4796 last_num_lookups = lookups->count;
4797 features->stages[stage].last_lookup = last_num_lookups;
4798 }
4799}
4800
4801static int __cdecl feature_search_compare(const void *a, const void* b)
4802{
4803 unsigned int tag = *(unsigned int *)a;
4804 const struct shaping_feature *feature = b;
4805
4806 return tag < feature->tag ? -1 : tag > feature->tag ? 1 : 0;
4807}
4808
4809static unsigned int shaping_features_get_mask(const struct shaping_features *features, unsigned int tag, unsigned int *shift)
4810{
4811 struct shaping_feature *feature;
4812
4813 feature = bsearch(&tag, features->features, features->count, sizeof(*features->features), feature_search_compare);
4814
4815 if (!feature || feature->index == 0xffff)
4816 return 0;
4817
4818 if (shift) *shift = feature->shift;
4819 return feature->mask;
4820}
4821
4822unsigned int shape_get_feature_1_mask(const struct shaping_features *features, unsigned int tag)
4823{
4824 unsigned int shift, mask = shaping_features_get_mask(features, tag, &shift);
4825 return (1 << shift) & mask;
4826}
4827
4829 unsigned int end_char, unsigned int *start_glyph, unsigned int *end_glyph)
4830{
4831 *start_glyph = context->u.buffer.clustermap[start_char];
4832 if (end_char >= context->length - 1)
4833 *end_glyph = context->glyph_count - 1;
4834 else
4835 *end_glyph = context->u.buffer.clustermap[end_char] - 1;
4836}
4837
4839{
4840 const DWRITE_TYPOGRAPHIC_FEATURES **user_features = context->user_features.features;
4841 unsigned int f, r, g, start_char, mask, shift, value;
4842
4843 for (g = 0; g < context->glyph_count; ++g)
4844 context->glyph_infos[g].mask = context->global_mask;
4845
4846 if (opentype_layout_is_subst_context(context) && context->shaper->setup_masks)
4847 context->shaper->setup_masks(context, features);
4848
4849 for (r = 0, start_char = 0; r < context->user_features.range_count; ++r)
4850 {
4851 unsigned int start_glyph, end_glyph;
4852
4853 if (start_char >= context->length)
4854 break;
4855
4856 if (!context->user_features.range_lengths[r])
4857 continue;
4858
4859 opentype_layout_get_glyph_range_for_text(context, start_char, start_char + context->user_features.range_lengths[r],
4860 &start_glyph, &end_glyph);
4861 start_char += context->user_features.range_lengths[r];
4862
4863 if (start_glyph > end_glyph || end_glyph >= context->glyph_count)
4864 continue;
4865
4866 for (f = 0; f < user_features[r]->featureCount; ++f)
4867 {
4868 mask = shaping_features_get_mask(features, user_features[r]->features[f].nameTag, &shift);
4869 if (!mask)
4870 continue;
4871
4872 value = (user_features[r]->features[f].parameter << shift) & mask;
4873
4874 for (g = start_glyph; g <= end_glyph; ++g)
4875 context->glyph_infos[g].mask = (context->glyph_infos[g].mask & ~mask) | value;
4876 }
4877 }
4878}
4879
4880static void opentype_layout_apply_gpos_context_lookup(struct scriptshaping_context *context, unsigned int lookup_index)
4881{
4882 struct lookup lookup = { 0 };
4883 if (opentype_layout_init_lookup(context->table, lookup_index, NULL, &lookup))
4885}
4886
4888{
4890 int chain = context->glyph_infos[i].attach_chain;
4891 unsigned int j, k;
4892
4893 if (!chain)
4894 return;
4895
4896 context->glyph_infos[i].attach_chain = 0;
4897
4898 j = (int)i + chain;
4899 if (j >= context->glyph_count)
4900 return;
4901
4903
4905 {
4906 /* FIXME: handle vertical direction. */
4907 context->offsets[i].ascenderOffset += context->offsets[j].ascenderOffset;
4908 }
4909 else if (type == GLYPH_ATTACH_MARK)
4910 {
4911 context->offsets[i].advanceOffset += context->offsets[j].advanceOffset;
4912 context->offsets[i].ascenderOffset += context->offsets[j].ascenderOffset;
4913
4914 /* FIXME: handle vertical adjustment. */
4915 if (context->is_rtl)
4916 {
4917 for (k = j + 1; k < i + 1; ++k)
4918 {
4919 context->offsets[i].advanceOffset += context->advances[k];
4920 }
4921 }
4922 else
4923 {
4924 for (k = j; k < i; k++)
4925 {
4926 context->offsets[i].advanceOffset -= context->advances[k];
4927 }
4928 }
4929 }
4930}
4931
4933 unsigned int language_index, struct shaping_features *features)
4934{
4935 struct lookups lookups = { 0 };
4936 unsigned int i;
4937 BOOL ret;
4938
4939 context->nesting_level_left = SHAPE_MAX_NESTING_LEVEL;
4940 context->u.buffer.apply_context_lookup = opentype_layout_apply_gpos_context_lookup;
4941 opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gpos, &lookups);
4942
4943 for (i = 0; i < context->glyph_count; ++i)
4946
4947 for (i = 0; i < lookups.count; ++i)
4948 {
4949 const struct lookup *lookup = &lookups.lookups[i];
4950
4951 context->cur = 0;
4952 context->lookup_mask = lookup->mask;
4953 context->auto_zwnj = lookup->auto_zwnj;
4954 context->auto_zwj = lookup->auto_zwj;
4955
4956 while (context->cur < context->glyph_count)
4957 {
4958 ret = FALSE;
4959
4960 if ((context->glyph_infos[context->cur].mask & lookup->mask) &&
4962 {
4964 }
4965
4966 if (!ret)
4967 context->cur++;
4968 }
4969 }
4970
4972
4973 if (context->has_gpos_attachment)
4974 {
4975 for (i = 0; i < context->glyph_count; ++i)
4977 }
4978}
4979
4981{
4982 UINT16 orig_glyph = context->u.subst.glyphs[context->cur];
4983 if (glyph != orig_glyph)
4984 {
4985 context->u.subst.glyphs[context->cur] = glyph;
4987 }
4988}
4989
4991 unsigned int subtable_offset)
4992{
4993 const struct dwrite_fonttable *table = &context->table->table;
4994 UINT16 format, coverage, orig_glyph, glyph;
4995 unsigned int coverage_index;
4996
4997 orig_glyph = glyph = context->u.subst.glyphs[context->cur];
4998
4999 format = table_read_be_word(table, subtable_offset);
5000
5001 coverage = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsub_singlesubst_format1, coverage));
5002
5003 if (format == 1)
5004 {
5005 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5006 if (coverage_index == GLYPH_NOT_COVERED) return FALSE;
5007
5008 glyph = orig_glyph + table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsub_singlesubst_format1, delta));
5009 }
5010 else if (format == 2)
5011 {
5012 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5013 if (coverage_index == GLYPH_NOT_COVERED) return FALSE;
5014
5016 coverage_index, &glyph))
5017 {
5018 return FALSE;
5019 }
5020 }
5021 else
5022 {
5023 WARN("Unknown single substitution format %u.\n", format);
5024 return FALSE;
5025 }
5026
5028 context->cur++;
5029
5030 return TRUE;
5031}
5032
5034{
5036 struct shaping_glyph_info *glyph_infos;
5037 unsigned int new_capacity;
5038 UINT16 *glyphs;
5039 BOOL ret;
5040
5041 if (context->u.subst.capacity >= count)
5042 return TRUE;
5043
5044 new_capacity = context->u.subst.capacity * 2;
5045
5046 if ((glyphs = realloc(context->u.subst.glyphs, new_capacity * sizeof(*glyphs))))
5047 context->u.subst.glyphs = glyphs;
5048 if ((glyph_props = realloc(context->u.subst.glyph_props, new_capacity * sizeof(*glyph_props))))
5049 context->u.subst.glyph_props = glyph_props;
5050 if ((glyph_infos = realloc(context->glyph_infos, new_capacity * sizeof(*glyph_infos))))
5051 context->glyph_infos = glyph_infos;
5052
5053 if ((ret = (glyphs && glyph_props && glyph_infos)))
5054 context->u.subst.capacity = new_capacity;
5055
5056 return ret;
5057}
5058
5060 unsigned int subtable_offset)
5061{
5062 const struct dwrite_fonttable *table = &context->table->table;
5063 UINT16 format, coverage, glyph, glyph_count;
5064 unsigned int i, idx, coverage_index;
5065 const UINT16 *glyphs;
5066
5067 idx = context->cur;
5068 glyph = context->u.subst.glyphs[idx];
5069
5070 format = table_read_be_word(table, subtable_offset);
5071
5072 coverage = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsub_multsubst_format1, coverage));
5073
5074 if (format == 1)
5075 {
5076 UINT16 seq_offset;
5077
5078 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5079 if (coverage_index == GLYPH_NOT_COVERED) return FALSE;
5080
5081 if (!table_read_array_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsub_multsubst_format1, seq_count),
5082 coverage_index, &seq_offset))
5083 {
5084 return FALSE;
5085 }
5086
5087 if (!(glyphs = table_read_array_be_word(table, subtable_offset + seq_offset, ~0u, &glyph_count))) return FALSE;
5088
5089 if (glyph_count == 1)
5090 {
5091 /* Equivalent of single substitution. */
5093 context->cur++;
5094 }
5095 else if (glyph_count == 0)
5096 {
5097 context->cur++;
5098 }
5099 else
5100 {
5101 unsigned int shift_len, src_idx, dest_idx, mask;
5102
5103 /* Current glyph is also replaced. */
5104 glyph_count--;
5105
5106 if (!(opentype_layout_gsub_ensure_buffer(context, context->glyph_count + glyph_count)))
5107 return FALSE;
5108
5109 shift_len = context->cur + 1 < context->glyph_count ? context->glyph_count - context->cur - 1 : 0;
5110
5111 if (shift_len)
5112 {
5113 src_idx = context->cur + 1;
5114 dest_idx = src_idx + glyph_count;
5115
5116 memmove(&context->u.subst.glyphs[dest_idx], &context->u.subst.glyphs[src_idx],
5117 shift_len * sizeof(*context->u.subst.glyphs));
5118 memmove(&context->u.subst.glyph_props[dest_idx], &context->u.subst.glyph_props[src_idx],
5119 shift_len * sizeof(*context->u.subst.glyph_props));
5120 memmove(&context->glyph_infos[dest_idx], &context->glyph_infos[src_idx],
5121 shift_len * sizeof(*context->glyph_infos));
5122 }
5123
5124 mask = context->glyph_infos[context->cur].mask;
5125 for (i = 0, idx = context->cur; i <= glyph_count; ++i)
5126 {
5127 glyph = GET_BE_WORD(glyphs[i]);
5128 context->u.subst.glyphs[idx + i] = glyph;
5129 if (i)
5130 {
5131 context->u.subst.glyph_props[idx + i].isClusterStart = 0;
5132 context->u.buffer.glyph_props[idx + i].components = 0;
5133 context->glyph_infos[idx + i].start_text_idx = 0;
5134 }
5136 /* Inherit feature mask from original matched glyph. */
5137 context->glyph_infos[idx + i].mask = mask;
5138 }
5139
5140 context->cur += glyph_count + 1;
5141 context->glyph_count += glyph_count;
5142 }
5143 }
5144 else
5145 {
5146 WARN("Unknown multiple substitution format %u.\n", format);
5147 return FALSE;
5148 }
5149
5150 return TRUE;
5151}
5152
5154 unsigned int subtable_offset)
5155{
5156 const struct dwrite_fonttable *table = &context->table->table;
5157 unsigned int idx, coverage_index;
5158 UINT16 format, coverage, glyph;
5159
5160 idx = context->cur;
5161 glyph = context->u.subst.glyphs[idx];
5162
5163 format = table_read_be_word(table, subtable_offset);
5164
5165 if (format == 1)
5166 {
5167 const struct ot_gsub_altsubst_format1 *format1 = table_read_ensure(table, subtable_offset, sizeof(*format1));
5168 DWORD shift;
5169 unsigned int alt_index;
5170 UINT16 set_offset;
5171
5173
5174 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5175 if (coverage_index == GLYPH_NOT_COVERED) return FALSE;
5176
5178 coverage_index, &set_offset))
5179 return FALSE;
5180
5181 /* Argument is 1-based. */
5182 BitScanForward(&shift, context->lookup_mask);
5183 alt_index = (context->lookup_mask & context->glyph_infos[idx].mask) >> shift;
5184 if (!alt_index) return FALSE;
5185
5186 if (!table_read_array_be_word(table, subtable_offset + set_offset, alt_index - 1, &glyph)) return FALSE;
5187 }
5188 else
5189 {
5190 WARN("Unexpected alternate substitution format %d.\n", format);
5191 return FALSE;
5192 }
5193
5195 context->cur++;
5196
5197 return TRUE;
5198}
5199
5200static BOOL opentype_layout_context_match_input(const struct match_context *mc, unsigned int count, const UINT16 *input,
5201 unsigned int *end_offset, unsigned int *match_positions)
5202{
5203 struct match_data match_data = { .mc = mc, .subtable_offset = mc->input_offset };
5205 struct glyph_iterator iter;
5206 unsigned int i;
5207
5209 return FALSE;
5210
5211 match_positions[0] = context->cur;
5212
5213 glyph_iterator_init(context, mc->lookup->flags, context->cur, count - 1, &iter);
5214 iter.mask = context->lookup_mask;
5215 iter.match_func = mc->match_func;
5216 iter.match_data = &match_data;
5217 iter.glyph_data = input;
5218
5219 for (i = 1; i < count; ++i)
5220 {
5221 if (!glyph_iterator_next(&iter))
5222 return FALSE;
5223
5224 match_positions[i] = iter.pos;
5225 }
5226
5227 *end_offset = iter.pos - context->cur + 1;
5228
5229 return TRUE;
5230}
5231
5232/* Marks text segment as unsafe to break between [start, end) glyphs. */
5234 unsigned int end)
5235{
5236 unsigned int i;
5237
5238 while (start && !context->u.buffer.glyph_props[start].isClusterStart)
5239 --start;
5240
5241 while (--end && !context->u.buffer.glyph_props[end].isClusterStart)
5242 ;
5243
5244 if (start == end)
5245 {
5246 context->u.buffer.text_props[context->glyph_infos[start].start_text_idx].canBreakShapingAfter = 0;
5247 return;
5248 }
5249
5250 for (i = context->glyph_infos[start].start_text_idx; i < context->glyph_infos[end].start_text_idx; ++i)
5251 {
5252 context->u.buffer.text_props[i].canBreakShapingAfter = 0;
5253 }
5254}
5255
5257{
5258 unsigned int shift_len;
5259
5260 shift_len = context->glyph_count - context->cur - 1;
5261
5262 if (shift_len)
5263 {
5264 memmove(&context->u.buffer.glyphs[idx], &context->u.buffer.glyphs[idx + 1],
5265 shift_len * sizeof(*context->u.buffer.glyphs));
5266 memmove(&context->u.buffer.glyph_props[idx], &context->u.buffer.glyph_props[idx + 1],
5267 shift_len * sizeof(*context->u.buffer.glyph_props));
5268 memmove(&context->glyph_infos[idx], &context->glyph_infos[idx + 1], shift_len * sizeof(*context->glyph_infos));
5269 }
5270
5271 context->glyph_count--;
5272}
5273
5275 const struct lookup *lookup)
5276{
5277 struct match_context mc = { .context = context, .lookup = lookup, .match_func = opentype_match_glyph_func };
5278 const struct dwrite_fonttable *gsub = &context->table->table;
5279 unsigned int match_positions[GLYPH_CONTEXT_MAX_LENGTH];
5280 unsigned int i, j, comp_count, match_length = 0;
5281 const struct ot_gsub_lig *lig;
5283
5285
5286 if (!comp_count)
5287 return FALSE;
5288
5290 if (!lig)
5291 return FALSE;
5292
5294
5295 if (comp_count == 1)
5296 {
5298 context->cur++;
5299 return TRUE;
5300 }
5301
5302 if (!opentype_layout_context_match_input(&mc, comp_count, lig->components, &match_length, match_positions))
5303 return FALSE;
5304
5306 context->u.buffer.glyph_props[context->cur].components = comp_count;
5307
5308 /* Positioning against a ligature implies keeping track of ligature component
5309 glyph should be attached to. Update per-glyph property for interleaving glyphs,
5310 0 means attaching to last component, n - attaching to n-th glyph before last. */
5311 for (i = 1; i < comp_count; ++i)
5312 {
5313 j = match_positions[i - 1] + 1;
5314 while (j < match_positions[i])
5315 {
5316 context->u.buffer.glyph_props[j++].lig_component = comp_count - i;
5317 }
5318 }
5319 opentype_layout_unsafe_to_break(context, match_positions[0], match_positions[comp_count - 1] + 1);
5320
5321 /* Delete ligated glyphs, backwards to preserve index. */
5322 for (i = 1; i < comp_count; ++i)
5323 {
5324 opentype_layout_delete_glyph(context, match_positions[comp_count - i]);
5325 }
5326
5327 /* Skip whole matched sequence, accounting for deleted glyphs. */
5328 context->cur += match_length - (comp_count - 1);
5329
5330 return TRUE;
5331}
5332
5334 unsigned int subtable_offset)
5335{
5336 const struct dwrite_fonttable *table = &context->table->table;
5337 UINT16 format, coverage, glyph, lig_set_offset;
5338 unsigned int coverage_index;
5339
5340 glyph = context->u.subst.glyphs[context->cur];
5341
5342 format = table_read_be_word(table, subtable_offset);
5343
5344 if (format == 1)
5345 {
5346 const struct ot_gsub_ligsubst_format1 *format1 = table_read_ensure(table, subtable_offset, sizeof(*format1));
5347 unsigned int i;
5348 const UINT16 *offsets;
5349 UINT16 lig_count;
5350
5352
5353 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5354 if (coverage_index == GLYPH_NOT_COVERED) return FALSE;
5355
5357 coverage_index, &lig_set_offset))
5358 return FALSE;
5359
5360 if (!(offsets = table_read_array_be_word(table, subtable_offset + lig_set_offset, ~0u, &lig_count)))
5361 return FALSE;
5362
5363 /* First applicable ligature is used. */
5364 for (i = 0; i < lig_count; ++i)
5365 {
5366 if (opentype_layout_apply_ligature(context, subtable_offset + lig_set_offset + GET_BE_WORD(offsets[i]), lookup))
5367 return TRUE;
5368 }
5369 }
5370 else
5371 WARN("Unexpected ligature substitution format %d.\n", format);
5372
5373 return FALSE;
5374}
5375
5377 const UINT16 *backtrack, unsigned int *match_start)
5378{
5379 struct match_data match_data = { .mc = mc, .subtable_offset = mc->backtrack_offset };
5381 struct glyph_iterator iter;
5382 unsigned int i;
5383
5384 glyph_iterator_init(context, mc->lookup->flags, context->cur, count, &iter);
5385 iter.match_func = mc->match_func;
5386 iter.match_data = &match_data;
5387 iter.glyph_data = backtrack;
5388 iter.ignore_zwnj |= context->auto_zwnj;
5389 iter.ignore_zwj = 1;
5390
5391 for (i = 0; i < count; ++i)
5392 {
5393 if (!glyph_iterator_prev(&iter))
5394 return FALSE;
5395 }
5396
5397 *match_start = iter.pos;
5398
5399 return TRUE;
5400}
5401
5403 const UINT16 *lookahead, unsigned int offset, unsigned int *end_index)
5404{
5405 struct match_data match_data = { .mc = mc, .subtable_offset = mc->lookahead_offset };
5407 struct glyph_iterator iter;
5408 unsigned int i;
5409
5410 glyph_iterator_init(context, mc->lookup->flags, context->cur + offset - 1, count, &iter);
5411 iter.match_func = mc->match_func;
5412 iter.match_data = &match_data;
5413 iter.glyph_data = lookahead;
5414 iter.ignore_zwnj |= context->auto_zwnj;
5415 iter.ignore_zwj = 1;
5416
5417 for (i = 0; i < count; ++i)
5418 {
5419 if (!glyph_iterator_next(&iter))
5420 return FALSE;
5421 }
5422
5423 *end_index = iter.pos;
5424
5425 return TRUE;
5426}
5427
5429 unsigned int *match_positions, unsigned int lookup_count, const UINT16 *lookup_records, unsigned int match_length)
5430{
5431 unsigned int i, j;
5432 int end, delta;
5433
5434 if (!context->nesting_level_left)
5435 return TRUE;
5436
5437 end = context->cur + match_length;
5438
5439 for (i = 0; i < lookup_count; ++i)
5440 {
5441 unsigned int idx = GET_BE_WORD(lookup_records[i]);
5442 unsigned int orig_len, lookup_index, next;
5443
5444 if (idx >= count)
5445 continue;
5446
5447 context->cur = match_positions[idx];
5448
5449 orig_len = context->glyph_count;
5450
5451 lookup_index = GET_BE_WORD(lookup_records[i+1]);
5452
5453 --context->nesting_level_left;
5454 context->u.buffer.apply_context_lookup(context, lookup_index);
5455 ++context->nesting_level_left;
5456
5457 delta = context->glyph_count - orig_len;
5458 if (!delta)
5459 continue;
5460
5461 end += delta;
5462 if (end <= (int)match_positions[idx])
5463 {
5464 end = match_positions[idx];
5465 break;
5466 }
5467
5468 next = idx + 1;
5469
5470 if (delta > 0)
5471 {
5472 if (delta + count > GLYPH_CONTEXT_MAX_LENGTH)
5473 break;
5474 }
5475 else
5476 {
5477 delta = max(delta, (int)next - (int)count);
5478 next -= delta;
5479 }
5480
5481 memmove(match_positions + next + delta, match_positions + next,
5482 (count - next) * sizeof (*match_positions));
5483 next += delta;
5484 count += delta;
5485
5486 for (j = idx + 1; j < next; j++)
5487 match_positions[j] = match_positions[j - 1] + 1;
5488
5489 for (; next < count; next++)
5490 match_positions[next] += delta;
5491 }
5492
5493 context->cur = end;
5494
5495 return TRUE;
5496}
5497
5498static BOOL opentype_layout_apply_chain_context_match(unsigned int backtrack_count, const UINT16 *backtrack,
5499 unsigned int input_count, const UINT16 *input, unsigned int lookahead_count, const UINT16 *lookahead,
5500 unsigned int lookup_count, const UINT16 *lookup_records, const struct match_context *mc)
5501{
5502 unsigned int start_index = 0, match_length = 0, end_index = 0;
5503 unsigned int match_positions[GLYPH_CONTEXT_MAX_LENGTH];
5504
5505 return opentype_layout_context_match_input(mc, input_count, input, &match_length, match_positions) &&
5506 opentype_layout_context_match_backtrack(mc, backtrack_count, backtrack, &start_index) &&
5507 opentype_layout_context_match_lookahead(mc, lookahead_count, lookahead, input_count, &end_index) &&
5508 opentype_layout_context_apply_lookup(mc->context, input_count, match_positions, lookup_count, lookup_records, match_length);
5509}
5510
5512{
5513 unsigned int backtrack_count, input_count, lookahead_count, lookup_count;
5514 const struct dwrite_fonttable *table = &mc->context->table->table;
5515 const UINT16 *backtrack, *lookahead, *input, *lookup_records;
5516 const struct ot_gsubgpos_ruleset *ruleset;
5517 unsigned int i, count;
5518
5520 ruleset = table_read_ensure(table, offset, count * sizeof(ruleset->offsets));
5521
5522 for (i = 0; i < count; ++i)
5523 {
5524 unsigned int rule_offset = offset + GET_BE_WORD(ruleset->offsets[i]);
5525
5526 backtrack_count = table_read_be_word(table, rule_offset);
5527 rule_offset += 2;
5528 backtrack = table_read_ensure(table, rule_offset, backtrack_count * sizeof(*backtrack));
5529 rule_offset += backtrack_count * sizeof(*backtrack);
5530
5531 if (!(input_count = table_read_be_word(table, rule_offset)))
5532 continue;
5533
5534 rule_offset += 2;
5535 input = table_read_ensure(table, rule_offset, (input_count - 1) * sizeof(*input));
5536 rule_offset += (input_count - 1) * sizeof(*input);
5537
5538 lookahead_count = table_read_be_word(table, rule_offset);
5539 rule_offset += 2;
5540 lookahead = table_read_ensure(table, rule_offset, lookahead_count * sizeof(*lookahead));
5541 rule_offset += lookahead_count * sizeof(*lookahead);
5542
5543 lookup_count = table_read_be_word(table, rule_offset);
5544 rule_offset += 2;
5545 lookup_records = table_read_ensure(table, rule_offset, lookup_count * 2 * sizeof(*lookup_records));
5546
5547 /* First applicable rule is used. */
5548 if (opentype_layout_apply_chain_context_match(backtrack_count, backtrack, input_count, input, lookahead_count,
5549 lookahead, lookup_count, lookup_records, mc))
5550 {
5551 return TRUE;
5552 }
5553 }
5554
5555 return FALSE;
5556}
5557
5558static BOOL opentype_layout_apply_context_match(unsigned int input_count, const UINT16 *input, unsigned int lookup_count,
5559 const UINT16 *lookup_records, const struct match_context *mc)
5560{
5561 unsigned int match_positions[GLYPH_CONTEXT_MAX_LENGTH];
5562 unsigned int match_length = 0;
5563
5564 return opentype_layout_context_match_input(mc, input_count, input, &match_length, match_positions) &&
5565 opentype_layout_context_apply_lookup(mc->context, input_count, match_positions, lookup_count,
5566 lookup_records, match_length);
5567}
5568
5569static BOOL opentype_layout_apply_rule_set(const struct match_context *mc, unsigned int offset)
5570{
5571 unsigned int input_count, lookup_count;
5572 const struct dwrite_fonttable *table = &mc->context->table->table;
5573 const UINT16 *input, *lookup_records;
5574 const struct ot_gsubgpos_ruleset *ruleset;
5575 unsigned int i, count;
5576
5578 ruleset = table_read_ensure(table, offset, count * sizeof(ruleset->offsets));
5579
5580 for (i = 0; i < count; ++i)
5581 {
5582 unsigned int rule_offset = offset + GET_BE_WORD(ruleset->offsets[i]);
5583
5584 if (!(input_count = table_read_be_word(table, rule_offset)))
5585 continue;
5586 rule_offset += 2;
5587
5588 if (!(lookup_count = table_read_be_word(table, rule_offset)))
5589 continue;
5590 rule_offset += 2;
5591
5592 if (!(input = table_read_ensure(table, rule_offset, (input_count - 1) * sizeof(*input))))
5593 continue;
5594 rule_offset += (input_count - 1) * sizeof(*input);
5595
5596 if (!(lookup_records = table_read_ensure(table, rule_offset, lookup_count * 2 * sizeof(*lookup_records))))
5597 continue;
5598
5599 /* First applicable rule is used. */
5600 if (opentype_layout_apply_context_match(input_count, input, lookup_count, lookup_records, mc))
5601 return TRUE;
5602 }
5603
5604 return FALSE;
5605}
5606
5608 unsigned int subtable_offset)
5609{
5610 struct match_context mc = { .context = context, .lookup = lookup };
5611 const struct dwrite_fonttable *table = &context->table->table;
5612 unsigned int coverage_index = GLYPH_NOT_COVERED, count, offset;
5613 UINT16 glyph, format, coverage;
5614 BOOL ret = FALSE;
5615
5616 glyph = context->u.subst.glyphs[context->cur];
5617
5618 format = table_read_be_word(table, subtable_offset);
5619
5620 if (format == 1)
5621 {
5622 coverage = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsubgpos_context_format1, coverage));
5623
5624 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5625 if (coverage_index == GLYPH_NOT_COVERED)
5626 return FALSE;
5627
5628 count = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsubgpos_context_format1, ruleset_count));
5629 if (coverage_index >= count)
5630 return FALSE;
5631
5633 rulesets[coverage_index]));
5634 offset += subtable_offset;
5635
5637
5639 }
5640 else if (format == 2)
5641 {
5642 unsigned int input_classdef, rule_set_idx;
5643
5644 offset = subtable_offset + 2 /* format */;
5645
5646 coverage = table_read_be_word(table, offset);
5647 offset += 2;
5648
5649 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5650 if (coverage_index == GLYPH_NOT_COVERED)
5651 return FALSE;
5652
5653 input_classdef = table_read_be_word(table, offset) + subtable_offset;
5654 offset += 2;
5655
5657 offset+= 2;
5658
5659 rule_set_idx = opentype_layout_get_glyph_class(table, input_classdef, glyph);
5660 if (rule_set_idx >= count)
5661 return FALSE;
5662
5663 offset = table_read_be_word(table, offset + rule_set_idx * 2);
5664 offset += subtable_offset;
5665
5666 mc.input_offset = input_classdef;
5668
5670 }
5671 else if (format == 3)
5672 {
5673 unsigned int input_count, lookup_count;
5674 const UINT16 *input, *lookup_records;
5675
5676 offset = subtable_offset + 2 /* format */;
5677
5678 input_count = table_read_be_word(table, offset);
5679 offset += 2;
5680
5681 if (!input_count)
5682 return FALSE;
5683
5684 lookup_count = table_read_be_word(table, offset);
5685 offset += 2;
5686
5687 if (!(input = table_read_ensure(table, offset, sizeof(*input) * input_count)))
5688 return FALSE;
5689 offset += sizeof(*input) * input_count;
5690
5691 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(input[0]), glyph);
5692 if (coverage_index == GLYPH_NOT_COVERED)
5693 return FALSE;
5694
5695 lookup_records = table_read_ensure(table, offset, lookup_count * 2 * sizeof(*lookup_records));
5696
5697 mc.input_offset = subtable_offset;
5699
5700 ret = opentype_layout_apply_context_match(input_count, input + 1, lookup_count, lookup_records, &mc);
5701 }
5702 else
5703 WARN("Unknown contextual substitution format %u.\n", format);
5704
5705 return ret;
5706}
5707
5709 unsigned int subtable_offset)
5710{
5711 struct match_context mc = { .context = context, .lookup = lookup };
5712 const struct dwrite_fonttable *table = &context->table->table;
5713 unsigned int coverage_index = GLYPH_NOT_COVERED, count, offset;
5714 UINT16 glyph, format, coverage;
5715 BOOL ret = FALSE;
5716
5717 glyph = context->u.subst.glyphs[context->cur];
5718
5719 format = table_read_be_word(table, subtable_offset);
5720
5721 if (format == 1)
5722 {
5723 coverage = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsubgpos_context_format1, coverage));
5724
5725 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5726 if (coverage_index == GLYPH_NOT_COVERED)
5727 return FALSE;
5728
5729 count = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsubgpos_context_format1, ruleset_count));
5730 if (coverage_index >= count)
5731 return FALSE;
5732
5734 rulesets[coverage_index]));
5735 offset += subtable_offset;
5736
5738
5740 }
5741 else if (format == 2)
5742 {
5743 unsigned int backtrack_classdef, input_classdef, lookahead_classdef, rule_set_idx;
5744
5745 offset = subtable_offset + 2 /* format */;
5746
5747 coverage = table_read_be_word(table, offset);
5748 offset += 2;
5749
5750 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5751 if (coverage_index == GLYPH_NOT_COVERED)
5752 return FALSE;
5753
5754 backtrack_classdef = table_read_be_word(table, offset) + subtable_offset;
5755 offset += 2;
5756
5757 input_classdef = table_read_be_word(table, offset) + subtable_offset;
5758 offset += 2;
5759
5760 lookahead_classdef = table_read_be_word(table, offset) + subtable_offset;
5761 offset += 2;
5762
5764 offset+= 2;
5765
5766 rule_set_idx = opentype_layout_get_glyph_class(table, input_classdef, glyph);
5767 if (rule_set_idx >= count)
5768 return FALSE;
5769
5770 offset = table_read_be_word(table, offset + rule_set_idx * 2);
5771 offset += subtable_offset;
5772
5773 mc.backtrack_offset = backtrack_classdef;
5774 mc.input_offset = input_classdef;
5775 mc.lookahead_offset = lookahead_classdef;
5777
5779 }
5780 else if (format == 3)
5781 {
5782 unsigned int backtrack_count, input_count, lookahead_count, lookup_count;
5783 const UINT16 *backtrack, *lookahead, *input, *lookup_records;
5784
5785 offset = subtable_offset + 2 /* format */;
5786
5787 backtrack_count = table_read_be_word(table, offset);
5788 offset += 2;
5789 backtrack = table_read_ensure(table, offset, backtrack_count * sizeof(*backtrack));
5790 offset += backtrack_count * sizeof(*backtrack);
5791
5792 input_count = table_read_be_word(table, offset);
5793 offset += 2;
5794 input = table_read_ensure(table, offset, input_count * sizeof(*input));
5795 offset += input_count * sizeof(*input);
5796
5797 lookahead_count = table_read_be_word(table, offset);
5798 offset += 2;
5799 lookahead = table_read_ensure(table, offset, lookahead_count * sizeof(*lookahead));
5800 offset += lookahead_count * sizeof(*lookahead);
5801
5802 lookup_count = table_read_be_word(table, offset);
5803 offset += 2;
5804 lookup_records = table_read_ensure(table, offset, lookup_count * 2 * sizeof(*lookup_records));
5805
5806 if (input)
5807 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(input[0]), glyph);
5808
5809 if (coverage_index == GLYPH_NOT_COVERED)
5810 return FALSE;
5811
5812 mc.backtrack_offset = subtable_offset;
5813 mc.input_offset = subtable_offset;
5814 mc.lookahead_offset = subtable_offset;
5816
5817 ret = opentype_layout_apply_chain_context_match(backtrack_count, backtrack, input_count, input + 1, lookahead_count,
5818 lookahead, lookup_count, lookup_records, &mc);
5819 }
5820 else
5821 WARN("Unknown chaining contextual substitution format %u.\n", format);
5822
5823 return ret;
5824}
5825
5827 const struct lookup *lookup, unsigned int subtable_offset)
5828{
5829 const struct dwrite_fonttable *table = &context->table->table;
5830 unsigned int offset = subtable_offset;
5831 UINT16 glyph, format;
5832
5833 if (context->nesting_level_left != SHAPE_MAX_NESTING_LEVEL)
5834 return FALSE;
5835
5836 glyph = context->u.subst.glyphs[context->cur];
5837
5839 offset += 2;
5840
5841 if (format == 1)
5842 {
5843 struct match_context mc = { .context = context, .lookup = lookup };
5844 unsigned int start_index = 0, end_index = 0, backtrack_count, lookahead_count;
5845 unsigned int coverage, coverage_index;
5846 const UINT16 *backtrack, *lookahead;
5847
5848 coverage = table_read_be_word(table, offset);
5849 offset += 2;
5850
5851 coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
5852 if (coverage_index == GLYPH_NOT_COVERED)
5853 return FALSE;
5854
5855 backtrack_count = table_read_be_word(table, offset);
5856 offset += 2;
5857
5858 backtrack = table_read_ensure(table, offset, sizeof(*backtrack) * backtrack_count);
5859 offset += sizeof(*backtrack) * backtrack_count;
5860
5861 lookahead_count = table_read_be_word(table, offset);
5862 offset += 2;
5863
5864 lookahead = table_read_ensure(table, offset, sizeof(*lookahead) * lookahead_count);
5865 offset += sizeof(*lookahead) * lookahead_count;
5866
5868 mc.backtrack_offset = subtable_offset;
5869 mc.lookahead_offset = subtable_offset;
5870
5871 if (opentype_layout_context_match_backtrack(&mc, backtrack_count, backtrack, &start_index) &&
5872 opentype_layout_context_match_lookahead(&mc, lookahead_count, lookahead, 1, &end_index))
5873 {
5874 unsigned int glyph_count = table_read_be_word(table, offset);
5875 if (coverage_index >= glyph_count)
5876 return FALSE;
5877 offset += 2;
5878
5879 glyph = table_read_be_word(table, offset + coverage_index * sizeof(glyph));
5881
5882 return TRUE;
5883 }
5884 }
5885 else
5886 WARN("Unknown reverse chaining contextual substitution format %u.\n", format);
5887
5888 return FALSE;
5889}
5890
5892{
5893 unsigned int i, lookup_type;
5894 BOOL ret = FALSE;
5895
5896 for (i = 0; i < lookup->subtable_count; ++i)
5897 {
5898 unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup, i, &lookup_type);
5899
5900 switch (lookup_type)
5901 {
5904 break;
5907 break;
5910 break;
5913 break;
5915 ret = opentype_layout_apply_context(context, lookup, subtable_offset);
5916 break;
5919 break;
5922 break;
5924 WARN("Invalid lookup type for extension substitution %#x.\n", lookup_type);
5925 break;
5926 default:
5927 WARN("Unknown lookup type %u.\n", lookup_type);
5928 }
5929
5930 if (ret)
5931 break;
5932 }
5933
5934 return ret;
5935}
5936
5937static unsigned int unicode_get_mirrored_char(unsigned int codepoint)
5938{
5939 extern const WCHAR wine_mirror_map[];
5940 WCHAR mirror;
5941 /* TODO: check if mirroring for higher planes makes sense at all */
5942 if (codepoint > 0xffff) return codepoint;
5943 mirror = get_table_entry_16(wine_mirror_map, codepoint);
5944 return mirror ? mirror : codepoint;
5945}
5946
5947/*
5948 * 034F # Mn COMBINING GRAPHEME JOINER
5949 * 061C # Cf ARABIC LETTER MARK
5950 * 180B..180D # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
5951 * 180E # Cf MONGOLIAN VOWEL SEPARATOR
5952 * 200B..200F # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
5953 * FEFF # Cf ZERO WIDTH NO-BREAK SPACE
5954*/
5955static unsigned int opentype_is_zero_width(unsigned int codepoint)
5956{
5957 return codepoint == 0x34f || codepoint == 0x61c || codepoint == 0xfeff ||
5958 (codepoint >= 0x180b && codepoint <= 0x180e) || (codepoint >= 0x200b && codepoint <= 0x200f);
5959}
5960
5961/*
5962 * 00AD # Cf SOFT HYPHEN
5963 * 034F # Mn COMBINING GRAPHEME JOINER
5964 * 061C # Cf ARABIC LETTER MARK
5965 * 115F..1160 # Lo [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
5966 * 17B4..17B5 # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
5967 * 180B..180D # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
5968 * 180E # Cf MONGOLIAN VOWEL SEPARATOR
5969 * 200B..200F # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
5970 * 202A..202E # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
5971 * 2060..2064 # Cf [5] WORD JOINER..INVISIBLE PLUS
5972 * 2065 # Cn <reserved-2065>
5973 * 2066..206F # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
5974 * 3164 # Lo HANGUL FILLER
5975 * FE00..FE0F # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
5976 * FEFF # Cf ZERO WIDTH NO-BREAK SPACE
5977 * FFA0 # Lo HALFWIDTH HANGUL FILLER
5978 * FFF0..FFF8 # Cn [9] <reserved-FFF0>..<reserved-FFF8>
5979 * 1BCA0..1BCA3 # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
5980 * 1D173..1D17A # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
5981 * E0000 # Cn <reserved-E0000>
5982 * E0001 # Cf LANGUAGE TAG
5983 * E0002..E001F # Cn [30] <reserved-E0002>..<reserved-E001F>
5984 * E0020..E007F # Cf [96] TAG SPACE..CANCEL TAG
5985 * E0080..E00FF # Cn [128] <reserved-E0080>..<reserved-E00FF>
5986 * E0100..E01EF # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
5987 * E01F0..E0FFF # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
5988*/
5989static unsigned int opentype_is_default_ignorable(unsigned int codepoint)
5990{
5991 if (codepoint < 0x80) return 0;
5992 return codepoint == 0xad ||
5993 codepoint == 0x34f ||
5994 codepoint == 0x61c ||
5995 (codepoint >= 0x17b4 && codepoint <= 0x17b5) ||
5996 (codepoint >= 0x180b && codepoint <= 0x180e) ||
5997 (codepoint >= 0x200b && codepoint <= 0x200f) ||
5998 (codepoint >= 0x202a && codepoint <= 0x202e) ||
5999 (codepoint >= 0x2060 && codepoint <= 0x206f) ||
6000 (codepoint >= 0xfe00 && codepoint <= 0xfe0f) ||
6001 codepoint == 0xfeff ||
6002 (codepoint >= 0xfff0 && codepoint <= 0xfff8) ||
6003 (codepoint >= 0x1d173 && codepoint <= 0x1d17a) ||
6004 (codepoint >= 0xe0000 && codepoint <= 0xe0fff);
6005}
6006
6007static unsigned int opentype_is_diacritic(unsigned int codepoint)
6008{
6009 WCHAR ch = codepoint;
6010 WORD type = 0;
6011 /* Ignore higher planes for now. */
6012 if (codepoint > 0xffff) return 0;
6014 return !!(type & C3_DIACRITIC);
6015}
6016
6018{
6019 unsigned int rtlm_mask = shaping_features_get_mask(features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','m'), NULL);
6020 const struct shaping_font_ops *font = context->cache->font;
6021 unsigned int i, g, c, codepoint, cluster_start_idx = 0;
6022 UINT16 *clustermap = context->u.subst.clustermap;
6023 const WCHAR *text = context->text;
6024 BOOL bmp;
6025
6026 memset(context->u.subst.glyph_props, 0, context->u.subst.max_glyph_count * sizeof(*context->u.subst.glyph_props));
6027 memset(context->u.buffer.text_props, 0, context->length * sizeof(*context->u.buffer.text_props));
6028
6029 for (i = 0; i < context->length; ++i)
6030 {
6031 g = context->glyph_count;
6032
6033 if ((bmp = !(IS_HIGH_SURROGATE(text[i]) && (i < context->length - 1) && IS_LOW_SURROGATE(text[i + 1]))))
6034 {
6035 codepoint = text[i];
6036 }
6037 else
6038 {
6039 codepoint = 0x10000 + ((text[i] - 0xd800) << 10) + (text[i + 1] - 0xdc00);
6040 }
6041
6042 if (context->is_rtl)
6043 {
6044 c = unicode_get_mirrored_char(codepoint);
6045 if (c != codepoint && font->has_glyph(context->cache->context, c))
6046 codepoint = c;
6047 else
6048 context->glyph_infos[i].mask |= rtlm_mask;
6049 }
6050
6051 /* Glyph availability is not tested for a replacement digit. */
6052 if (*context->u.subst.digits && codepoint >= '0' && codepoint <= '9')
6053 codepoint = context->u.subst.digits[codepoint - '0'];
6054
6055 context->glyph_infos[g].codepoint = codepoint;
6056 context->u.buffer.glyphs[g] = font->get_glyph(context->cache->context, codepoint);
6057 context->u.buffer.glyph_props[g].justification = SCRIPT_JUSTIFY_CHARACTER;
6059 if (opentype_is_default_ignorable(codepoint))
6060 {
6061 context->glyph_infos[g].props |= GLYPH_PROP_IGNORABLE;
6062 if (codepoint == 0x200d)
6063 context->glyph_infos[g].props |= GLYPH_PROP_ZWJ;
6064 else if (codepoint == 0x200c)
6065 context->glyph_infos[g].props |= GLYPH_PROP_ZWNJ;
6066 /* Mongolian FVSs, TAGs, COMBINING GRAPHEME JOINER */
6067 else if ((codepoint >= 0x180b && codepoint <= 0x180d) ||
6068 (codepoint >= 0xe0020 && codepoint <= 0xe007f) ||
6069 codepoint == 0x34f)
6070 {
6071 context->glyph_infos[g].props |= GLYPH_PROP_HIDDEN;
6072 }
6073 }
6074
6075 /* Group diacritics with preceding base. Glyph class is ignored here. */
6076 if (!g || !opentype_is_diacritic(codepoint))
6077 {
6078 context->u.buffer.glyph_props[g].isClusterStart = 1;
6079 context->glyph_infos[g].start_text_idx = i;
6080 cluster_start_idx = g;
6081 }
6082 if (opentype_is_zero_width(codepoint))
6083 context->u.buffer.glyph_props[g].isZeroWidthSpace = 1;
6084
6085 context->u.buffer.glyph_props[g].components = 1;
6086 context->glyph_count++;
6087
6088 /* Set initial cluster map here, it's used for setting user features masks. */
6089 clustermap[i] = cluster_start_idx;
6090 if (bmp)
6091 context->u.buffer.text_props[i].canBreakShapingAfter = 1;
6092 else
6093 {
6094 clustermap[i + 1] = cluster_start_idx;
6095 context->u.buffer.text_props[i + 1].canBreakShapingAfter = 1;
6096 ++i;
6097 }
6098 }
6099}
6100
6102{
6103 unsigned int lookup_type;
6104
6107}
6108
6109static void opentype_layout_apply_gsub_context_lookup(struct scriptshaping_context *context, unsigned int lookup_index)
6110{
6111 struct lookup lookup = { 0 };
6112 if (opentype_layout_init_lookup(context->table, lookup_index, NULL, &lookup))
6114}
6115
6117 unsigned int language_index, struct shaping_features *features)
6118{
6119 struct lookups lookups = { 0 };
6120 unsigned int i = 0, j, start_idx;
6121 BOOL ret;
6122
6123 context->nesting_level_left = SHAPE_MAX_NESTING_LEVEL;
6124 context->u.buffer.apply_context_lookup = opentype_layout_apply_gsub_context_lookup;
6125 opentype_layout_collect_lookups(context, script_index, language_index, features, context->table, &lookups);
6126
6129
6130 for (j = 0; j <= features->stage; ++j)
6131 {
6132 for (; i < features->stages[j].last_lookup; ++i)
6133 {
6134 const struct lookup *lookup = &lookups.lookups[i];
6135
6136 context->lookup_mask = lookup->mask;
6137 context->auto_zwnj = lookup->auto_zwnj;
6138 context->auto_zwj = lookup->auto_zwj;
6139
6141 {
6142 context->cur = 0;
6143 while (context->cur < context->glyph_count)
6144 {
6145 ret = FALSE;
6146
6147 if ((context->glyph_infos[context->cur].mask & lookup->mask) &&
6149 {
6151 }
6152
6153 if (!ret)
6154 context->cur++;
6155 }
6156 }
6157 else
6158 {
6159 context->cur = context->glyph_count - 1;
6160
6161 for (;;)
6162 {
6163 if ((context->glyph_infos[context->cur].mask & lookup->mask) &&
6165 {
6167 }
6168
6169 if (context->cur == 0) break;
6170 --context->cur;
6171 }
6172 }
6173 }
6174
6175 if (features->stages[j].func)
6176 features->stages[j].func(context, features);
6177 }
6178
6179 /* For every glyph range of [<last>.isClusterStart, <next>.isClusterStart) set corresponding
6180 text span to start_idx. */
6181 start_idx = 0;
6182 for (i = 1; i < context->glyph_count; ++i)
6183 {
6184 if (context->u.buffer.glyph_props[i].isClusterStart)
6185 {
6186 unsigned int start_text, end_text;
6187
6188 start_text = context->glyph_infos[start_idx].start_text_idx;
6189 end_text = context->glyph_infos[i].start_text_idx;
6190
6191 for (j = start_text; j < end_text; ++j)
6192 context->u.buffer.clustermap[j] = start_idx;
6193
6194 start_idx = i;
6195 }
6196 }
6197
6198 /* Fill the tail. */
6199 for (j = context->glyph_infos[start_idx].start_text_idx; j < context->length; ++j)
6200 context->u.buffer.clustermap[j] = start_idx;
6201
6203}
6204
6206 unsigned int subtable_offset, unsigned int coverage, unsigned int format)
6207{
6208 const struct dwrite_fonttable *table = &context->table->table;
6209 const UINT16 *offsets;
6210 unsigned int count;
6211
6212 if (format == 1 || format == 2)
6213 {
6214 if (opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph) != GLYPH_NOT_COVERED)
6215 return TRUE;
6216 }
6217 else if (format == 3)
6218 {
6219 count = table_read_be_word(table, subtable_offset + 2);
6220 if (!count || !(offsets = table_read_ensure(table, subtable_offset + 6, count * sizeof(*offsets))))
6221 return FALSE;
6222
6223 if (opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(offsets[0]), glyph) != GLYPH_NOT_COVERED)
6224 return TRUE;
6225 }
6226
6227 return FALSE;
6228}
6229
6231 unsigned int subtable_offset, unsigned int coverage, unsigned int format)
6232{
6233 const struct dwrite_fonttable *table = &context->table->table;
6234 unsigned int count, backtrack_count;
6235 const UINT16 *offsets;
6236
6237 if (format == 1 || format == 2)
6238 {
6239 if (opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph) != GLYPH_NOT_COVERED)
6240 return TRUE;
6241 }
6242 else if (format == 3)
6243 {
6244 backtrack_count = table_read_be_word(table, subtable_offset + 2);
6245
6246 count = table_read_be_word(table, subtable_offset + 4 + backtrack_count * sizeof(*offsets));
6247
6248 if (!count || !(offsets = table_read_ensure(table, subtable_offset + 6 + backtrack_count * sizeof(*offsets),
6249 count * sizeof(*offsets))))
6250 return FALSE;
6251
6252 if (opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(offsets[0]), glyph) != GLYPH_NOT_COVERED)
6253 return TRUE;
6254 }
6255
6256 return FALSE;
6257}
6258
6260 const struct lookup *lookup)
6261{
6262 const struct dwrite_fonttable *gsub = &context->table->table;
6263 static const unsigned short gsub_formats[] =
6264 {
6265 0, /* Unused */
6266 1, /* SingleSubst */
6267 1, /* MultipleSubst */
6268 1, /* AlternateSubst */
6269 1, /* LigatureSubst */
6270 3, /* ContextSubst */
6271 3, /* ChainContextSubst */
6272 0, /* Extension, unused */
6273 1, /* ReverseChainSubst */
6274 };
6275 unsigned int i, coverage, lookup_type, format;
6276
6277 for (i = 0; i < lookup->subtable_count; ++i)
6278 {
6279 unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup, i, &lookup_type);
6280
6281 format = table_read_be_word(gsub, subtable_offset);
6282
6283 if (!format || format > ARRAY_SIZE(gsub_formats) || format > gsub_formats[lookup_type])
6284 break;
6285
6286 coverage = table_read_be_word(gsub, subtable_offset + 2);
6287
6288 switch (lookup_type)
6289 {
6295
6296 if (opentype_layout_is_glyph_covered(gsub, subtable_offset + coverage, glyph) != GLYPH_NOT_COVERED)
6297 return TRUE;
6298
6299 break;
6300
6302
6303 if (opentype_layout_contextual_lookup_is_glyph_covered(context, glyph, subtable_offset, coverage, format))
6304 return TRUE;
6305
6306 break;
6307
6309
6310 if (opentype_layout_chain_contextual_lookup_is_glyph_covered(context, glyph, subtable_offset, coverage, format))
6311 return TRUE;
6312
6313 break;
6314
6315 default:
6316 WARN("Unknown lookup type %u.\n", lookup_type);
6317 }
6318 }
6319
6320 return FALSE;
6321}
6322
6324 const struct lookup *lookup)
6325{
6326 const struct dwrite_fonttable *gpos = &context->table->table;
6327 static const unsigned short gpos_formats[] =
6328 {
6329 0, /* Unused */
6330 2, /* SinglePos */
6331 2, /* PairPos */
6332 1, /* CursivePos */
6333 1, /* MarkBasePos */
6334 1, /* MarkLigPos */
6335 1, /* MarkMarkPos */
6336 3, /* ContextPos */
6337 3, /* ChainContextPos */
6338 0, /* Extension, unused */
6339 };
6340 unsigned int i, coverage, lookup_type, format;
6341
6342 for (i = 0; i < lookup->subtable_count; ++i)
6343 {
6344 unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup, i, &lookup_type);
6345
6346 format = table_read_be_word(gpos, subtable_offset);
6347
6348 if (!format || format > ARRAY_SIZE(gpos_formats) || format > gpos_formats[lookup_type])
6349 break;
6350
6351 coverage = table_read_be_word(gpos, subtable_offset + 2);
6352
6353 switch (lookup_type)
6354 {
6361
6362 if (opentype_layout_is_glyph_covered(gpos, subtable_offset + coverage, glyph) != GLYPH_NOT_COVERED)
6363 return TRUE;
6364
6365 break;
6366
6368
6369 if (opentype_layout_contextual_lookup_is_glyph_covered(context, glyph, subtable_offset, coverage, format))
6370 return TRUE;
6371
6372 break;
6373
6375
6376 if (opentype_layout_chain_contextual_lookup_is_glyph_covered(context, glyph, subtable_offset, coverage, format))
6377 return TRUE;
6378
6379 break;
6380
6381 default:
6382 WARN("Unknown lookup type %u.\n", lookup_type);
6383 }
6384 }
6385
6386 return FALSE;
6387}
6388
6390
6392 unsigned int language_index, struct shaping_feature *feature, unsigned int glyph_count,
6393 const UINT16 *glyphs, UINT8 *feature_applies)
6394{
6395 p_lookup_is_glyph_covered_func func_is_covered;
6396 struct shaping_features features = { 0 };
6397 struct lookups lookups = { 0 };
6398 BOOL ret = FALSE, is_covered;
6399 unsigned int i, j, applies;
6400
6401 features.features = feature;
6402 features.count = 1;
6403
6404 for (i = 0; i < context->glyph_count; ++i)
6406
6407 opentype_layout_collect_lookups(context, script_index, language_index, &features, context->table, &lookups);
6408
6411
6412 for (i = 0; i < lookups.count; ++i)
6413 {
6414 struct lookup *lookup = &lookups.lookups[i];
6415
6416 applies = 0;
6417 for (j = 0; j < context->glyph_count; ++j)
6418 {
6420 {
6421 if ((is_covered = func_is_covered(context, glyphs[i], lookup)))
6422 ++applies;
6423 feature_applies[j] |= is_covered;
6424 }
6425 }
6426
6427 if ((ret = (applies == context->glyph_count)))
6428 break;
6429 }
6430
6432
6433 return ret;
6434}
6435
6437{
6438 unsigned int i, j, count = 0, lookup_type, subtable_offset;
6439 struct shaping_features features = { 0 };
6440 struct shaping_feature vert_feature = { 0 };
6441 struct scriptshaping_context context = { 0 };
6442 struct lookups lookups = { 0 };
6443 UINT16 format;
6444
6446 return !!(fontface->flags & FONTFACE_VERTICAL_VARIANTS);
6447
6448 context.cache = fontface_get_shaping_cache(fontface);
6449 context.table = &context.cache->gsub;
6450
6451 vert_feature.tag = DWRITE_MAKE_OPENTYPE_TAG('v','e','r','t');
6453 vert_feature.max_value = 1;
6454 vert_feature.default_value = 1;
6455
6456 features.features = &vert_feature;
6457 features.count = features.capacity = 1;
6458
6459 opentype_layout_collect_lookups(&context, ~0u, ~0u, &features, context.table, &lookups);
6460
6461 for (i = 0; i < lookups.count && !count; ++i)
6462 {
6463 const struct dwrite_fonttable *table = &context.table->table;
6464 const struct lookup *lookup = &lookups.lookups[i];
6465
6466 for (j = 0; j < lookup->subtable_count && !count; ++j)
6467 {
6468 subtable_offset = opentype_layout_get_gsubgpos_subtable(&context, lookup, j, &lookup_type);
6469
6470 if (lookup_type != GSUB_LOOKUP_SINGLE_SUBST)
6471 continue;
6472
6473 format = table_read_be_word(table, subtable_offset);
6474
6475 if (format == 1)
6476 {
6477 count = 1;
6478 }
6479 else if (format == 2)
6480 {
6482 }
6483 else
6484 WARN("Unrecognized single substitution format %u.\n", format);
6485 }
6486 }
6487
6489
6490 if (count)
6491 fontface->flags |= FONTFACE_VERTICAL_VARIANTS;
6492 else
6494
6495 return !!(fontface->flags & FONTFACE_VERTICAL_VARIANTS);
6496}
6497
6498HRESULT opentype_get_vertical_glyph_variants(struct dwrite_fontface *fontface, unsigned int glyph_count,
6499 const UINT16 *nominal_glyphs, UINT16 *glyphs)
6500{
6501 struct shaping_features features = { 0 };
6502 struct shaping_feature vert_feature = { 0 };
6503 struct scriptshaping_context context = { 0 };
6504 struct lookups lookups = { 0 };
6505 unsigned int i;
6506
6507 memcpy(glyphs, nominal_glyphs, glyph_count * sizeof(*glyphs));
6508
6509 if (!opentype_has_vertical_variants(fontface))
6510 return S_OK;
6511
6512 context.cache = fontface_get_shaping_cache(fontface);
6513 context.u.subst.glyphs = glyphs;
6514 context.u.subst.glyph_props = calloc(glyph_count, sizeof(*context.u.subst.glyph_props));
6515 context.u.subst.max_glyph_count = glyph_count;
6516 context.u.subst.capacity = glyph_count;
6517 context.glyph_infos = calloc(glyph_count, sizeof(*context.glyph_infos));
6518 context.table = &context.cache->gsub;
6519
6520 vert_feature.tag = DWRITE_MAKE_OPENTYPE_TAG('v','e','r','t');
6522 vert_feature.max_value = 1;
6523 vert_feature.default_value = 1;
6524
6525 features.features = &vert_feature;
6526 features.count = features.capacity = 1;
6527
6528 opentype_layout_collect_lookups(&context, ~0u, ~0u, &features, context.table, &lookups);
6530
6531 for (i = 0; i < lookups.count; ++i)
6532 {
6533 const struct lookup *lookup = &lookups.lookups[i];
6534
6535 context.cur = 0;
6536 while (context.cur < context.glyph_count)
6537 {
6538 BOOL ret = FALSE;
6539
6542
6543 if (!ret)
6544 context.cur++;
6545 }
6546 }
6547
6548 free(context.u.subst.glyph_props);
6549 free(context.glyph_infos);
6551
6552 return S_OK;
6553}
6554
6556{
6557 const struct kern_subtable_header *subtable;
6558 struct file_stream_desc stream_desc;
6559 const struct kern_header *header;
6560 unsigned int offset, count, i;
6561
6563 return !!(fontface->flags & FONTFACE_KERNING_PAIRS);
6564
6565 fontface->flags |= FONTFACE_NO_KERNING_PAIRS;
6566
6567 stream_desc.stream = fontface->stream;
6568 stream_desc.face_type = fontface->type;
6569 stream_desc.face_index = fontface->index;
6570
6571 opentype_get_font_table(&stream_desc, MS_KERN_TAG, &fontface->kern);
6572 if (fontface->kern.exists)
6573 {
6574 if ((header = table_read_ensure(&fontface->kern, 0, sizeof(*header))))
6575 {
6576 count = GET_BE_WORD(header->table_count);
6577 offset = sizeof(*header);
6578
6579 /* FreeType limits table count this way. */
6580 count = min(count, 32);
6581
6582 /* Check for presence of format 0 subtable with horizontal coverage. */
6583 for (i = 0; i < count; ++i)
6584 {
6585 if (!(subtable = table_read_ensure(&fontface->kern, offset, sizeof(*subtable))))
6586 break;
6587
6588 if (subtable->version == 0 && GET_BE_WORD(subtable->coverage) & 1)
6589 {
6590 fontface->flags &= ~FONTFACE_NO_KERNING_PAIRS;
6591 fontface->flags |= FONTFACE_KERNING_PAIRS;
6592 break;
6593 }
6594
6595 offset += GET_BE_WORD(subtable->length);
6596 }
6597 }
6598 }
6599
6600 if (fontface->flags & FONTFACE_NO_KERNING_PAIRS && fontface->kern.data)
6601 IDWriteFontFileStream_ReleaseFileFragment(stream_desc.stream, fontface->kern.context);
6602
6603 return !!(fontface->flags & FONTFACE_KERNING_PAIRS);
6604}
6605
6607{
6610};
6611
6612static int __cdecl kern_format0_compare(const void *a, const void *b)
6613{
6614 const struct kern_format0_compare_key *key = a;
6615 const WORD *data = b;
6617 int ret;
6618
6619 if ((ret = (int)key->left - (int)left)) return ret;
6620 if ((ret = (int)key->right - (int)right)) return ret;
6621 return 0;
6622}
6623
6625 const UINT16 *glyphs, INT32 *values)
6626{
6627 const struct kern_subtable_header *subtable;
6628 unsigned int i, s, offset, pair_count, subtable_count;
6630 const struct kern_header *header;
6631 const WORD *data;
6632
6633 if (!opentype_has_kerning_pairs(fontface))
6634 {
6635 memset(values, 0, count * sizeof(*values));
6636 return S_OK;
6637 }
6638
6639 subtable_count = table_read_be_word(&fontface->kern, 2);
6640 subtable_count = min(subtable_count, 32);
6641
6642 for (i = 0; i < count - 1; ++i)
6643 {
6644 offset = sizeof(*header);
6645
6646 key.left = glyphs[i];
6647 key.right = glyphs[i + 1];
6648 values[i] = 0;
6649
6650 for (s = 0; s < subtable_count; ++s)
6651 {
6652 if (!(subtable = table_read_ensure(&fontface->kern, offset, sizeof(*subtable))))
6653 break;
6654
6655 if (subtable->version == 0 && GET_BE_WORD(subtable->coverage) & 1)
6656 {
6657 if ((data = table_read_ensure(&fontface->kern, offset, GET_BE_WORD(subtable->length))))
6658 {
6659 /* Skip subtable header */
6660 data += 3;
6661 pair_count = GET_BE_WORD(*data);
6662 data += 4;
6663 /* Move to pair data */
6664 if ((data = table_read_ensure(&fontface->kern, offset + 7 * sizeof(*data),
6665 pair_count * 3 * sizeof(*data))))
6666 {
6667 if ((data = bsearch(&key, data, pair_count, 3 * sizeof(*data), kern_format0_compare)))
6668 {
6669 values[i] = (short)GET_BE_WORD(data[2]);
6670 break;
6671 }
6672 }
6673 }
6674 }
6675
6676 offset += GET_BE_WORD(subtable->length);
6677 }
6678 }
6679 values[count - 1] = 0;
6680
6681 return S_OK;
6682}
6683
6684static void opentype_font_var_add_static_axis(struct dwrite_var_axis **axis, unsigned int *axis_count,
6685 unsigned int tag, float value)
6686{
6687 struct dwrite_var_axis *entry = &(*axis)[(*axis_count)++];
6688 entry->tag = tag;
6689 entry->min_value = entry->max_value = entry->default_value = value;
6690 entry->attributes = 0;
6691}
6692
6694 unsigned int *axis_count)
6695{
6696 static const float width_axis_values[] =
6697 {
6698 0.0f, /* DWRITE_FONT_STRETCH_UNDEFINED */
6699 50.0f, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
6700 62.5f, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
6701 75.0f, /* DWRITE_FONT_STRETCH_CONDENSED */
6702 87.5f, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
6703 100.0f, /* DWRITE_FONT_STRETCH_NORMAL */
6704 112.5f, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
6705 125.0f, /* DWRITE_FONT_STRETCH_EXPANDED */
6706 150.0f, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
6707 200.0f, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
6708 };
6709 BOOL has_wght = FALSE, has_wdth = FALSE, has_slnt = FALSE, has_ital = FALSE;
6710 const struct var_axis_record *records;
6711 const struct fvar_header *header;
6712 unsigned int i, count, tag, size;
6713 struct dwrite_font_props props;
6714 struct dwrite_fonttable fvar;
6715 HRESULT hr = S_OK;
6716
6717 *axis = NULL;
6718 *axis_count = 0;
6719
6720 opentype_get_font_table(stream_desc, MS_FVAR_TAG, &fvar);
6721
6722 if (!(header = table_read_ensure(&fvar, 0, sizeof(*header)))) goto done;
6723 if (!(GET_BE_WORD(header->major_version) == 1 && GET_BE_WORD(header->minor_version) == 0))
6724 {
6725 WARN("Unexpected fvar version.\n");
6726 goto done;
6727 }
6728
6729 count = GET_BE_WORD(header->axis_count);
6730 size = GET_BE_WORD(header->axis_size);
6731
6732 if (!count || size != sizeof(*records)) goto done;
6733 if (!(records = table_read_ensure(&fvar, GET_BE_WORD(header->axes_array_offset), size * count))) goto done;
6734
6735 if (!(*axis = calloc(count + 4, sizeof(**axis))))
6736 {
6737 hr = E_OUTOFMEMORY;
6738 goto done;
6739 }
6740
6741 for (i = 0; i < count; ++i)
6742 {
6743 (*axis)[i].tag = tag = records[i].tag;
6744 (*axis)[i].default_value = GET_BE_FIXED(records[i].default_value);
6745 (*axis)[i].min_value = GET_BE_FIXED(records[i].min_value);
6746 (*axis)[i].max_value = GET_BE_FIXED(records[i].max_value);
6747 if (GET_BE_WORD(records[i].flags & 0x1))
6748 (*axis)[i].attributes |= DWRITE_FONT_AXIS_ATTRIBUTES_HIDDEN;
6749 /* FIXME: set DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE */
6750
6751 if (tag == DWRITE_FONT_AXIS_TAG_WEIGHT) has_wght = TRUE;
6752 if (tag == DWRITE_FONT_AXIS_TAG_WIDTH) has_wdth = TRUE;
6753 if (tag == DWRITE_FONT_AXIS_TAG_SLANT) has_slnt = TRUE;
6754 if (tag == DWRITE_FONT_AXIS_TAG_ITALIC) has_ital = TRUE;
6755 }
6756
6757 if (!has_wght || !has_wdth || !has_slnt || !has_ital)
6758 {
6759 opentype_get_font_properties(stream_desc, &props);
6762 props.style == DWRITE_FONT_STYLE_ITALIC ? 1.0f : 0.0f);
6764 width_axis_values[props.stretch]);
6765 if (!has_slnt) opentype_font_var_add_static_axis(axis, &count, DWRITE_FONT_AXIS_TAG_SLANT, props.slant_angle);
6766 }
6767
6768 *axis_count = count;
6769
6770done:
6771 if (fvar.context)
6772 IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, fvar.context);
6773
6774 return hr;
6775}
int WINAPI LCIDToLocaleName(_In_ LCID Locale, _Out_writes_opt_(cchName) LPWSTR lpName, _In_ int cchName, _In_ DWORD dwFlags)
_STLP_MOVE_TO_STD_NAMESPACE void _STLP_CALL advance(_InputIterator &__i, _Distance __n)
unsigned short UINT16
Definition: actypes.h:129
unsigned char UINT8
Definition: actypes.h:128
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
struct outqueuenode * head
Definition: adnsresfilter.c:66
#define skip(...)
Definition: atltest.h:64
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static const WCHAR nameW[]
Definition: main.c:49
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
Definition: _locale.h:75
range
Definition: d3dx9_private.h:58
@ DWRITE_GLYPH_IMAGE_FORMATS_COLR
Definition: dcommon.idl:47
@ DWRITE_GLYPH_IMAGE_FORMATS_NONE
Definition: dcommon.idl:44
@ DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8
Definition: dcommon.idl:52
@ DWRITE_GLYPH_IMAGE_FORMATS_JPEG
Definition: dcommon.idl:50
@ DWRITE_GLYPH_IMAGE_FORMATS_PNG
Definition: dcommon.idl:49
@ DWRITE_GLYPH_IMAGE_FORMATS_CFF
Definition: dcommon.idl:46
@ DWRITE_GLYPH_IMAGE_FORMATS_SVG
Definition: dcommon.idl:48
@ DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
Definition: dcommon.idl:45
@ DWRITE_GLYPH_IMAGE_FORMATS_TIFF
Definition: dcommon.idl:51
@ DWRITE_MEASURING_MODE_NATURAL
Definition: dcommon.idl:37
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
HRESULT hr
Definition: delayimp.cpp:582
#define LF_FACESIZE
Definition: dimm.idl:39
const unsigned short wine_mirror_map[1428]
Definition: mirror.c:7
static void get_name_record_locale(enum OPENTYPE_PLATFORM_ID platform, USHORT lang_id, WCHAR *locale, USHORT locale_len)
Definition: opentype.c:2314
static HRESULT opentype_get_font_strings_from_meta(const struct file_stream_desc *stream_desc, DWRITE_INFORMATIONAL_STRING_ID id, IDWriteLocalizedStrings **ret)
Definition: opentype.c:2518
BOOL(* p_match_func)(UINT16 glyph, UINT16 glyph_data, const struct match_data *match_data)
Definition: opentype.c:3700
static int __cdecl cmap_format4_compare_range(const void *a, const void *b)
Definition: opentype.c:1640
static void opentype_font_var_add_static_axis(struct dwrite_var_axis **axis, unsigned int *axis_count, unsigned int tag, float value)
Definition: opentype.c:6684
#define MS_HHEA_TAG
Definition: opentype.c:29
static void glyph_iterator_init(struct scriptshaping_context *context, unsigned int flags, unsigned int pos, unsigned int len, struct glyph_iterator *iter)
Definition: opentype.c:3726
#define MS_NAME_TAG
Definition: opentype.c:35
static BOOL opentype_layout_apply_gpos_pair_adjustment(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:3959
#define MS_WOFF_TAG
Definition: opentype.c:55
static UINT16 opentype_cmap_format0_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
Definition: opentype.c:1616
static BOOL opentype_layout_apply_rule_set(const struct match_context *mc, unsigned int offset)
Definition: opentype.c:5569
static BOOL opentype_layout_apply_context(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:5607
#define MS_OS2_TAG
Definition: opentype.c:31
static DWORD table_read_dword(const struct dwrite_fonttable *table, unsigned int offset)
Definition: opentype.c:1331
unsigned int opentype_layout_find_script(const struct scriptshaping_cache *cache, unsigned int kind, DWORD script, unsigned int *script_index)
Definition: opentype.c:3279
#define MS_GDEF_TAG
Definition: opentype.c:34
TT_NAME_MAC_ENCODING_ID
Definition: opentype.c:862
@ TT_NAME_MAC_ENCODING_HEBREW
Definition: opentype.c:868
@ TT_NAME_MAC_ENCODING_DEVANAGARI
Definition: opentype.c:872
@ TT_NAME_MAC_ENCODING_TAMIL
Definition: opentype.c:877
@ TT_NAME_MAC_ENCODING_GEEZ
Definition: opentype.c:891
@ TT_NAME_MAC_ENCODING_TELUGU
Definition: opentype.c:878
@ TT_NAME_MAC_ENCODING_BENGALI
Definition: opentype.c:876
@ TT_NAME_MAC_ENCODING_BURMESE
Definition: opentype.c:882
@ TT_NAME_MAC_ENCODING_SLAVIC
Definition: opentype.c:892
@ TT_NAME_MAC_ENCODING_GURMUKHI
Definition: opentype.c:873
@ TT_NAME_MAC_ENCODING_KOREAN
Definition: opentype.c:866
@ TT_NAME_MAC_ENCODING_JAPANESE
Definition: opentype.c:864
@ TT_NAME_MAC_ENCODING_MALAYALAM
Definition: opentype.c:880
@ TT_NAME_MAC_ENCODING_GUJARATI
Definition: opentype.c:874
@ TT_NAME_MAC_ENCODING_THAI
Definition: opentype.c:884
@ TT_NAME_MAC_ENCODING_GREEK
Definition: opentype.c:869
@ TT_NAME_MAC_ENCODING_VIETNAMESE
Definition: opentype.c:893
@ TT_NAME_MAC_ENCODING_TIBETAN
Definition: opentype.c:889
@ TT_NAME_MAC_ENCODING_SIMPL_CHINESE
Definition: opentype.c:888
@ TT_NAME_MAC_ENCODING_KANNADA
Definition: opentype.c:879
@ TT_NAME_MAC_ENCODING_TRAD_CHINESE
Definition: opentype.c:865
@ TT_NAME_MAC_ENCODING_ORIYA
Definition: opentype.c:875
@ TT_NAME_MAC_ENCODING_SINHALESE
Definition: opentype.c:881
@ TT_NAME_MAC_ENCODING_RSYMBOL
Definition: opentype.c:871
@ TT_NAME_MAC_ENCODING_ARMENIAN
Definition: opentype.c:887
@ TT_NAME_MAC_ENCODING_ROMAN
Definition: opentype.c:863
@ TT_NAME_MAC_ENCODING_ARABIC
Definition: opentype.c:867
@ TT_NAME_MAC_ENCODING_RUSSIAN
Definition: opentype.c:870
@ TT_NAME_MAC_ENCODING_GEORGIAN
Definition: opentype.c:886
@ TT_NAME_MAC_ENCODING_UNINTERPRETED
Definition: opentype.c:895
@ TT_NAME_MAC_ENCODING_KHMER
Definition: opentype.c:883
@ TT_NAME_MAC_ENCODING_LAOTIAN
Definition: opentype.c:885
@ TT_NAME_MAC_ENCODING_SINDHI
Definition: opentype.c:894
@ TT_NAME_MAC_ENCODING_MONGOLIAN
Definition: opentype.c:890
static BOOL opentype_match_class_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
Definition: opentype.c:3754
#define MS_CMAP_TAG
Definition: opentype.c:45
static UINT16 opentype_cmap_dummy_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
Definition: opentype.c:1781
#define MS_CPAL_TAG
Definition: opentype.c:39
static enum attach_type opentype_get_glyph_attach_type(const struct scriptshaping_context *context, unsigned int idx)
Definition: opentype.c:4156
static int __cdecl colr_compare_gid(const void *g, const void *r)
Definition: opentype.c:2986
#define MS_COLR_TAG
Definition: opentype.c:40
HRESULT opentype_try_get_font_table(const struct file_stream_desc *stream_desc, UINT32 tag, const void **table_data, void **table_context, UINT32 *table_size, BOOL *found)
Definition: opentype.c:1528
static WORD table_read_be_word(const struct dwrite_fonttable *table, unsigned int offset)
Definition: opentype.c:1314
static int __cdecl coverage_compare_format1(const void *left, const void *right)
Definition: opentype.c:3453
unsigned int opentype_layout_find_language(const struct scriptshaping_cache *cache, unsigned int kind, DWORD language, unsigned int script_index, unsigned int *language_index)
Definition: opentype.c:3309
static BOOL opentype_match_glyph_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
Definition: opentype.c:3749
static unsigned int opentype_set_glyph_props(struct scriptshaping_context *context, unsigned int idx)
Definition: opentype.c:3402
static BOOL opentype_layout_apply_chain_rule_set(const struct match_context *mc, unsigned int offset)
Definition: opentype.c:5511
static BOOL opentype_decode_namerecord(const struct dwrite_fonttable *table, unsigned int idx, IDWriteLocalizedStrings *strings)
Definition: opentype.c:2361
static unsigned int find_vdmx_group(const struct vdmx_header *hdr)
Definition: opentype.c:2820
static BOOL opentype_layout_apply_gsub_alt_substitution(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:5153
BOOL(* p_lookup_is_glyph_covered_func)(struct scriptshaping_context *context, UINT16 glyph, const struct lookup *lookup)
Definition: opentype.c:6389
static void opentype_layout_collect_lookups(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, struct shaping_features *features, const struct ot_gsubgpos_table *table, struct lookups *lookups)
Definition: opentype.c:4631
#define MS_CFF__TAG
Definition: opentype.c:37
static void opentype_propagate_attachment_offsets(struct scriptshaping_context *context, unsigned int i)
Definition: opentype.c:4887
gpos_lookup_type
Definition: opentype.c:529
@ GPOS_LOOKUP_MARK_TO_BASE_ATTACHMENT
Definition: opentype.c:533
@ GPOS_LOOKUP_MARK_TO_MARK_ATTACHMENT
Definition: opentype.c:535
@ GPOS_LOOKUP_CONTEXTUAL_CHAINING_POSITION
Definition: opentype.c:537
@ GPOS_LOOKUP_EXTENSION_POSITION
Definition: opentype.c:538
@ GPOS_LOOKUP_CONTEXTUAL_POSITION
Definition: opentype.c:536
@ GPOS_LOOKUP_CURSIVE_ATTACHMENT
Definition: opentype.c:532
@ GPOS_LOOKUP_SINGLE_ADJUSTMENT
Definition: opentype.c:530
@ GPOS_LOOKUP_MARK_TO_LIGATURE_ATTACHMENT
Definition: opentype.c:534
@ GPOS_LOOKUP_PAIR_ADJUSTMENT
Definition: opentype.c:531
BOOL opentype_layout_check_feature(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, struct shaping_feature *feature, unsigned int glyph_count, const UINT16 *glyphs, UINT8 *feature_applies)
Definition: opentype.c:6391
static unsigned int opentype_cmap_format0_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, DWRITE_UNICODE_RANGE *ranges)
Definition: opentype.c:1622
#define MS_TIFF_TAG
Definition: opentype.c:53
HRESULT opentype_get_font_var_axis(const struct file_stream_desc *stream_desc, struct dwrite_var_axis **axis, unsigned int *axis_count)
Definition: opentype.c:6693
static unsigned int opentype_cmap_format12_13_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, DWRITE_UNICODE_RANGE *ranges)
Definition: opentype.c:1752
static BOOL opentype_layout_contextual_lookup_is_glyph_covered(struct scriptshaping_context *context, UINT16 glyph, unsigned int subtable_offset, unsigned int coverage, unsigned int format)
Definition: opentype.c:6205
static UINT16 opentype_cmap_format6_10_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
Definition: opentype.c:1706
HRESULT opentype_get_font_info_strings(const struct file_stream_desc *stream_desc, DWRITE_INFORMATIONAL_STRING_ID id, IDWriteLocalizedStrings **strings)
Definition: opentype.c:2608
#define MS_KERN_TAG
Definition: opentype.c:47
#define MS_WOF2_TAG
Definition: opentype.c:56
gpos_value_format
Definition: opentype.c:554
@ GPOS_VALUE_Y_PLACEMENT
Definition: opentype.c:556
@ GPOS_VALUE_X_ADVANCE_DEVICE
Definition: opentype.c:561
@ GPOS_VALUE_X_ADVANCE
Definition: opentype.c:557
@ GPOS_VALUE_Y_PLACEMENT_DEVICE
Definition: opentype.c:560
@ GPOS_VALUE_X_PLACEMENT_DEVICE
Definition: opentype.c:559
@ GPOS_VALUE_X_PLACEMENT
Definition: opentype.c:555
@ GPOS_VALUE_Y_ADVANCE_DEVICE
Definition: opentype.c:562
@ GPOS_VALUE_Y_ADVANCE
Definition: opentype.c:558
static void opentype_set_subst_glyph_props(struct scriptshaping_context *context, unsigned int idx)
Definition: opentype.c:3439
#define MS_FVAR_TAG
Definition: opentype.c:48
static BOOL opentype_layout_apply_gpos_mark_to_lig_attachment(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:4386
void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, struct shaping_features *features)
Definition: opentype.c:4932
static DWORD table_read_be_dword(const struct dwrite_fonttable *table, unsigned int offset)
Definition: opentype.c:1320
static HRESULT opentype_otf_analyzer(IDWriteFontFileStream *stream, UINT32 *font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type)
Definition: opentype.c:1393
TT_NAME_WINDOWS_ENCODING_ID
Definition: opentype.c:847
@ TT_NAME_WINDOWS_ENCODING_RESERVED3
Definition: opentype.c:857
@ TT_NAME_WINDOWS_ENCODING_JOHAB
Definition: opentype.c:854
@ TT_NAME_WINDOWS_ENCODING_BIG5
Definition: opentype.c:852
@ TT_NAME_WINDOWS_ENCODING_SJIS
Definition: opentype.c:850
@ TT_NAME_WINDOWS_ENCODING_UNICODE_FULL
Definition: opentype.c:858
@ TT_NAME_WINDOWS_ENCODING_SYMBOL
Definition: opentype.c:848
@ TT_NAME_WINDOWS_ENCODING_PRC
Definition: opentype.c:851
@ TT_NAME_WINDOWS_ENCODING_WANSUNG
Definition: opentype.c:853
@ TT_NAME_WINDOWS_ENCODING_UNICODE_BMP
Definition: opentype.c:849
@ TT_NAME_WINDOWS_ENCODING_RESERVED1
Definition: opentype.c:855
@ TT_NAME_WINDOWS_ENCODING_RESERVED2
Definition: opentype.c:856
void opentype_layout_unsafe_to_break(struct scriptshaping_context *context, unsigned int start, unsigned int end)
Definition: opentype.c:5233
#define MS_SVG__TAG
Definition: opentype.c:41
attach_type
Definition: opentype.c:507
@ GLYPH_ATTACH_MARK
Definition: opentype.c:509
@ GLYPH_ATTACH_NONE
Definition: opentype.c:508
@ GLYPH_ATTACH_CURSIVE
Definition: opentype.c:510
static void opentype_layout_gpos_get_anchor(const struct scriptshaping_context *context, unsigned int anchor_offset, unsigned int glyph_index, float *x, float *y)
Definition: opentype.c:4094
static HRESULT opentype_ttc_analyzer(IDWriteFontFileStream *stream, UINT32 *font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type)
Definition: opentype.c:1348
static BOOL opentype_is_gsub_lookup_reversed(const struct scriptshaping_context *context, const struct lookup *lookup)
Definition: opentype.c:6101
static unsigned int opentype_is_diacritic(unsigned int codepoint)
Definition: opentype.c:6007
static UINT get_name_record_codepage(enum OPENTYPE_PLATFORM_ID platform, USHORT encoding)
Definition: opentype.c:2235
HRESULT opentype_get_cpal_entries(const struct dwrite_fonttable *cpal, unsigned int palette, unsigned int first_entry_index, unsigned int entry_count, DWRITE_COLOR_F *entries)
Definition: opentype.c:2937
static BOOL opentype_layout_apply_gsub_lookup(struct scriptshaping_context *context, const struct lookup *lookup)
Definition: opentype.c:5891
static float opentype_scale_gpos_be_value(WORD value, float emsize, UINT16 upem)
Definition: opentype.c:3534
static BOOL opentype_layout_apply_gsub_lig_substitution(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:5333
static unsigned int shaping_features_get_mask(const struct shaping_features *features, unsigned int tag, unsigned int *shift)
Definition: opentype.c:4809
static const char name_mac_langid_to_locale[][10]
Definition: opentype.c:1021
static const UINT16 * table_read_array_be_word(const struct dwrite_fonttable *table, unsigned int offset, unsigned int index, UINT16 *data)
Definition: opentype.c:4374
#define MS_SBIX_TAG
Definition: opentype.c:42
glyph_prop_flags
Definition: opentype.c:514
@ GLYPH_PROP_HIDDEN
Definition: opentype.c:522
@ GLYPH_PROP_ZWJ
Definition: opentype.c:520
@ GLYPH_PROP_ZWNJ
Definition: opentype.c:519
@ GLYPH_PROP_ATTACH_TYPE_MASK
Definition: opentype.c:525
@ GLYPH_PROP_IGNORABLE
Definition: opentype.c:521
@ GLYPH_PROP_MARK_ATTACH_CLASS_MASK
Definition: opentype.c:524
@ GLYPH_PROP_LIGATURE
Definition: opentype.c:516
@ GLYPH_PROP_MARK
Definition: opentype.c:517
@ GLYPH_PROP_BASE
Definition: opentype.c:515
static void opentype_reverse_cursive_offset(struct scriptshaping_context *context, unsigned int i, unsigned int new_parent)
Definition: opentype.c:4161
static BOOL opentype_layout_apply_context_match(unsigned int input_count, const UINT16 *input, unsigned int lookup_count, const UINT16 *lookup_records, const struct match_context *mc)
Definition: opentype.c:5558
static void opentype_layout_delete_glyph(struct scriptshaping_context *context, unsigned int idx)
Definition: opentype.c:5256
OPENTYPE_STRING_ID
Definition: opentype.c:1176
@ OPENTYPE_STRING_UNIQUE_IDENTIFIER
Definition: opentype.c:1180
@ OPENTYPE_STRING_DESCRIPTION
Definition: opentype.c:1187
@ OPENTYPE_STRING_FAMILY_NAME
Definition: opentype.c:1178
@ OPENTYPE_STRING_DESIGNER_URL
Definition: opentype.c:1189
@ OPENTYPE_STRING_VENDOR_URL
Definition: opentype.c:1188
@ OPENTYPE_STRING_WWS_FAMILY_NAME
Definition: opentype.c:1198
@ OPENTYPE_STRING_POSTSCRIPT_FONTNAME
Definition: opentype.c:1183
@ OPENTYPE_STRING_SAMPLE_TEXT
Definition: opentype.c:1196
@ OPENTYPE_STRING_COMPATIBLE_FULLNAME
Definition: opentype.c:1195
@ OPENTYPE_STRING_COPYRIGHT_NOTICE
Definition: opentype.c:1177
@ OPENTYPE_STRING_VERSION_STRING
Definition: opentype.c:1182
@ OPENTYPE_STRING_WWS_SUBFAMILY_NAME
Definition: opentype.c:1199
@ OPENTYPE_STRING_LICENSE_DESCRIPTION
Definition: opentype.c:1190
@ OPENTYPE_STRING_MANUFACTURER
Definition: opentype.c:1185
@ OPENTYPE_STRING_TYPOGRAPHIC_SUBFAMILY_NAME
Definition: opentype.c:1194
@ OPENTYPE_STRING_RESERVED_ID15
Definition: opentype.c:1192
@ OPENTYPE_STRING_DESIGNER
Definition: opentype.c:1186
@ OPENTYPE_STRING_LICENSE_INFO_URL
Definition: opentype.c:1191
@ OPENTYPE_STRING_SUBFAMILY_NAME
Definition: opentype.c:1179
@ OPENTYPE_STRING_TYPOGRAPHIC_FAMILY_NAME
Definition: opentype.c:1193
@ OPENTYPE_STRING_TRADEMARK
Definition: opentype.c:1184
@ OPENTYPE_STRING_FULL_FONTNAME
Definition: opentype.c:1181
@ OPENTYPE_STRING_POSTSCRIPT_CID_NAME
Definition: opentype.c:1197
static BOOL opentype_layout_apply_chain_context(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:5708
static int __cdecl gpos_pair_adjustment_compare_format1(const void *g, const void *r)
Definition: opentype.c:3952
static UINT16 opentype_cmap_format4_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
Definition: opentype.c:1656
#define MS_PNG__TAG
Definition: opentype.c:51
#define MS_POST_TAG
Definition: opentype.c:32
void opentype_layout_apply_gsub_features(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, struct shaping_features *features)
Definition: opentype.c:6116
gsub_gpos_lookup_flags
Definition: opentype.c:494
@ LOOKUP_FLAG_USE_MARK_FILTERING_SET
Definition: opentype.c:502
@ LOOKUP_FLAG_IGNORE_MARKS
Definition: opentype.c:499
@ LOOKUP_FLAG_IGNORE_LIGATURES
Definition: opentype.c:498
@ LOOKUP_FLAG_RTL
Definition: opentype.c:495
@ LOOKUP_FLAG_MARK_ATTACHMENT_TYPE
Definition: opentype.c:503
@ LOOKUP_FLAG_IGNORE_MASK
Definition: opentype.c:500
@ LOOKUP_FLAG_IGNORE_BASE
Definition: opentype.c:497
HRESULT opentype_analyze_font(IDWriteFontFileStream *stream, BOOL *supported, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, UINT32 *face_count)
Definition: opentype.c:1492
static int __cdecl cmap_header_compare(const void *a, const void *b)
Definition: opentype.c:1803
static UINT16 opentype_cmap_format13_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
Definition: opentype.c:1769
static void opentype_layout_set_glyph_masks(struct scriptshaping_context *context, const struct shaping_features *features)
Definition: opentype.c:4838
static unsigned int unicode_get_mirrored_char(unsigned int codepoint)
Definition: opentype.c:5937
BOOL opentype_has_vertical_variants(struct dwrite_fontface *fontface)
Definition: opentype.c:6436
gsub_lookup_type
Definition: opentype.c:542
@ GSUB_LOOKUP_CONTEXTUAL_SUBST
Definition: opentype.c:547
@ GSUB_LOOKUP_MULTIPLE_SUBST
Definition: opentype.c:544
@ GSUB_LOOKUP_SINGLE_SUBST
Definition: opentype.c:543
@ GSUB_LOOKUP_REVERSE_CHAINING_CONTEXTUAL_SUBST
Definition: opentype.c:550
@ GSUB_LOOKUP_LIGATURE_SUBST
Definition: opentype.c:546
@ GSUB_LOOKUP_ALTERNATE_SUBST
Definition: opentype.c:545
@ GSUB_LOOKUP_EXTENSION_SUBST
Definition: opentype.c:549
@ GSUB_LOOKUP_CHAINING_CONTEXTUAL_SUBST
Definition: opentype.c:548
static BOOL glyph_iterator_next(struct glyph_iterator *iter)
Definition: opentype.c:3844
tt_head_macstyle
Definition: opentype.c:158
@ TT_HEAD_MACSTYLE_EXTENDED
Definition: opentype.c:165
@ TT_HEAD_MACSTYLE_UNDERLINE
Definition: opentype.c:161
@ TT_HEAD_MACSTYLE_ITALIC
Definition: opentype.c:160
@ TT_HEAD_MACSTYLE_OUTLINE
Definition: opentype.c:162
@ TT_HEAD_MACSTYLE_BOLD
Definition: opentype.c:159
@ TT_HEAD_MACSTYLE_SHADOW
Definition: opentype.c:163
@ TT_HEAD_MACSTYLE_CONDENSED
Definition: opentype.c:164
HRESULT opentype_get_colr_glyph(const struct dwrite_fonttable *colr, UINT16 glyph, struct dwrite_colorglyph *ret)
Definition: opentype.c:3000
static void opentype_get_nominal_glyphs(struct scriptshaping_context *context, const struct shaping_features *features)
Definition: opentype.c:6017
static BOOL glyph_iterator_prev(struct glyph_iterator *iter)
Definition: opentype.c:3872
#define MS_OTTO_TAG
Definition: opentype.c:30
static BOOL opentype_layout_apply_ligature(struct scriptshaping_context *context, unsigned int offset, const struct lookup *lookup)
Definition: opentype.c:5274
void opentype_get_font_typo_metrics(struct file_stream_desc *stream_desc, unsigned int *ascent, unsigned int *descent)
Definition: opentype.c:1954
static BOOL opentype_layout_apply_mark_array(struct scriptshaping_context *context, unsigned int subtable_offset, unsigned int mark_array, unsigned int mark_index, unsigned int glyph_index, unsigned int anchors_matrix, unsigned int class_count, unsigned int glyph_pos)
Definition: opentype.c:4285
ot_gdef_class
Definition: opentype.c:435
@ GDEF_CLASS_UNCLASSIFIED
Definition: opentype.c:436
@ GDEF_CLASS_MAX
Definition: opentype.c:441
@ GDEF_CLASS_BASE
Definition: opentype.c:437
@ GDEF_CLASS_LIGATURE
Definition: opentype.c:438
@ GDEF_CLASS_MARK
Definition: opentype.c:439
@ GDEF_CLASS_COMPONENT
Definition: opentype.c:440
static unsigned int opentype_cmap_dummy_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, DWRITE_UNICODE_RANGE *ranges)
Definition: opentype.c:1786
static BOOL opentype_layout_gsub_ensure_buffer(struct scriptshaping_context *context, unsigned int count)
Definition: opentype.c:5033
static int __cdecl gdef_class_compare_format2(const void *g, const void *r)
Definition: opentype.c:3344
static unsigned int opentype_layout_is_pos_context(const struct scriptshaping_context *context)
Definition: opentype.c:3642
void dwrite_cmap_init(struct dwrite_cmap *cmap, IDWriteFontFile *file, unsigned int face_index, DWRITE_FONT_FACE_TYPE face_type)
Definition: opentype.c:1818
opentype_cmap_table_platform
Definition: opentype.c:122
@ OPENTYPE_CMAP_TABLE_PLATFORM_WIN
Definition: opentype.c:123
static BOOL opentype_layout_gpos_lookup_is_glyph_covered(struct scriptshaping_context *context, UINT16 glyph, const struct lookup *lookup)
Definition: opentype.c:6323
static BOOL opentype_layout_apply_gsub_single_substitution(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:4990
#define MS_SLNG_TAG
Definition: opentype.c:60
#define GLYPH_CONTEXT_MAX_LENGTH
Definition: opentype.c:72
static unsigned int dwrite_popcount(unsigned int x)
Definition: opentype.c:3523
UINT16 opentype_cmap_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
Definition: opentype.c:1792
HRESULT opentype_get_font_facename(struct file_stream_desc *stream_desc, WCHAR *lfname, IDWriteLocalizedStrings **names)
Definition: opentype.c:2690
static unsigned int opentype_layout_get_glyph_class(const struct dwrite_fonttable *table, unsigned int offset, UINT16 glyph)
Definition: opentype.c:3357
#define MS_JPG__TAG
Definition: opentype.c:52
static HRESULT opentype_get_font_table(const struct file_stream_desc *stream_desc, UINT32 tag, struct dwrite_fonttable *table)
Definition: opentype.c:1606
UINT32 opentype_get_glyph_image_formats(IDWriteFontFace5 *fontface)
Definition: opentype.c:3191
static BOOL opentype_layout_init_lookup(const struct ot_gsubgpos_table *table, unsigned short lookup_index, const struct shaping_feature *feature, struct lookup *lookup)
Definition: opentype.c:4549
static enum iterator_match glyph_iterator_may_match(const struct glyph_iterator *iter)
Definition: opentype.c:3831
static const UINT16 dwriteid_to_opentypeid[DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME+1]
Definition: opentype.c:1202
void opentype_colr_next_glyph(const struct dwrite_fonttable *colr, struct dwrite_colorglyph *glyph)
Definition: opentype.c:3041
unsigned int shape_get_feature_1_mask(const struct shaping_features *features, unsigned int tag)
Definition: opentype.c:4822
OPENTYPE_CMAP_TABLE_FORMAT
Definition: opentype.c:116
@ OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING
Definition: opentype.c:117
@ OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE
Definition: opentype.c:118
unsigned int opentype_get_gasp_flags(const struct dwrite_fonttable *gasp, float emsize)
Definition: opentype.c:2895
static void opentype_layout_add_lookups(const struct ot_feature_list *feature_list, UINT16 total_lookup_count, const struct ot_gsubgpos_table *table, struct shaping_feature *feature, struct lookups *lookups)
Definition: opentype.c:4595
HRESULT opentype_get_font_familyname(const struct file_stream_desc *stream_desc, DWRITE_FONT_FAMILY_MODEL family_model, IDWriteLocalizedStrings **names)
Definition: opentype.c:2629
static int __cdecl coverage_compare_format2(const void *g, const void *r)
Definition: opentype.c:3466
static BOOL opentype_layout_context_match_input(const struct match_context *mc, unsigned int count, const UINT16 *input, unsigned int *end_offset, unsigned int *match_positions)
Definition: opentype.c:5200
BOOL is_face_type_supported(DWRITE_FONT_FACE_TYPE type)
Definition: opentype.c:1337
static int __cdecl kern_format0_compare(const void *a, const void *b)
Definition: opentype.c:6612
TT_NAME_MAC_LANGUAGE_ID
Definition: opentype.c:899
@ TT_NAME_MAC_LANGID_RUNDI
Definition: opentype.c:991
@ TT_NAME_MAC_LANGID_KHMER
Definition: opentype.c:978
@ TT_NAME_MAC_LANGID_TURKISH
Definition: opentype.c:917
@ TT_NAME_MAC_LANGID_MALAGASY
Definition: opentype.c:993
@ TT_NAME_MAC_LANGID_ARABIC
Definition: opentype.c:912
@ TT_NAME_MAC_LANGID_TELUGU
Definition: opentype.c:975
@ TT_NAME_MAC_LANGID_INUKTITUT
Definition: opentype.c:1010
@ TT_NAME_MAC_LANGID_TATAR
Definition: opentype.c:1002
@ TT_NAME_MAC_LANGID_SOMALI
Definition: opentype.c:988
@ TT_NAME_MAC_LANGID_SIMPL_CHINESE
Definition: opentype.c:933
@ TT_NAME_MAC_LANGID_ESPERANTO
Definition: opentype.c:994
@ TT_NAME_MAC_LANGID_JAVANESE
Definition: opentype.c:1005
@ TT_NAME_MAC_LANGID_MANX_GAELIC
Definition: opentype.c:1012
@ TT_NAME_MAC_LANGID_AZERB_ARABIC
Definition: opentype.c:950
@ TT_NAME_MAC_LANGID_GUARANI
Definition: opentype.c:1000
@ TT_NAME_MAC_LANGID_GERMAN
Definition: opentype.c:902
@ TT_NAME_MAC_LANGID_YIDDISH
Definition: opentype.c:941
@ TT_NAME_MAC_LANGID_PORTUGUESE
Definition: opentype.c:908
@ TT_NAME_MAC_LANGID_UIGHUR
Definition: opentype.c:1003
@ TT_NAME_MAC_LANGID_JAPANESE
Definition: opentype.c:911
@ TT_NAME_MAC_LANGID_NYANJA
Definition: opentype.c:992
@ TT_NAME_MAC_LANGID_ASSAMESE
Definition: opentype.c:968
@ TT_NAME_MAC_LANGID_DUTCH
Definition: opentype.c:904
@ TT_NAME_MAC_LANGID_SLOVAK
Definition: opentype.c:939
@ TT_NAME_MAC_LANGID_NEPALI
Definition: opentype.c:964
@ TT_NAME_MAC_LANGID_FRENCH
Definition: opentype.c:901
@ TT_NAME_MAC_LANGID_INDONESIAN
Definition: opentype.c:981
@ TT_NAME_MAC_LANGID_SWEDISH
Definition: opentype.c:905
@ TT_NAME_MAC_LANGID_MALAYALAM
Definition: opentype.c:972
@ TT_NAME_MAC_LANGID_BENGALI
Definition: opentype.c:967
@ TT_NAME_MAC_LANGID_AFRIKAANS
Definition: opentype.c:1008
@ TT_NAME_MAC_LANGID_FINNISH
Definition: opentype.c:913
@ TT_NAME_MAC_LANGID_TURKMEN
Definition: opentype.c:956
@ TT_NAME_MAC_LANGID_GREENLANDIC
Definition: opentype.c:1016
@ TT_NAME_MAC_LANGID_SINHALESE
Definition: opentype.c:976
@ TT_NAME_MAC_LANGID_MACEDONIAN
Definition: opentype.c:943
@ TT_NAME_MAC_LANGID_NORWEGIAN
Definition: opentype.c:909
@ TT_NAME_MAC_LANGID_GEORGIAN
Definition: opentype.c:952
@ TT_NAME_MAC_LANGID_TIGRINYA
Definition: opentype.c:986
@ TT_NAME_MAC_LANGID_DZONGKHA
Definition: opentype.c:1004
@ TT_NAME_MAC_LANGID_LATIN
Definition: opentype.c:998
@ TT_NAME_MAC_LANGID_ALBANIAN
Definition: opentype.c:936
@ TT_NAME_MAC_LANGID_LITHUANIAN
Definition: opentype.c:924
@ TT_NAME_MAC_LANGID_CATALAN
Definition: opentype.c:997
@ TT_NAME_MAC_LANGID_DANISH
Definition: opentype.c:907
@ TT_NAME_MAC_LANGID_LATVIAN
Definition: opentype.c:928
@ TT_NAME_MAC_LANGID_LAO
Definition: opentype.c:979
@ TT_NAME_MAC_LANGID_BRETON
Definition: opentype.c:1009
@ TT_NAME_MAC_LANGID_SCOTTISH_GAELIC
Definition: opentype.c:1011
@ TT_NAME_MAC_LANGID_FAROESE
Definition: opentype.c:930
@ TT_NAME_MAC_LANGID_HUNGARIAN
Definition: opentype.c:926
@ TT_NAME_MAC_LANGID_ROMANIAN
Definition: opentype.c:937
@ TT_NAME_MAC_LANGID_MARATHI
Definition: opentype.c:966
@ TT_NAME_MAC_LANGID_TAMIL
Definition: opentype.c:974
@ TT_NAME_MAC_LANGID_SINDHI
Definition: opentype.c:962
@ TT_NAME_MAC_LANGID_TONGAN
Definition: opentype.c:1014
@ TT_NAME_MAC_LANGID_TAGALOG
Definition: opentype.c:982
@ TT_NAME_MAC_LANGID_PASHTO
Definition: opentype.c:959
@ TT_NAME_MAC_LANGID_MALTESE
Definition: opentype.c:916
@ TT_NAME_MAC_LANGID_MALAY_ROMAN
Definition: opentype.c:983
@ TT_NAME_MAC_LANGID_HEBREW
Definition: opentype.c:910
@ TT_NAME_MAC_LANGID_GREEK
Definition: opentype.c:914
@ TT_NAME_MAC_LANGID_SWAHILI
Definition: opentype.c:989
@ TT_NAME_MAC_LANGID_FARSI
Definition: opentype.c:931
@ TT_NAME_MAC_LANGID_CZECH
Definition: opentype.c:938
@ TT_NAME_MAC_LANGID_QUECHUA
Definition: opentype.c:999
@ TT_NAME_MAC_LANGID_ORIYA
Definition: opentype.c:971
@ TT_NAME_MAC_LANGID_GAELIC
Definition: opentype.c:935
@ TT_NAME_MAC_LANGID_SLOVENIAN
Definition: opentype.c:940
@ TT_NAME_MAC_LANGID_TAJIKI
Definition: opentype.c:955
@ TT_NAME_MAC_LANGID_URDU
Definition: opentype.c:920
@ TT_NAME_MAC_LANGID_BYELORUSSIAN
Definition: opentype.c:946
@ TT_NAME_MAC_LANGID_SERBIAN
Definition: opentype.c:942
@ TT_NAME_MAC_LANGID_SANSKRIT
Definition: opentype.c:965
@ TT_NAME_MAC_LANGID_FLEMISH
Definition: opentype.c:934
@ TT_NAME_MAC_LANGID_MONGOLIAN_CYR
Definition: opentype.c:958
@ TT_NAME_MAC_LANGID_BASQUE
Definition: opentype.c:996
@ TT_NAME_MAC_LANGID_UKRAINIAN
Definition: opentype.c:945
@ TT_NAME_MAC_LANGID_KURDISH
Definition: opentype.c:960
@ TT_NAME_MAC_LANGID_KAZAKH
Definition: opentype.c:948
@ TT_NAME_MAC_LANGID_THAI
Definition: opentype.c:922
@ TT_NAME_MAC_LANGID_AZERB_CYR
Definition: opentype.c:949
@ TT_NAME_MAC_LANGID_GALLA
Definition: opentype.c:987
@ TT_NAME_MAC_LANGID_BULGARIAN
Definition: opentype.c:944
@ TT_NAME_MAC_LANGID_KANNADA
Definition: opentype.c:973
@ TT_NAME_MAC_LANGID_BURMESE
Definition: opentype.c:977
@ TT_NAME_MAC_LANGID_KASHMIRI
Definition: opentype.c:961
@ TT_NAME_MAC_LANGID_HINDI
Definition: opentype.c:921
@ TT_NAME_MAC_LANGID_ENGLISH
Definition: opentype.c:900
@ TT_NAME_MAC_LANGID_KOREAN
Definition: opentype.c:923
@ TT_NAME_MAC_LANGID_RUSSIAN
Definition: opentype.c:932
@ TT_NAME_MAC_LANGID_MALAY_ARABIC
Definition: opentype.c:984
@ TT_NAME_MAC_LANGID_KINYARWANDA
Definition: opentype.c:990
@ TT_NAME_MAC_LANGID_GALICIAN
Definition: opentype.c:1007
@ TT_NAME_MAC_LANGID_AMHARIC
Definition: opentype.c:985
@ TT_NAME_MAC_LANGID_MONGOLIAN
Definition: opentype.c:957
@ TT_NAME_MAC_LANGID_AZER_ROMAN
Definition: opentype.c:1017
@ TT_NAME_MAC_LANGID_TIBETAN
Definition: opentype.c:963
@ TT_NAME_MAC_LANGID_KIRGHIZ
Definition: opentype.c:954
@ TT_NAME_MAC_LANGID_POLISH
Definition: opentype.c:925
@ TT_NAME_MAC_LANGID_SPANISH
Definition: opentype.c:906
@ TT_NAME_MAC_LANGID_CROATIAN
Definition: opentype.c:918
@ TT_NAME_MAC_LANGID_SAMI
Definition: opentype.c:929
@ TT_NAME_MAC_LANGID_WELSH
Definition: opentype.c:995
@ TT_NAME_MAC_LANGID_AYMARA
Definition: opentype.c:1001
@ TT_NAME_MAC_LANGID_SUNDANESE
Definition: opentype.c:1006
@ TT_NAME_MAC_LANGID_ICELANDIC
Definition: opentype.c:915
@ TT_NAME_MAC_LANGID_ARMENIAN
Definition: opentype.c:951
@ TT_NAME_MAC_LANGID_PUNJABI
Definition: opentype.c:970
@ TT_NAME_MAC_LANGID_MOLDAVIAN
Definition: opentype.c:953
@ TT_NAME_MAC_LANGID_UZBEK
Definition: opentype.c:947
@ TT_NAME_MAC_LANGID_VIETNAMESE
Definition: opentype.c:980
@ TT_NAME_MAC_LANGID_IRISH_GAELIC
Definition: opentype.c:1013
@ TT_NAME_MAC_LANGID_ESTONIAN
Definition: opentype.c:927
@ TT_NAME_MAC_LANGID_GREEK_POLYTONIC
Definition: opentype.c:1015
@ TT_NAME_MAC_LANGID_TRAD_CHINESE
Definition: opentype.c:919
@ TT_NAME_MAC_LANGID_ITALIAN
Definition: opentype.c:903
@ TT_NAME_MAC_LANGID_GUJARATI
Definition: opentype.c:969
void opentype_get_typographic_features(struct ot_gsubgpos_table *table, unsigned int script_index, unsigned int language_index, struct tag_array *t)
Definition: opentype.c:2789
static WCHAR * meta_get_lng_name(WCHAR *str, WCHAR **ctx)
Definition: opentype.c:2503
static BOOL opentype_layout_apply_gpos_mark_to_mark_attachment(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:4438
static enum iterator_match glyph_iterator_may_skip(const struct glyph_iterator *iter)
Definition: opentype.c:3814
static int __cdecl lookups_sorting_compare(const void *a, const void *b)
Definition: opentype.c:4542
static BOOL opentype_layout_context_match_backtrack(const struct match_context *mc, unsigned int count, const UINT16 *backtrack, unsigned int *match_start)
Definition: opentype.c:5376
#define MS_META_TAG
Definition: opentype.c:46
static void opentype_layout_replace_glyph(struct scriptshaping_context *context, UINT16 glyph)
Definition: opentype.c:4980
static HRESULT opentype_ttf_analyzer(IDWriteFontFileStream *stream, UINT32 *font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type)
Definition: opentype.c:1371
static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:3900
static unsigned int opentype_is_default_ignorable(unsigned int codepoint)
Definition: opentype.c:5989
void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT_METRICS1 *metrics, DWRITE_CARET_METRICS *caret)
Definition: opentype.c:1973
static BOOL opentype_layout_mark_set_covers(const struct scriptshaping_cache *cache, unsigned int set_index, UINT16 glyph)
Definition: opentype.c:3768
static unsigned int opentype_cmap_format4_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, DWRITE_UNICODE_RANGE *ranges)
Definition: opentype.c:1690
#define MS_GLYF_TAG
Definition: opentype.c:36
static BOOL opentype_layout_apply_gsub_mult_substitution(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:5059
HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_cmap *cmap, unsigned int max_count, DWRITE_UNICODE_RANGE *ranges, unsigned int *count)
Definition: opentype.c:1943
static HRESULT opentype_get_font_strings_from_id(const struct dwrite_fonttable *table, enum OPENTYPE_STRING_ID id, IDWriteLocalizedStrings **strings)
Definition: opentype.c:2420
void opentype_layout_scriptshaping_cache_init(struct scriptshaping_cache *cache)
Definition: opentype.c:3238
#define MS_HEAD_TAG
Definition: opentype.c:28
static BOOL opentype_layout_apply_gpos_lookup(struct scriptshaping_context *context, const struct lookup *lookup)
Definition: opentype.c:4486
#define MS_MAXP_TAG
Definition: opentype.c:43
static BOOL lookup_is_glyph_match(const struct scriptshaping_context *context, unsigned int idx, unsigned int match_props)
Definition: opentype.c:3794
static BOOL opentype_is_english_namerecord(const struct dwrite_fonttable *table, unsigned int idx)
Definition: opentype.c:2350
static BOOL opentype_layout_apply_gpos_mark_to_base_attachment(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:4333
static BOOL opentype_has_font_table(IDWriteFontFace5 *fontface, UINT32 tag)
Definition: opentype.c:3064
HRESULT opentype_get_kerning_pairs(struct dwrite_fontface *fontface, unsigned int count, const UINT16 *glyphs, INT32 *values)
Definition: opentype.c:6624
static unsigned int opentype_get_sbix_formats(IDWriteFontFace5 *fontface)
Definition: opentype.c:3082
static void opentype_layout_apply_gpos_value(struct scriptshaping_context *context, unsigned int table_offset, WORD value_format, const WORD *values, unsigned int glyph)
Definition: opentype.c:3574
unsigned int opentype_get_cpal_paletteentrycount(const struct dwrite_fonttable *cpal)
Definition: opentype.c:2932
BOOL opentype_has_kerning_pairs(struct dwrite_fontface *fontface)
Definition: opentype.c:6555
#define GET_BE_WORD(x)
Definition: opentype.c:67
static BOOL opentype_layout_apply_gsub_reverse_chain_context_substitution(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:5826
#define MS_TTCF_TAG
Definition: opentype.c:33
static BOOL opentype_layout_chain_contextual_lookup_is_glyph_covered(struct scriptshaping_context *context, UINT16 glyph, unsigned int subtable_offset, unsigned int coverage, unsigned int format)
Definition: opentype.c:6230
static void opentype_layout_apply_gsub_context_lookup(struct scriptshaping_context *context, unsigned int lookup_index)
Definition: opentype.c:6109
#define MS_DLNG_TAG
Definition: opentype.c:59
static int __cdecl feature_search_compare(const void *a, const void *b)
Definition: opentype.c:4801
opentype_cmap_table_encoding
Definition: opentype.c:127
@ OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_BMP
Definition: opentype.c:129
@ OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL
Definition: opentype.c:128
@ OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_FULL
Definition: opentype.c:130
#define GET_BE_DWORD(x)
Definition: opentype.c:68
static float table_read_be_fixed(const struct dwrite_fonttable *table, unsigned int offset)
Definition: opentype.c:1326
unsigned int opentype_get_cpal_palettecount(const struct dwrite_fonttable *cpal)
Definition: opentype.c:2927
void dwrite_cmap_release(struct dwrite_cmap *cmap)
Definition: opentype.c:1932
#define MS_CBLC_TAG
Definition: opentype.c:44
static unsigned int opentype_is_zero_width(unsigned int codepoint)
Definition: opentype.c:5955
#define GLYPH_NOT_COVERED
Definition: opentype.c:668
#define GET_BE_FIXED(x)
Definition: opentype.c:69
static unsigned int opentype_cmap_format6_10_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, DWRITE_UNICODE_RANGE *ranges)
Definition: opentype.c:1713
OS2_FSSELECTION
Definition: opentype.c:328
@ OS2_FSSELECTION_STRIKEOUT
Definition: opentype.c:333
@ OS2_FSSELECTION_NEGATIVE
Definition: opentype.c:331
@ OS2_FSSELECTION_ITALIC
Definition: opentype.c:329
@ OS2_FSSELECTION_REGULAR
Definition: opentype.c:335
@ OS2_FSSELECTION_USE_TYPO_METRICS
Definition: opentype.c:336
@ OS2_FSSELECTION_OBLIQUE
Definition: opentype.c:338
@ OS2_FSSELECTION_WWS
Definition: opentype.c:337
@ OS2_FSSELECTION_UNDERSCORE
Definition: opentype.c:330
@ OS2_FSSELECTION_BOLD
Definition: opentype.c:334
@ OS2_FSSELECTION_OUTLINED
Definition: opentype.c:332
#define MS_CFF2_TAG
Definition: opentype.c:38
void opentype_get_font_properties(const struct file_stream_desc *stream_desc, struct dwrite_font_props *props)
Definition: opentype.c:2090
static unsigned int opentype_layout_is_subst_context(const struct scriptshaping_context *context)
Definition: opentype.c:3637
static HRESULT opentype_type1_analyzer(IDWriteFontFileStream *stream, UINT32 *font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type)
Definition: opentype.c:1415
static BOOL opentype_layout_apply_gpos_cursive_attachment(struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable_offset)
Definition: opentype.c:4186
static void opentype_layout_get_glyph_range_for_text(struct scriptshaping_context *context, unsigned int start_char, unsigned int end_char, unsigned int *start_glyph, unsigned int *end_glyph)
Definition: opentype.c:4828
static const void * table_read_ensure(const struct dwrite_fonttable *table, unsigned int offset, unsigned int size)
Definition: opentype.c:1306
static int __cdecl cmap_format12_13_compare_group(const void *a, const void *b)
Definition: opentype.c:1725
static void opentype_layout_apply_gpos_context_lookup(struct scriptshaping_context *context, unsigned int lookup_index)
Definition: opentype.c:4880
static BOOL opentype_match_coverage_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
Definition: opentype.c:3761
static BOOL opentype_layout_apply_chain_context_match(unsigned int backtrack_count, const UINT16 *backtrack, unsigned int input_count, const UINT16 *input, unsigned int lookahead_count, const UINT16 *lookahead, unsigned int lookup_count, const UINT16 *lookup_records, const struct match_context *mc)
Definition: opentype.c:5498
#define SHAPE_MAX_NESTING_LEVEL
Definition: opentype.c:73
static unsigned int opentype_layout_get_gsubgpos_subtable(const struct scriptshaping_context *context, const struct lookup *lookup, unsigned int subtable, unsigned int *lookup_type)
Definition: opentype.c:3647
static int opentype_layout_gpos_get_dev_value(const struct scriptshaping_context *context, unsigned int offset)
Definition: opentype.c:3539
OPENTYPE_PLATFORM_ID
Definition: opentype.c:566
@ OPENTYPE_PLATFORM_WIN
Definition: opentype.c:570
@ OPENTYPE_PLATFORM_ISO
Definition: opentype.c:569
@ OPENTYPE_PLATFORM_UNICODE
Definition: opentype.c:567
@ OPENTYPE_PLATFORM_CUSTOM
Definition: opentype.c:571
@ OPENTYPE_PLATFORM_MAC
Definition: opentype.c:568
static BOOL opentype_layout_gsub_lookup_is_glyph_covered(struct scriptshaping_context *context, UINT16 glyph, const struct lookup *lookup)
Definition: opentype.c:6259
HRESULT opentype_get_vertical_glyph_variants(struct dwrite_fontface *fontface, unsigned int glyph_count, const UINT16 *nominal_glyphs, UINT16 *glyphs)
Definition: opentype.c:6498
static BOOL opentype_layout_context_match_lookahead(const struct match_context *mc, unsigned int count, const UINT16 *lookahead, unsigned int offset, unsigned int *end_index)
Definition: opentype.c:5402
static BOOL opentype_layout_context_apply_lookup(struct scriptshaping_context *context, unsigned int count, unsigned int *match_positions, unsigned int lookup_count, const UINT16 *lookup_records, unsigned int match_length)
Definition: opentype.c:5428
static unsigned int opentype_layout_is_glyph_covered(const struct dwrite_fonttable *table, unsigned int coverage, UINT16 glyph)
Definition: opentype.c:3479
static void opentype_set_glyph_attach_type(struct scriptshaping_context *context, unsigned int idx, enum attach_type attach_type)
Definition: opentype.c:4149
static unsigned int opentype_get_cblc_formats(IDWriteFontFace5 *fontface)
Definition: opentype.c:3154
iterator_match
Definition: opentype.c:3686
@ ITER_NO
Definition: opentype.c:3688
@ ITER_YES
Definition: opentype.c:3689
@ ITER_MAYBE
Definition: opentype.c:3690
static const struct ot_langsys * opentype_get_langsys(const struct ot_gsubgpos_table *table, unsigned int script_index, unsigned int language_index, unsigned int *feature_count)
Definition: opentype.c:2755
BOOL opentype_get_vdmx_size(const struct dwrite_fonttable *vdmx, INT emsize, UINT16 *ascent, UINT16 *descent)
Definition: opentype.c:2846
DWRITE_CONTAINER_TYPE opentype_analyze_container_type(void const *data, UINT32 data_size)
Definition: opentype.c:3217
HRESULT(* dwrite_fontfile_analyzer)(IDWriteFontFileStream *stream, UINT32 *font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type)
Definition: opentype.c:1345
static UINT16 opentype_cmap_format12_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch)
Definition: opentype.c:1739
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
INT32 int32_t
Definition: types.h:71
UINT32 uint32_t
Definition: types.h:75
INT16 int16_t
Definition: types.h:70
WORD face[3]
Definition: mesh.c:4854
static const GUID * classes[]
Definition: loader.c:49
unsigned int idx
Definition: utils.c:40
#define wcschr
Definition: compat.h:17
#define CP_ACP
Definition: compat.h:109
#define MultiByteToWideChar
Definition: compat.h:110
#define lstrcpynW
Definition: compat.h:738
static const WCHAR version[]
Definition: asmname.c:66
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3098
INT WINAPI GetSystemDefaultLocaleName(LPWSTR localename, INT len)
Definition: locale.c:1246
const WCHAR * text
Definition: package.c:1826
unsigned char ch[4][2]
Definition: console.c:118
#define __cdecl
Definition: corecrt.h:121
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
_ACRTIMP void __cdecl qsort(void *, size_t, size_t, int(__cdecl *)(const void *, const void *))
unsigned short uint16_t
Definition: stdint.h:35
unsigned char uint8_t
Definition: stdint.h:33
signed char int8_t
Definition: stdint.h:32
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
r parent
Definition: btrfs.c:3010
struct nls_table * tables
Definition: nls_base.c:22
DWRITE_FONT_FILE_TYPE
Definition: dwrite.idl:47
@ DWRITE_FONT_FILE_TYPE_TRUETYPE
Definition: dwrite.idl:50
@ DWRITE_FONT_FILE_TYPE_TYPE1_PFM
Definition: dwrite.idl:52
@ DWRITE_FONT_FILE_TYPE_TYPE1_PFB
Definition: dwrite.idl:53
@ DWRITE_FONT_FILE_TYPE_OPENTYPE_COLLECTION
Definition: dwrite.idl:51
@ DWRITE_FONT_FILE_TYPE_UNKNOWN
Definition: dwrite.idl:48
@ DWRITE_FONT_FILE_TYPE_CFF
Definition: dwrite.idl:49
DWRITE_INFORMATIONAL_STRING_ID
Definition: dwrite.idl:116
@ DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME
Definition: dwrite.idl:136
@ DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG
Definition: dwrite.idl:137
@ DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
Definition: dwrite.idl:138
DWRITE_FONT_FACE_TYPE
Definition: dwrite.idl:60
@ DWRITE_FONT_FACE_TYPE_TYPE1
Definition: dwrite.idl:64
@ DWRITE_FONT_FACE_TYPE_CFF
Definition: dwrite.idl:61
@ DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION
Definition: dwrite.idl:63
@ DWRITE_FONT_FACE_TYPE_UNKNOWN
Definition: dwrite.idl:67
@ DWRITE_FONT_FACE_TYPE_TRUETYPE
Definition: dwrite.idl:62
@ DWRITE_FONT_FACE_TYPE_RAW_CFF
Definition: dwrite.idl:68
@ DWRITE_FONT_WEIGHT_NORMAL
Definition: dwrite.idl:79
@ DWRITE_FONT_WEIGHT_BOLD
Definition: dwrite.idl:84
@ DWRITE_FONT_WEIGHT_ULTRA_BLACK
Definition: dwrite.idl:90
@ DWRITE_FONT_STYLE_NORMAL
Definition: dwrite.idl:110
@ DWRITE_FONT_STYLE_ITALIC
Definition: dwrite.idl:112
@ DWRITE_FONT_STYLE_OBLIQUE
Definition: dwrite.idl:111
@ DWRITE_FONT_STRETCH_EXPANDED
Definition: dwrite.idl:103
@ DWRITE_FONT_STRETCH_NORMAL
Definition: dwrite.idl:100
@ DWRITE_FONT_STRETCH_UNDEFINED
Definition: dwrite.idl:95
@ DWRITE_FONT_STRETCH_ULTRA_EXPANDED
Definition: dwrite.idl:105
@ DWRITE_FONT_STRETCH_CONDENSED
Definition: dwrite.idl:98
@ DWRITE_PANOSE_FAMILY_SYMBOL
Definition: dwrite_1.idl:28
@ DWRITE_PANOSE_PROPORTION_MONOSPACED
Definition: dwrite_1.idl:83
enum DWRITE_CONTAINER_TYPE_WOFF
DWRITE_FONT_FAMILY_MODEL
Definition: dwrite_3.idl:169
@ DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC
Definition: dwrite_3.idl:170
@ DWRITE_FONT_AXIS_TAG_WEIGHT
Definition: dwrite_3.idl:126
@ DWRITE_FONT_AXIS_TAG_WIDTH
Definition: dwrite_3.idl:127
@ DWRITE_FONT_AXIS_TAG_ITALIC
Definition: dwrite_3.idl:130
@ DWRITE_FONT_AXIS_TAG_SLANT
Definition: dwrite_3.idl:128
@ DWRITE_FONT_AXIS_ATTRIBUTES_HIDDEN
Definition: dwrite_3.idl:165
enum DWRITE_CONTAINER_TYPE_WOFF2
unsigned int get_localizedstrings_count(IDWriteLocalizedStrings *strings)
Definition: main.c:563
@ FEATURE_NEEDS_FALLBACK
@ FEATURE_MANUAL_ZWNJ
@ FEATURE_GLOBAL_SEARCH
@ FEATURE_MANUAL_ZWJ
@ FEATURE_GLOBAL
@ FEATURE_HAS_FALLBACK
HRESULT get_filestream_from_file(IDWriteFontFile *, IDWriteFontFileStream **)
Definition: font.c:3563
HRESULT add_localizedstring(IDWriteLocalizedStrings *, const WCHAR *, const WCHAR *)
Definition: main.c:466
static LPWSTR heap_strdupnW(const WCHAR *str, UINT32 len)
void sort_localizedstrings(IDWriteLocalizedStrings *)
Definition: main.c:556
HRESULT create_localizedstrings(IDWriteLocalizedStrings **)
Definition: main.c:449
@ FONT_IS_COLORED
@ FONTFACE_KERNING_PAIRS
@ FONTFACE_VERTICAL_VARIANTS
@ FONTFACE_NO_VERTICAL_VARIANTS
@ FONT_IS_SYMBOL
@ FONT_IS_MONOSPACED
@ FONTFACE_NO_KERNING_PAIRS
#define MS_GPOS_TAG
struct scriptshaping_cache * fontface_get_shaping_cache(struct dwrite_fontface *fontface)
Definition: font.c:559
static unsigned short get_table_entry_16(const unsigned short *table, WCHAR ch)
static BOOL dwrite_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
#define MS_GSUB_TAG
@ SCRIPT_JUSTIFY_CHARACTER
const void * get_fontface_table(IDWriteFontFace5 *fontface, UINT32 tag, struct dwrite_fonttable *table)
Definition: font.c:666
#define GID
Definition: ext2fs.h:155
#define abs(i)
Definition: fconv.c:206
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
Character const *const size_t const max_count
Definition: fullpath.cpp:66
static const FxOffsetAndName offsets[]
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLsizei GLuint * groups
Definition: glext.h:11113
GLuint GLuint * names
Definition: glext.h:11545
GLsizei const GLchar *const * strings
Definition: glext.h:7622
GLsizeiptr size
Definition: glext.h:5919
GLenum GLenum GLuint components
Definition: glext.h:9620
GLintptr offset
Definition: glext.h:5920
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLdouble GLdouble right
Definition: glext.h:10859
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLint left
Definition: glext.h:7726
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLboolean GLuint group
Definition: glext.h:11120
GLboolean GLboolean g
Definition: glext.h:6204
GLenum GLuint GLint GLint layer
Definition: glext.h:7007
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLenum GLenum GLenum input
Definition: glext.h:9031
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
unsigned int UINT
Definition: sysinfo.c:13
#define BitScanReverse
Definition: interlocked.h:6
#define BitScanForward
Definition: interlocked.h:5
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
char hdr[14]
Definition: iptest.cpp:33
uint32_t entry
Definition: isohybrid.c:63
#define f
Definition: ke_i.h:83
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
#define debugstr_w
Definition: kernel32.h:32
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static PVOID ptr
Definition: dispmode.c:27
BITMAP bmp
Definition: alphablend.c:62
int face_count
Definition: d3drm.c:3529
static const WCHAR localeW[]
Definition: locale.c:49
INTERNETFEATURELIST feature
Definition: misc.c:1807
static HPALETTE palette
Definition: clipboard.c:1457
static HWND child
Definition: cursoricon.c:298
#define shift
Definition: input.c:3280
#define min(a, b)
Definition: monoChain.cc:55
static const struct @662 sizes[]
int k
Definition: mpi.c:3369
script
Definition: msipriv.h:396
platform
Definition: msipriv.h:364
Definition: mk_font.cpp:20
#define BOOL
Definition: nt_native.h:43
#define LOCALE_NAME_MAX_LENGTH
#define SORT_DEFAULT
#define MAKELCID(lgid, srtid)
short WCHAR
Definition: pedump.c:58
short SHORT
Definition: pedump.c:59
unsigned short USHORT
Definition: pedump.c:61
char CHAR
Definition: pedump.c:57
static unsigned __int64 next
Definition: rand_nt.c:6
#define calloc
Definition: rosglue.h:14
const WCHAR * str
wcscpy
static __inline const char * debugstr_fourcc(unsigned int cc)
Definition: debug.h:397
FD_TYPE file_type(FDSC **curr, char *fixed)
Definition: file.c:221
#define memset(x, y, z)
Definition: compat.h:39
LOCAL int table_size
Definition: write.c:65
#define TRACE(s)
Definition: solgame.cpp:4
DWRITE_FONT_FEATURE * features
Definition: dwrite.idl:544
Definition: undname.c:54
Definition: cache.c:41
struct sbit_line_metrics hori
Definition: opentype.c:305
uint32_t indexTablesSize
Definition: opentype.c:302
uint32_t numberofIndexSubTables
Definition: opentype.c:303
uint16_t endGlyphIndex
Definition: opentype.c:308
uint32_t indexSubTableArrayOffset
Definition: opentype.c:301
uint16_t startGlyphIndex
Definition: opentype.c:307
struct sbit_line_metrics vert
Definition: opentype.c:306
uint16_t major_version
Definition: opentype.c:278
uint32_t num_sizes
Definition: opentype.c:280
uint16_t minor_version
Definition: opentype.c:279
uint16_t platformID
Definition: opentype.c:103
uint16_t encodingID
Definition: opentype.c:104
const struct dwrite_cmap * cmap
Definition: opentype.c:1636
uint16_t num_tables
Definition: opentype.c:111
uint16_t version
Definition: opentype.c:110
struct cmap_encoding_record tables[1]
Definition: opentype.c:112
uint16_t first_layer_index
Definition: opentype.c:1258
uint16_t num_layer_records
Definition: opentype.c:1252
uint32_t offset_layer_records
Definition: opentype.c:1251
uint32_t offset_baseglyph_records
Definition: opentype.c:1250
uint16_t version
Definition: opentype.c:1248
uint16_t num_baseglyph_records
Definition: opentype.c:1249
uint16_t palette_index
Definition: opentype.c:1265
uint16_t glyph
Definition: opentype.c:1264
Definition: http.c:7252
uint16_t version
Definition: opentype.c:1229
uint16_t num_color_records
Definition: opentype.c:1232
uint16_t color_record_indices[1]
Definition: opentype.c:1234
uint16_t num_palettes
Definition: opentype.c:1231
uint16_t num_palette_entries
Definition: opentype.c:1230
uint32_t offset_first_color_record
Definition: opentype.c:1233
Definition: tftpd.h:126
struct dwrite_cmap::@304::@306 format6_10
union dwrite_cmap::@304 u
const void * data
struct dwrite_cmap::@304::@305 format4
IDWriteFontFileStream * stream
unsigned short symbol
struct dwrite_cmap::@304::@307 format12_13
void * table_context
p_cmap_get_glyph_func get_glyph
p_cmap_get_ranges_func get_ranges
struct dwrite_fonttable kern
IDWriteFontFileStream * stream
unsigned int flags
DWRITE_FONT_FACE_TYPE type
const BYTE * data
DWRITE_FONT_AXIS_TAG tag
DWRITE_FONT_FACE_TYPE face_type
IDWriteFontFileStream * stream
Definition: fci.c:123
uint16_t axis_count
Definition: opentype.c:1290
uint16_t major_version
Definition: opentype.c:1286
uint16_t minor_version
Definition: opentype.c:1287
uint16_t instance_count
Definition: opentype.c:1292
uint16_t axes_array_offset
Definition: opentype.c:1288
uint16_t reserved
Definition: opentype.c:1289
uint16_t instance_size
Definition: opentype.c:1293
uint16_t axis_size
Definition: opentype.c:1291
WORD num_ranges
Definition: opentype.c:324
struct gasp_range ranges[1]
Definition: opentype.c:325
WORD version
Definition: opentype.c:323
WORD max_ppem
Definition: opentype.c:317
WORD flags
Definition: opentype.c:318
uint16_t ligcaret_list
Definition: opentype.c:450
uint16_t markattach_classdef
Definition: opentype.c:451
uint16_t minor_version
Definition: opentype.c:447
uint16_t markglyphsetdef
Definition: opentype.c:452
uint16_t attach_list
Definition: opentype.c:449
uint16_t classdef
Definition: opentype.c:448
uint16_t major_version
Definition: opentype.c:446
const UINT16 * glyph_data
Definition: opentype.c:3720
unsigned int ignore_zwnj
Definition: opentype.c:3722
unsigned int flags
Definition: opentype.c:3715
unsigned int ignore_zwj
Definition: opentype.c:3723
unsigned int pos
Definition: opentype.c:3716
unsigned int len
Definition: opentype.c:3717
unsigned int mask
Definition: opentype.c:3718
p_match_func match_func
Definition: opentype.c:3719
const struct match_data * match_data
Definition: opentype.c:3721
struct scriptshaping_context * context
Definition: opentype.c:3714
uint16_t lookup_list
Definition: opentype.c:490
uint16_t feature_list
Definition: opentype.c:489
uint16_t script_list
Definition: opentype.c:488
uint16_t minor_version
Definition: opentype.c:487
uint16_t major_version
Definition: opentype.c:486
uint16_t version
Definition: opentype.c:833
uint16_t table_count
Definition: opentype.c:834
Definition: copy.c:22
union key::@406 u
unsigned int offset
Definition: opentype.c:3632
unsigned short subtable_count
Definition: opentype.c:3628
unsigned short type
Definition: opentype.c:3627
unsigned int flags
Definition: opentype.c:3631
unsigned int auto_zwj
Definition: opentype.c:3634
unsigned short index
Definition: opentype.c:3626
unsigned int auto_zwnj
Definition: opentype.c:3633
unsigned int mask
Definition: opentype.c:3630
size_t capacity
Definition: opentype.c:4538
size_t count
Definition: opentype.c:4539
struct lookup * lookups
Definition: opentype.c:4537
unsigned int input_offset
Definition: opentype.c:3706
struct scriptshaping_context * context
Definition: opentype.c:3704
unsigned int lookahead_offset
Definition: opentype.c:3707
unsigned int backtrack_offset
Definition: opentype.c:3705
const struct lookup * lookup
Definition: opentype.c:3709
p_match_func match_func
Definition: opentype.c:3708
unsigned int subtable_offset
Definition: opentype.c:3697
const struct match_context * mc
Definition: opentype.c:3696
Definition: match.c:28
Definition: opentype.c:271
DWORD version
Definition: opentype.c:272
WORD num_glyphs
Definition: opentype.c:273
uint32_t length
Definition: opentype.c:1272
uint32_t offset
Definition: opentype.c:1271
uint32_t tag
Definition: opentype.c:1270
struct meta_data_map maps[1]
Definition: opentype.c:1281
uint32_t version
Definition: opentype.c:1277
uint32_t flags
Definition: opentype.c:1278
uint32_t data_maps_count
Definition: opentype.c:1280
uint32_t reserved
Definition: opentype.c:1279
uint16_t format
Definition: opentype.c:353
uint16_t count
Definition: opentype.c:354
struct name_record records[1]
Definition: opentype.c:356
uint16_t stringOffset
Definition: opentype.c:355
uint16_t platformID
Definition: opentype.c:343
uint16_t offset
Definition: opentype.c:348
uint16_t languageID
Definition: opentype.c:345
uint16_t encodingID
Definition: opentype.c:344
uint16_t nameID
Definition: opentype.c:346
uint16_t length
Definition: opentype.c:347
Definition: name.c:39
uint16_t glyph_count
Definition: opentype.c:673
uint16_t glyphs[1]
Definition: opentype.c:674
uint16_t range_count
Definition: opentype.c:687
struct ot_coverage_range ranges[1]
Definition: opentype.c:688
uint16_t startcoverage_index
Definition: opentype.c:681
uint16_t end_glyph
Definition: opentype.c:680
uint16_t start_glyph
Definition: opentype.c:679
uint16_t feature_count
Definition: opentype.c:397
struct ot_feature_record features[1]
Definition: opentype.c:398
uint32_t tag
Definition: opentype.c:391
uint16_t offset
Definition: opentype.c:392
uint16_t lookuplist_index[1]
Definition: opentype.c:651
uint16_t feature_params
Definition: opentype.c:649
uint16_t lookup_count
Definition: opentype.c:650
uint16_t start_glyph
Definition: opentype.c:465
uint16_t end_glyph
Definition: opentype.c:466
uint16_t glyph_class
Definition: opentype.c:467
struct ot_gdef_class_range ranges[1]
Definition: opentype.c:474
uint32_t offsets[1]
Definition: opentype.c:481
uint16_t offsets[1]
Definition: opentype.c:798
uint16_t count
Definition: opentype.c:797
uint16_t anchors[1]
Definition: opentype.c:780
uint16_t start_size
Definition: opentype.c:693
uint16_t count
Definition: opentype.c:791
struct ot_gpos_mark_record records[1]
Definition: opentype.c:792
uint16_t mark_anchor
Definition: opentype.c:786
uint16_t mark_class
Definition: opentype.c:785
uint16_t pairsets[1]
Definition: opentype.c:735
uint16_t values[1]
Definition: opentype.c:748
uint16_t pairvalue_count
Definition: opentype.c:724
struct ot_gpos_pairvalue pairvalues[1]
Definition: opentype.c:725
uint16_t second_glyph
Definition: opentype.c:718
uint16_t comp_count
Definition: opentype.c:629
uint16_t components[1]
Definition: opentype.c:630
uint16_t lig_glyph
Definition: opentype.c:628
uint16_t count
Definition: opentype.c:622
uint16_t offsets[1]
Definition: opentype.c:623
uint16_t lig_sets[1]
Definition: opentype.c:617
uint16_t offsets[1]
Definition: opentype.c:644
uint16_t langsys
Definition: opentype.c:412
uint32_t tag
Definition: opentype.c:411
uint16_t lookup_order
Definition: opentype.c:403
uint16_t feature_index[1]
Definition: opentype.c:406
uint16_t feature_count
Definition: opentype.c:405
uint16_t required_feature_index
Definition: opentype.c:404
uint16_t lookup_count
Definition: opentype.c:656
uint16_t lookup_type
Definition: opentype.c:662
uint16_t subtable[1]
Definition: opentype.c:665
uint16_t flags
Definition: opentype.c:663
uint16_t subtable_count
Definition: opentype.c:664
unsigned int offset
Definition: opentype.c:3680
unsigned int flags
Definition: opentype.c:3682
unsigned int subtable_count
Definition: opentype.c:3681
uint16_t script_count
Definition: opentype.c:430
struct ot_script_record scripts[1]
Definition: opentype.c:431
uint16_t script
Definition: opentype.c:425
uint32_t tag
Definition: opentype.c:424
uint16_t default_langsys
Definition: opentype.c:417
struct ot_langsys_record langsys[1]
Definition: opentype.c:419
uint16_t langsys_count
Definition: opentype.c:418
uint32_t version
Definition: opentype.c:86
uint16_t entrySelector
Definition: opentype.c:89
uint16_t numTables
Definition: opentype.c:87
uint16_t searchRange
Definition: opentype.c:88
uint16_t rangeShift
Definition: opentype.c:90
uint32_t tag
Definition: opentype.c:95
uint32_t checksum
Definition: opentype.c:96
uint32_t length
Definition: opentype.c:98
uint32_t offset
Definition: opentype.c:97
Definition: _pair.h:47
int8_t minAdvanceSB
Definition: opentype.c:292
int8_t maxBeforeBL
Definition: opentype.c:293
int8_t caretOffset
Definition: opentype.c:290
int8_t caretSlopeNumerator
Definition: opentype.c:288
int8_t minAfterBL
Definition: opentype.c:294
int8_t descender
Definition: opentype.c:286
int8_t minOriginSB
Definition: opentype.c:291
uint8_t widthMax
Definition: opentype.c:287
int8_t caretSlopeDenominator
Definition: opentype.c:289
int16_t originOffsetX
Definition: opentype.c:264
int16_t originOffsetY
Definition: opentype.c:265
uint32_t graphic_type
Definition: opentype.c:266
uint32_t num_strikes
Definition: opentype.c:251
uint16_t flags
Definition: opentype.c:250
uint16_t version
Definition: opentype.c:249
uint32_t strike_offset[1]
Definition: opentype.c:252
uint16_t ppem
Definition: opentype.c:257
uint16_t ppi
Definition: opentype.c:258
uint32_t glyphdata_offsets[1]
Definition: opentype.c:259
unsigned int default_value
unsigned int tag
unsigned int mask
unsigned int flags
unsigned int index
unsigned int stage
unsigned int max_value
struct shaping_feature * features
struct shaping_stage stages[MAX_SHAPING_STAGE]
unsigned int stage
Definition: parse.h:23
BYTE * data
Definition: ecma_167.h:138
USHORT macStyle
Definition: opentype.c:150
ULONGLONG modified
Definition: opentype.c:145
SHORT yMin
Definition: opentype.c:147
USHORT majorVersion
Definition: opentype.c:137
USHORT flags
Definition: opentype.c:142
SHORT index_format
Definition: opentype.c:153
USHORT lowestRecPPEM
Definition: opentype.c:151
SHORT yMax
Definition: opentype.c:149
SHORT xMin
Definition: opentype.c:146
USHORT unitsPerEm
Definition: opentype.c:143
ULONG revision
Definition: opentype.c:139
ULONG checksumadj
Definition: opentype.c:140
ULONG magic
Definition: opentype.c:141
ULONGLONG created
Definition: opentype.c:144
USHORT minorVersion
Definition: opentype.c:138
SHORT glyphdata_format
Definition: opentype.c:154
SHORT xMax
Definition: opentype.c:148
SHORT direction_hint
Definition: opentype.c:152
int16_t minLeftSideBearing
Definition: opentype.c:236
int16_t descender
Definition: opentype.c:233
int16_t caretSlopeRise
Definition: opentype.c:239
uint16_t minorVersion
Definition: opentype.c:231
int16_t metricDataFormat
Definition: opentype.c:243
int16_t xMaxExtent
Definition: opentype.c:238
int16_t linegap
Definition: opentype.c:234
int16_t reserved[4]
Definition: opentype.c:242
uint16_t majorVersion
Definition: opentype.c:230
int16_t ascender
Definition: opentype.c:232
uint16_t advanceWidthMax
Definition: opentype.c:235
uint16_t numberOfHMetrics
Definition: opentype.c:244
int16_t minRightSideBearing
Definition: opentype.c:237
int16_t caretOffset
Definition: opentype.c:241
int16_t caretSlopeRun
Definition: opentype.c:240
USHORT usMaxContext
Definition: opentype.c:225
USHORT sTypoAscender
Definition: opentype.c:212
USHORT fsSelection
Definition: opentype.c:205
SHORT xAvgCharWidth
Definition: opentype.c:184
CHAR achVendID[4]
Definition: opentype.c:204
USHORT usWidthClass
Definition: opentype.c:186
PANOSE panose
Definition: opentype.c:199
SHORT yStrikeoutPosition
Definition: opentype.c:197
USHORT usWinAscent
Definition: opentype.c:215
SHORT fsType
Definition: opentype.c:187
SHORT sxHeight
Definition: opentype.c:221
SHORT ySubscriptYOffset
Definition: opentype.c:191
USHORT version
Definition: opentype.c:183
ULONG ulUnicodeRange4
Definition: opentype.c:203
SHORT ySuperscriptXSize
Definition: opentype.c:192
SHORT sCapHeight
Definition: opentype.c:222
USHORT usBreakChar
Definition: opentype.c:224
USHORT sTypoLineGap
Definition: opentype.c:214
SHORT ySubscriptYSize
Definition: opentype.c:189
SHORT ySubscriptXSize
Definition: opentype.c:188
USHORT sTypoDescender
Definition: opentype.c:213
USHORT usFirstCharIndex
Definition: opentype.c:206
SHORT ySuperscriptXOffset
Definition: opentype.c:194
USHORT usDefaultChar
Definition: opentype.c:223
SHORT sFamilyClass
Definition: opentype.c:198
SHORT ySubscriptXOffset
Definition: opentype.c:190
USHORT usWeightClass
Definition: opentype.c:185
ULONG ulUnicodeRange3
Definition: opentype.c:202
ULONG ulUnicodeRange2
Definition: opentype.c:201
USHORT usWinDescent
Definition: opentype.c:216
ULONG ulUnicodeRange1
Definition: opentype.c:200
USHORT usLastCharIndex
Definition: opentype.c:207
SHORT ySuperscriptYOffset
Definition: opentype.c:195
SHORT ySuperscriptYSize
Definition: opentype.c:193
ULONG ulCodePageRange1
Definition: opentype.c:218
SHORT yStrikeoutSize
Definition: opentype.c:196
ULONG ulCodePageRange2
Definition: opentype.c:219
Definition: opentype.c:169
int32_t italicAngle
Definition: opentype.c:171
uint32_t fixed_pitch
Definition: opentype.c:174
uint32_t minmemType42
Definition: opentype.c:175
int16_t underlinePosition
Definition: opentype.c:172
uint32_t maxmemType1
Definition: opentype.c:178
int16_t underlineThickness
Definition: opentype.c:173
uint32_t minmemType1
Definition: opentype.c:177
uint32_t Version
Definition: opentype.c:170
uint32_t maxmemType42
Definition: opentype.c:176
uint16_t minor_version
Definition: opentype.c:79
uint32_t offsets[1]
Definition: opentype.c:81
uint16_t major_version
Definition: opentype.c:78
uint32_t tag
Definition: opentype.c:77
uint32_t num_fonts
Definition: opentype.c:80
int32_t max_value
Definition: opentype.c:1301
uint16_t flags
Definition: opentype.c:1302
uint16_t nameid
Definition: opentype.c:1303
int32_t default_value
Definition: opentype.c:1300
int32_t min_value
Definition: opentype.c:1299
uint32_t tag
Definition: opentype.c:1298
uint8_t endsz
Definition: opentype.c:385
uint8_t startsz
Definition: opentype.c:384
struct vdmx_vtable entries[1]
Definition: opentype.c:386
uint16_t recs
Definition: opentype.c:383
uint16_t num_recs
Definition: opentype.c:362
uint16_t version
Definition: opentype.c:361
uint16_t num_ratios
Definition: opentype.c:363
uint8_t yEndRatio
Definition: opentype.c:371
uint8_t xRatio
Definition: opentype.c:369
uint8_t yStartRatio
Definition: opentype.c:370
uint8_t bCharSet
Definition: opentype.c:368
int16_t yMax
Definition: opentype.c:377
uint16_t yPelHeight
Definition: opentype.c:376
int16_t yMin
Definition: opentype.c:378
#define max(a, b)
Definition: svc.c:63
struct sock * chain
Definition: tcpcore.h:1
#define bsearch
int32_t INT32
Definition: typedefs.h:58
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
int32_t INT
Definition: typedefs.h:58
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t UINT32
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
Definition: pdh_main.c:64
static const WCHAR props[]
Definition: wbemdisp.c:288
int codepage
Definition: win_iconv.c:156
#define HRESULT
Definition: msvc.h:7
#define S_FALSE
Definition: winerror.h:3451
#define DWRITE_E_NOCOLOR
Definition: winerror.h:7346
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:3437
#define C3_DIACRITIC
Definition: winnls.h:291
#define CT_CTYPE3
Definition: winnls.h:267
#define IS_HIGH_SURROGATE(ch)
Definition: winnls.h:763
#define IS_LOW_SURROGATE(ch)
Definition: winnls.h:764
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
ULONG bpp[]
Definition: xlate.c:19
unsigned char BYTE
Definition: xxhash.c:193