summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/tt_cmap.c
diff options
context:
space:
mode:
authorYukimasa Morimi <h20y6m@yahoo.co.jp>2024-02-10 03:25:28 +0000
committerYukimasa Morimi <h20y6m@yahoo.co.jp>2024-02-10 03:25:28 +0000
commit28c5129fe7864e1005edc90cf737372ba1bc78c7 (patch)
tree45536c0f5666955912b04bcd20c14a57aad31872 /Build/source/texk/dvipdfm-x/tt_cmap.c
parentfc7cd0ce37a54e91a81606bc8b046f771a839da5 (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.c155
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};