From 7d3486ce6de3cc1079206d467c6846cb93b05883 Mon Sep 17 00:00:00 2001 From: Connum Date: Thu, 2 Nov 2023 15:50:23 +0100 Subject: [PATCH] handle CMAP format 0 for platform 1, encoding 0 (legacy Macintosh encoding) --- src/tables/cmap.js | 40 +++++++++++++++++++++++++----- src/tables/name.js | 2 +- src/types.js | 2 +- test/fonts/LICENSE | 5 ++++ test/fonts/TestCMAPMacTurkish.ttf | Bin 0 -> 19644 bytes test/tables/cmap.js | 18 +++++++++++++- 6 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 test/fonts/TestCMAPMacTurkish.ttf diff --git a/src/tables/cmap.js b/src/tables/cmap.js index bc2b10f7..5184c9a6 100644 --- a/src/tables/cmap.js +++ b/src/tables/cmap.js @@ -4,6 +4,25 @@ import check from '../check.js'; import parse from '../parse.js'; import table from '../table.js'; +import { eightBitMacEncodings } from '../types.js'; +import { getEncoding } from '../tables/name.js'; + +function parseCmapTableFormat0(cmap, p, platformID, encodingID) { + // Length in bytes of the index map + cmap.length = p.parseUShort(); + // see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html + // section "Macintosh Language Codes" + cmap.language = p.parseUShort() - 1; + + const indexMap = p.parseByteList(cmap.length); + const glyphIndexMap = Object.assign({}, indexMap); + const encoding = getEncoding(platformID, encodingID, cmap.language); + const decodingTable = eightBitMacEncodings[encoding]; + for (let i = 0; i < decodingTable.length; i++) { + glyphIndexMap[decodingTable.charCodeAt(i)] = indexMap[0x80 + i]; + } + cmap.glyphIndexMap = glyphIndexMap; +} function parseCmapTableFormat12(cmap, p) { //Skip reserved. @@ -150,11 +169,15 @@ function parseCmapTable(data, start) { let format14Parser = null; let format14offset = -1; let offset = -1; + let platformId = null; + let encodingId = null; for (let i = cmap.numTables - 1; i >= 0; i -= 1) { - const platformId = parse.getUShort(data, start + 4 + (i * 8)); - const encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2); + platformId = parse.getUShort(data, start + 4 + (i * 8)); + encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2); if ((platformId === 3 && (encodingId === 0 || encodingId === 1 || encodingId === 10)) || - (platformId === 0 && (encodingId === 0 || encodingId === 1 || encodingId === 2 || encodingId === 3 || encodingId === 4))) { + (platformId === 0 && (encodingId === 0 || encodingId === 1 || encodingId === 2 || encodingId === 3 || encodingId === 4)) || + (platformId === 1 && encodingId === 0) // MacOS <= 9 + ) { offset = parse.getULong(data, start + 4 + (i * 8) + 4); // allow for early break if (format14Parser) { @@ -178,12 +201,17 @@ function parseCmapTable(data, start) { const p = new parse.Parser(data, start + offset); cmap.format = p.parseUShort(); - if (cmap.format === 12) { + if (cmap.format === 0) { + parseCmapTableFormat0(cmap, p, platformId, encodingId); + } else if (cmap.format === 12) { parseCmapTableFormat12(cmap, p); } else if (cmap.format === 4) { parseCmapTableFormat4(cmap, p, data, start, offset); } else { - throw new Error('Only format 4, 12 and 14 cmap tables are supported (found format ' + cmap.format + ').'); + throw new Error( + 'Only format 0 (platformId 1, encodingId 0), 4, 12 and 14 cmap tables are supported ' + + '(found format ' + cmap.format + ', platformId ' + platformId + ', encodingId ' + encodingId + ').' + ); } // format 14 is the only one that's not exclusive but can be used as a supplement. @@ -361,4 +389,4 @@ function makeCmapTable(glyphs) { export default { parse: parseCmapTable, make: makeCmapTable }; -export { parseCmapTableFormat14 }; +export { parseCmapTableFormat0, parseCmapTableFormat14 }; diff --git a/src/tables/name.js b/src/tables/name.js index 1ca803d3..b722127b 100644 --- a/src/tables/name.js +++ b/src/tables/name.js @@ -604,7 +604,7 @@ const macLanguageEncodings = { 146: 'x-mac-gaelic' // langIrishGaelicScript }; -function getEncoding(platformID, encodingID, languageID) { +export function getEncoding(platformID, encodingID, languageID) { switch (platformID) { case 0: // Unicode return utf16; diff --git a/src/types.js b/src/types.js index 25898970..d8e5e637 100644 --- a/src/types.js +++ b/src/types.js @@ -437,7 +437,7 @@ sizeOf.UTF16 = function(v) { /** * @private */ -const eightBitMacEncodings = { +export const eightBitMacEncodings = { 'x-mac-croatian': // Python: 'mac_croatian' 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø' + '¿¡¬√ƒ≈Ć«Č… ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ', diff --git a/test/fonts/LICENSE b/test/fonts/LICENSE index 84e75622..856f4d74 100644 --- a/test/fonts/LICENSE +++ b/test/fonts/LICENSE @@ -37,6 +37,11 @@ TestCMAP14.otf http://www.apache.org/licenses/LICENSE-2.0 https://github.com/unicode-org/text-rendering-tests/blob/main/LICENSE.md +TestCMAPMacTurkish.ttf + Copyright © 2016 by Unicode Inc. + SIL Open Font License, Version 1.1 + https://opensource.org/licenses/OFL-1.1 + Vibur.woff Copyright (c) 2010, Johan Kallas (johan.kallas@gmail.com). SIL Open Font License, Version 1.1 diff --git a/test/fonts/TestCMAPMacTurkish.ttf b/test/fonts/TestCMAPMacTurkish.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4f89b09330068a59a557bddcbe81b0b12a12c14b GIT binary patch literal 19644 zcmb7s2Yg%A_3*n-%a$!!>uK+&Ee{P#vTQ#)@=UxPkHkrA$MHxUCvg@TkU>JoAcG86 z7%ig#l9XKnDU`5EX`qZ2I)S#dw55fX_TLsL@$+}?dy?&pmfz>(Sx;9_=bn4++2>pn zh#-g@;#xvLgjzd_A~%jKUqTS51V$GRt{hk`xb2-^5QInrW2&VC>sAv+f+mQjZ^P$` zr7Jd%ysdurW`dCXi6E+fyli-2NFF+K2tIojuJ|$-$gRyf4EO(p%e8Ff`c10aEK-1V z8$k%RtQa30_=VxmDuNLEVC?yo1DjT(a`YbD>*0C(s)3cmSxpCu38E3hdvo>py7iM! z6A_sI0REi7xFh1adD2!_e_r{&2!R0bAc&vHegxlv*MFUOdBQ(&TKcJQ7rd1aBp!ty z_?|GIg?Vx)`23voQw|dU8UOp&+{mxdT%wcMONcJ{TmbKd0u3P{-y$gTWg;#x z!|Q!;?II{a0N&RT6gmah$;podG8jJr<1fPHfvcE^leeZ{{|=w^0v@MehY+D8UjzD= zPX0%rByz|Lt4gKYD_Yk+UZM zK|Vn!&?Z8JuAck@c`w{=Cp3aD2swEgu501>JBe)a9>Pn82`TzF(B)Y|3*RvVOo^a# z@;~I$L>}2ZIYC-s-k0INi1=Ij)i*`^A`Txhd?qCAM1o8a%LUCu0zFR{$a;=mDegVS z_b^A-6o>b7L^BEab9>QD1ksNPntQ&HNMM>?>4NPhFr7IXV>+iVps}2zbNV$yUrgi6 zE}$=_apodFg>_;YUf}}%^>cIunqsQJ^9z2DX*%-) znqvOIdxY^8dI8Vp;5py{ybs)-7r}n~8t8+shv0I<)eL;_PhubX67Ihse1dkO0QSg^ z{yF)T;7>r`Lf~(F0iToN=?lI?bJw>CM({LIDar>KsRo{3K_mqPQGxjs=;7k{ItS$F zCD@Dd$3}Cl_wT1Zb%L{ewt>P$ZUQWlM8%W%4|QQl-{V zTAkitG?^_{o8950U2c!p=MMz)3kr)u;YhSN7EhEUOUufcipp83s_L5By87938XB9L zTUy)N=XP{&$@yxT|Tlf5P-{n?M5fo8GR1<57=aC$Zq7CQ}I)Q$Geucgwvq%%^BRj|q z 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 parse(readFileSync(url), opt); describe('tables/cmap.js', function() { @@ -55,4 +58,17 @@ describe('tables/cmap.js', function() { assert.deepEqual(cmap.varSelectorList, expectedData); }); + it('can parse CMAP format 0 legacy Mac encoding', function() { + let font; + assert.doesNotThrow(function() { + font = loadSync('./test/fonts/TestCMAPMacTurkish.ttf'); + }); + const testString = '“ABÇĞIİÖŞÜ”abçğıiöşüă'; + const glyphIds = []; + const expectedGlyphIds = [200,34,35,126,176,42,178,140,181,145,201,66,67,154,177,222,74,168,182,174,123,184]; + for (let i = 0; i < testString.length; i++) { + glyphIds.push(font.charToGlyphIndex(testString.charAt(i))); + } + assert.deepEqual(glyphIds, expectedGlyphIds); + }); }); \ No newline at end of file