diff options
author | Yukimasa Morimi <h20y6m@yahoo.co.jp> | 2024-02-10 03:25:28 +0000 |
---|---|---|
committer | Yukimasa Morimi <h20y6m@yahoo.co.jp> | 2024-02-10 03:25:28 +0000 |
commit | 28c5129fe7864e1005edc90cf737372ba1bc78c7 (patch) | |
tree | 45536c0f5666955912b04bcd20c14a57aad31872 /Build/source/texk/dvipdfm-x/tt_cmap.c | |
parent | fc7cd0ce37a54e91a81606bc8b046f771a839da5 (diff) |
dvipdfmx: Look up the TrueType cmap format 14 subtable
git-svn-id: svn://tug.org/texlive/trunk@69764 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipdfm-x/tt_cmap.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/tt_cmap.c | 155 |
1 files changed, 154 insertions, 1 deletions
diff --git a/Build/source/texk/dvipdfm-x/tt_cmap.c b/Build/source/texk/dvipdfm-x/tt_cmap.c index 79bdab2815f..56c699275d6 100644 --- a/Build/source/texk/dvipdfm-x/tt_cmap.c +++ b/Build/source/texk/dvipdfm-x/tt_cmap.c @@ -447,6 +447,114 @@ lookup_cmap12 (struct cmap12 *map, ULONG cccc) return gid; } +/* format 14: unicode variation sequences */ + +struct variationSelector +{ + /* Variation selector */ + ULONG varSelector; + + /* Default UVS table */ + ULONG numUnicodeValueRanges; + ULONG *rangesStartUnicodeValue; + BYTE *rangesAdditionalCount; + + /* Non-Default UVS table */ + ULONG numUVSMappings; + ULONG *uvsMappingsUnicodeValue; + USHORT *uvsMappingsGlyphID; +}; + +struct cmap14 +{ + ULONG numVarSelectorRecords; + struct variationSelector *varSelector; +}; + +/* ULONG length */ +static struct cmap14 * +read_cmap14 (sfnt *sfont, ULONG offset, ULONG len) +{ + struct cmap14 *map; + ULONG *defaultUVSOffset, *nonDefaultUVSOffset; + ULONG i, j; + + if (len < 4) { + WARN("invalid format 14 TT cmap subtable"); + return NULL; + } + + map = NEW(1, struct cmap14); + map->numVarSelectorRecords = sfnt_get_ulong(sfont); + map->varSelector = NEW(map->numVarSelectorRecords, struct variationSelector); + defaultUVSOffset = NEW(map->numVarSelectorRecords, ULONG); + nonDefaultUVSOffset = NEW(map->numVarSelectorRecords, ULONG); + /* Read VariationSelector Record */ + for (i = 0; i < map->numVarSelectorRecords; i++) { + map->varSelector[i].varSelector = sfnt_get_uint24(sfont); + defaultUVSOffset[i] = sfnt_get_ulong(sfont); + nonDefaultUVSOffset[i] = sfnt_get_ulong(sfont); + } + for (i = 0; i < map->numVarSelectorRecords; i++) { + /* Read DefaultUVS Table */ + if (defaultUVSOffset[i] > 0) { + sfnt_seek_set(sfont, offset + defaultUVSOffset[i]); + map->varSelector[i].numUnicodeValueRanges = sfnt_get_ulong(sfont); + map->varSelector[i].rangesStartUnicodeValue = NEW(map->varSelector[i].numUnicodeValueRanges, ULONG); + map->varSelector[i].rangesAdditionalCount = NEW(map->varSelector[i].numUnicodeValueRanges, BYTE); + for (j = 0; j < map->varSelector[i].numUnicodeValueRanges; j++) { + map->varSelector[i].rangesStartUnicodeValue[j] = sfnt_get_uint24(sfont); + map->varSelector[i].rangesAdditionalCount[j] = sfnt_get_byte(sfont); + } + } else { + map->varSelector[i].numUnicodeValueRanges = 0; + map->varSelector[i].rangesStartUnicodeValue = NULL; + map->varSelector[i].rangesAdditionalCount = NULL; + } + /* Read NonDefaultUVS Table */ + if (nonDefaultUVSOffset[i] > 0) { + sfnt_seek_set(sfont, offset + nonDefaultUVSOffset[i]); + map->varSelector[i].numUVSMappings = sfnt_get_ulong(sfont); + map->varSelector[i].uvsMappingsUnicodeValue = NEW(map->varSelector[i].numUVSMappings, ULONG); + map->varSelector[i].uvsMappingsGlyphID = NEW(map->varSelector[i].numUVSMappings, USHORT); + for (j = 0; j < map->varSelector[i].numUVSMappings; j++) { + map->varSelector[i].uvsMappingsUnicodeValue[j] = sfnt_get_uint24(sfont); + map->varSelector[i].uvsMappingsGlyphID[j] = sfnt_get_ushort(sfont); + } + } else { + map->varSelector[i].numUVSMappings = 0; + map->varSelector[i].uvsMappingsUnicodeValue = NULL; + map->varSelector[i].uvsMappingsGlyphID = NULL; + } + } + + RELEASE(defaultUVSOffset); + RELEASE(nonDefaultUVSOffset); + return map; +} + +static void +release_cmap14 (struct cmap14 *map) +{ + ULONG i; + if (map) { + if (map->varSelector) { + for (i = 0; i < map->numVarSelectorRecords; i++) { + if (map->varSelector[i].rangesStartUnicodeValue) + RELEASE(map->varSelector[i].rangesStartUnicodeValue); + if (map->varSelector[i].rangesAdditionalCount) + RELEASE(map->varSelector[i].rangesAdditionalCount); + if (map->varSelector[i].uvsMappingsUnicodeValue) + RELEASE(map->varSelector[i].uvsMappingsUnicodeValue); + if (map->varSelector[i].uvsMappingsGlyphID) + RELEASE(map->varSelector[i].uvsMappingsGlyphID); + } + RELEASE(map->varSelector); + } + RELEASE(map); + } +} + /* read cmap */ tt_cmap * tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding) @@ -489,7 +597,7 @@ tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding) if (cmap->format <= 6) { length = sfnt_get_ushort(sfont); cmap->language = sfnt_get_ushort(sfont); /* language (Mac) */ - } else { + } else if (cmap->format != 14) { if (sfnt_get_ushort(sfont) != 0) { /* reverved - 0 */ WARN("Unrecognized cmap subtable format."); tt_cmap_release(cmap); @@ -498,6 +606,9 @@ tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding) length = sfnt_get_ulong(sfont); cmap->language = sfnt_get_ulong(sfont); } + } else { + length = sfnt_get_ulong(sfont); + cmap->language = 0; } switch(cmap->format) { @@ -517,6 +628,9 @@ tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding) /* WARN("UCS-4 TrueType cmap table..."); */ cmap->map = read_cmap12(sfont, length); break; + case 14: + cmap->map = read_cmap14(sfont, offset, length); + break; default: WARN("Unrecognized OpenType/TrueType cmap format."); tt_cmap_release(cmap); @@ -554,6 +668,9 @@ tt_cmap_release (tt_cmap *cmap) case 12: release_cmap12(cmap->map); break; + case 14: + release_cmap14(cmap->map); + break; default: WARN("Unrecognized OpenType/TrueType cmap format: %d", cmap->format); break; @@ -602,6 +719,42 @@ tt_cmap_lookup (tt_cmap *cmap, ULONG cc) return gid; } +static USHORT +lookup_cmap14 (struct cmap14 *map, tt_cmap* cmap_default, ULONG unicode, ULONG uvs) +{ + ULONG i, j; + + for (i = 0; i < map->numVarSelectorRecords; i++) { + if (map->varSelector[i].varSelector == uvs) { + for (j = 0; j < map->varSelector[i].numUnicodeValueRanges; j++) { + if (map->varSelector[i].rangesStartUnicodeValue[j] <= unicode && + unicode <= map->varSelector[i].rangesStartUnicodeValue[j] + map->varSelector[i].rangesAdditionalCount[j]) + return tt_cmap_lookup(cmap_default, unicode); + } + for (j = 0; j < map->varSelector[i].numUVSMappings; j++) { + if (map->varSelector[i].uvsMappingsUnicodeValue[j] == unicode) + return map->varSelector[i].uvsMappingsGlyphID[j]; + } + return 0; + } + } + + return 0; +} + +USHORT +tt_cmap_uvs_lookup(tt_cmap* cmap_uvs, tt_cmap* cmap_default, ULONG unicode, ULONG uvs) +{ + ASSERT(cmap_uvs); + + if (cmap_uvs->format != 14) { + WARN("Unicode Variation Sequences in OpenType/TrueType cmap must be format 14."); + return 0; + } + + return lookup_cmap14(cmap_uvs->map, cmap_default, unicode, uvs); +} + static unsigned char srange_min[2] = {0x00, 0x00}; |