summaryrefslogtreecommitdiff
path: root/Build/source
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source')
-rw-r--r--Build/source/texk/dvipdfm-x/ChangeLog7
-rw-r--r--Build/source/texk/dvipdfm-x/cidtype2.c76
-rw-r--r--Build/source/texk/dvipdfm-x/sfnt.h2
-rw-r--r--Build/source/texk/dvipdfm-x/tt_cmap.c155
-rw-r--r--Build/source/texk/dvipdfm-x/tt_cmap.h2
5 files changed, 217 insertions, 25 deletions
diff --git a/Build/source/texk/dvipdfm-x/ChangeLog b/Build/source/texk/dvipdfm-x/ChangeLog
index f906245d9da..5d748d72c59 100644
--- a/Build/source/texk/dvipdfm-x/ChangeLog
+++ b/Build/source/texk/dvipdfm-x/ChangeLog
@@ -1,3 +1,10 @@
+2024-02-10 Yukimasa Morimi <h20y6m@yahoo.co.jp>
+
+ * cidtype2.c, sfnt.h, tt_cmap.{c,h}:
+ Look up the TrueType cmap format 14 subtable when mapping CID to
+ Unicode Variation Sequence in new Adobe-Japan1-UCS2 CMap.
+ https://github.com/texjporg/tex-jp-build/issues/155
+
2024-02-10 TANAKA Takuji <ttk@t-lab.opal.ne.jp>
* cidtype2.c: Fix an issue on glyph conversion of
diff --git a/Build/source/texk/dvipdfm-x/cidtype2.c b/Build/source/texk/dvipdfm-x/cidtype2.c
index 67f39d21b78..6d801bc5618 100644
--- a/Build/source/texk/dvipdfm-x/cidtype2.c
+++ b/Build/source/texk/dvipdfm-x/cidtype2.c
@@ -439,13 +439,15 @@ fix_CJK_symbols (unsigned short code)
}
static int32_t
-cid_to_code (CMap *cmap, CID cid, int unicode_cmap)
+cid_to_code (CMap *cmap, CID cid, int unicode_cmap, int32_t *puvs)
{
unsigned char inbuf[2], outbuf[32];
int inbytesleft = 2, outbytesleft = 32;
const unsigned char *p;
unsigned char *q;
+ *puvs = -1;
+
if (!cmap)
return cid;
@@ -475,13 +477,9 @@ cid_to_code (CMap *cmap, CID cid, int unicode_cmap)
/* Check following Variation Selectors */
uvs = UC_UTF16BE_decode_char(&p, endptr);
if (p == endptr && uvs >= 0xfe00 && uvs <= 0xfe0f) {
- /* Combine CJK compatibility ideograph */
- int32_t cci = UC_Combine_CJK_compatibility_ideograph(uc, uvs);
- if (cci > 0)
- return cci;
- /* Ignore Standardized Variation Sequence */
- WARN("Ignored Variation Selector: CID=%u mapped to U+%04X U+%04X", cid, uc, uvs);
- return uc;
+ /* Standardized Variation Sequence */
+ *puvs = uvs;
+ return uc;
}
WARN("CID=%u mapped to non-single Unicode characters...", cid);
return -1;
@@ -500,16 +498,12 @@ cid_to_code (CMap *cmap, CID cid, int unicode_cmap)
uvs = UC_UTF16BE_decode_char(&p, endptr);
if (p == endptr) {
if (uvs >= 0xfe00 && uvs <= 0xfe0f) {
- /* Combine CJK compatibility ideograph */
- int32_t cci = UC_Combine_CJK_compatibility_ideograph(uc, uvs);
- if (cci > 0)
- return cci;
- /* Ignore Standardized Variation Sequence */
- WARN("Ignored Variation Selector: CID=%u mapped to U+%04X U+%04X", cid, uc, uvs);
+ /* Standardized Variation Sequence */
+ *puvs = uvs;
return uc;
} else if (uvs >= 0xe0100 && uvs <= 0xe01ef) {
- /* Ignore Ideographic Variation Sequence */
- WARN("Ignored Variation Selector: CID=%u mapped to U+%04X U+%04X", cid, uc, uvs);
+ /* Ideographic Variation Sequence */
+ *puvs = uvs;
return uc;
}
}
@@ -528,8 +522,8 @@ cid_to_code (CMap *cmap, CID cid, int unicode_cmap)
uvs = UC_UTF16BE_decode_char(&p, endptr);
if (p == endptr) {
if (uvs >= 0xe0100 && uvs <= 0xe01ef) {
- /* Ignore Ideographic Variation Sequence */
- WARN("Ignored Variation Selector: CID=%u mapped to U+%04X U+%04X", cid, uc, uvs);
+ /* Ideographic Variation Sequence */
+ *puvs = uvs;
return uc;
}
}
@@ -575,6 +569,7 @@ CIDFont_type2_dofont (pdf_font *font)
struct tt_glyphs *glyphs;
CMap *cmap = NULL;
tt_cmap *ttcmap = NULL;
+ tt_cmap *ttcmap_uvs = NULL;
ULONG offset = 0;
CID cid, last_cid;
unsigned char *cidtogidmap;
@@ -728,6 +723,8 @@ CIDFont_type2_dofont (pdf_font *font)
return -1;
} else if (i <= WIN_UCS_INDEX_MAX) {
unicode_cmap = 1;
+ /* Unicode Variation Sequences */
+ ttcmap_uvs = tt_cmap_read(sfont, 0, 5);
} else {
unicode_cmap = 0;
}
@@ -806,7 +803,7 @@ CIDFont_type2_dofont (pdf_font *font)
if (h_used_chars) {
used_chars = h_used_chars;
for (cid = 1; cid <= last_cid; cid++) {
- int32_t code;
+ int32_t code, uvs = 0;
uint16_t gid = 0;
if (!is_used_char2(h_used_chars, cid))
@@ -822,11 +819,26 @@ CIDFont_type2_dofont (pdf_font *font)
code = cid;
break;
case via_cid_to_code:
- code = cid_to_code(cmap, cid, unicode_cmap);
+ code = cid_to_code(cmap, cid, unicode_cmap, &uvs);
if (code < 0) {
WARN("Unable to map CID to code: CID=%u", cid);
} else {
- gid = tt_cmap_lookup(ttcmap, code);
+ if (ttcmap_uvs && uvs > 0) {
+ gid = tt_cmap_uvs_lookup(ttcmap_uvs, ttcmap, code, uvs);
+ }
+ if (gid == 0 && uvs >= 0xfe00 && uvs <= 0xfe0f) {
+ /* Standardized Variation Sequence */
+ /* Combine CJK compatibility ideograph */
+ int32_t code2 = UC_Combine_CJK_compatibility_ideograph(code, uvs);
+ if (code2 > 0)
+ gid = tt_cmap_lookup(ttcmap, code2);
+ }
+ if (gid == 0) {
+ gid = tt_cmap_lookup(ttcmap, code);
+ if (gid > 0 && uvs > 0) {
+ WARN("Ignored Variation Selector: CID=%u mapped to U+%04X U+%04X", cid, code, uvs);
+ }
+ }
#ifdef FIX_CJK_UNIOCDE_SYMBOLS
if (gid == 0 && unicode_cmap && code <= 0xFFFF) {
int alt_code;
@@ -888,7 +900,7 @@ CIDFont_type2_dofont (pdf_font *font)
}
for (cid = 1; cid <= last_cid; cid++) {
- int32_t code;
+ int32_t code, uvs = 0;
uint16_t gid = 0;
if (!is_used_char2(v_used_chars, cid))
@@ -912,11 +924,26 @@ CIDFont_type2_dofont (pdf_font *font)
code = cid;
break;
case via_cid_to_code:
- code = cid_to_code(cmap, cid, unicode_cmap);
+ code = cid_to_code(cmap, cid, unicode_cmap, &uvs);
if (code < 0) {
WARN("Unable to map CID to code: CID=%u", cid);
} else {
- gid = tt_cmap_lookup(ttcmap, code);
+ if (ttcmap_uvs && uvs > 0) {
+ gid = tt_cmap_uvs_lookup(ttcmap_uvs, ttcmap, code, uvs);
+ }
+ if (gid == 0 && uvs >= 0xfe00 && uvs <= 0xfe0f) {
+ /* Standardized Variation Sequence */
+ /* Combine CJK compatibility ideograph */
+ int32_t code2 = UC_Combine_CJK_compatibility_ideograph(code, uvs);
+ if (code2 > 0)
+ gid = tt_cmap_lookup(ttcmap, code2);
+ }
+ if (gid == 0) {
+ gid = tt_cmap_lookup(ttcmap, code);
+ if (gid > 0 && uvs > 0) {
+ WARN("Ignored Variation Selector: CID=%u mapped to U+%04X U+%04X", cid, code, uvs);
+ }
+ }
#ifdef FIX_CJK_UNIOCDE_SYMBOLS
if (gid == 0 && unicode_cmap && code <= 0xFFFF) {
int alt_code;
@@ -964,6 +991,7 @@ CIDFont_type2_dofont (pdf_font *font)
ASSERT(used_chars);
tt_cmap_release(ttcmap);
+ tt_cmap_release(ttcmap_uvs);
if (font->cid.options.embed) {
if (tt_build_tables(sfont, glyphs) < 0) {
diff --git a/Build/source/texk/dvipdfm-x/sfnt.h b/Build/source/texk/dvipdfm-x/sfnt.h
index 262ef0e14b3..c6d1f057de2 100644
--- a/Build/source/texk/dvipdfm-x/sfnt.h
+++ b/Build/source/texk/dvipdfm-x/sfnt.h
@@ -92,6 +92,8 @@ typedef struct
#define sfnt_get_ulong(s) ((ULONG) get_unsigned_quad((s)->stream))
#define sfnt_get_long(s) ((LONG) get_signed_quad ((s)->stream))
+#define sfnt_get_uint24(s) ((ULONG) get_unsigned_triple((s)->stream))
+
#define sfnt_seek_set(s,o) seek_absolute((s)->stream, (o))
#define sfnt_read(b,l,s) fread((b), 1, (l), (s)->stream)
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};
diff --git a/Build/source/texk/dvipdfm-x/tt_cmap.h b/Build/source/texk/dvipdfm-x/tt_cmap.h
index 439108c4797..420850d89e5 100644
--- a/Build/source/texk/dvipdfm-x/tt_cmap.h
+++ b/Build/source/texk/dvipdfm-x/tt_cmap.h
@@ -61,6 +61,8 @@ extern tt_cmap *tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding);
extern USHORT tt_cmap_lookup (tt_cmap *cmap, ULONG cc);
extern void tt_cmap_release (tt_cmap *cmap);
+extern USHORT tt_cmap_uvs_lookup(tt_cmap* cmap_uvs, tt_cmap* cmap_default, ULONG unicode, ULONG uvs);
+
#include "pdfobj.h"
/* Indirect reference */