diff --git a/src/core/core_utils.js b/src/core/core_utils.js index a84373d1614ac8..f3c48471f09c0d 100644 --- a/src/core/core_utils.js +++ b/src/core/core_utils.js @@ -670,6 +670,50 @@ function getSizeInBytes(x) { return Math.ceil(Math.ceil(Math.log2(1 + x)) / 8); } +function getVerticalPresentationForm() { + return getLookupTableFactory(lookup => { + for (const [key, value] of [ + // This table has been found at + // https://searchfox.org/mozilla-central/rev/cbdfa503a87597b20719aae5f6a1efccd6cb3b7b/gfx/thebes/gfxHarfBuzzShaper.cpp#251-294 + [0x2013, 0xfe32], // EN DASH + [0x2014, 0xfe31], // EM DASH + [0x2025, 0xfe30], // TWO DOT LEADER + [0x2026, 0xfe19], // HORIZONTAL ELLIPSIS + [0x3001, 0xfe11], // IDEOGRAPHIC COMMA + [0x3002, 0xfe12], // IDEOGRAPHIC FULL STOP + [0x3008, 0xfe3f], // LEFT ANGLE BRACKET + [0x3009, 0xfe40], // RIGHT ANGLE BRACKET + [0x300a, 0xfe3d], // LEFT DOUBLE ANGLE BRACKET + [0x300b, 0xfe3e], // RIGHT DOUBLE ANGLE BRACKET + [0x300c, 0xfe41], // LEFT CORNER BRACKET + [0x300d, 0xfe42], // RIGHT CORNER BRACKET + [0x300e, 0xfe43], // LEFT WHITE CORNER BRACKET + [0x300f, 0xfe44], // RIGHT WHITE CORNER BRACKET + [0x3010, 0xfe3b], // LEFT BLACK LENTICULAR BRACKET + [0x3011, 0xfe3c], // RIGHT BLACK LENTICULAR BRACKET + [0x3014, 0xfe39], // LEFT TORTOISE SHELL BRACKET + [0x3015, 0xfe3a], // RIGHT TORTOISE SHELL BRACKET + [0x3016, 0xfe17], // LEFT WHITE LENTICULAR BRACKET + [0x3017, 0xfe18], // RIGHT WHITE LENTICULAR BRACKET + [0xfe4f, 0xfe34], // WAVY LOW LINE + [0xff01, 0xfe15], // FULLWIDTH EXCLAMATION MARK + [0xff08, 0xfe35], // FULLWIDTH LEFT PARENTHESIS + [0xff09, 0xfe36], // FULLWIDTH RIGHT PARENTHESIS + [0xff0c, 0xfe10], // FULLWIDTH COMMA + [0xff1a, 0xfe13], // FULLWIDTH COLON + [0xff1b, 0xfe14], // FULLWIDTH SEMICOLON + [0xff1f, 0xfe16], // FULLWIDTH QUESTION MARK + [0xff3b, 0xfe47], // FULLWIDTH LEFT SQUARE BRACKET + [0xff3d, 0xfe48], // FULLWIDTH RIGHT SQUARE BRACKET + [0xff3f, 0xfe33], // FULLWIDTH LOW LINE + [0xff5b, 0xfe37], // FULLWIDTH LEFT CURLY BRACKET + [0xff5d, 0xfe38], + ]) { + lookup[key] = value; + } + })(); +} + export { arrayBuffersToBytes, codePointIter, @@ -682,6 +726,7 @@ export { getNewAnnotationsMap, getRotationMatrix, getSizeInBytes, + getVerticalPresentationForm, isAscii, isBooleanArray, isNumberArray, diff --git a/src/core/fonts.js b/src/core/fonts.js index 52994267da4627..d4a1a8e455b3c9 100644 --- a/src/core/fonts.js +++ b/src/core/fonts.js @@ -54,6 +54,7 @@ import { getSupplementalGlyphMapForArialBlack, getSupplementalGlyphMapForCalibri, } from "./standard_fonts.js"; +import { getVerticalPresentationForm, readUint32 } from "./core_utils.js"; import { IdentityToUnicodeMap, ToUnicodeMap } from "./to_unicode_map.js"; import { CFFFont } from "./cff_font.js"; import { FontRendererFactory } from "./font_renderer.js"; @@ -61,7 +62,6 @@ import { getFontBasicMetrics } from "./metrics.js"; import { GlyfTable } from "./glyf.js"; import { IdentityCMap } from "./cmap.js"; import { OpenTypeFileBuilder } from "./opentype_file_builder.js"; -import { readUint32 } from "./core_utils.js"; import { Stream } from "./stream.js"; import { Type1Font } from "./type1_font.js"; @@ -3366,6 +3366,13 @@ class Font { } } + if (this.missingFile && this.vertical && fontChar.length === 1) { + const vertical = getVerticalPresentationForm()[fontChar.charCodeAt(0)]; + if (vertical) { + fontChar = unicode = String.fromCharCode(vertical); + } + } + glyph = new Glyph( charcode, fontChar, diff --git a/test/pdfs/bug1905623.pdf.link b/test/pdfs/bug1905623.pdf.link new file mode 100644 index 00000000000000..0c249d74b4846d --- /dev/null +++ b/test/pdfs/bug1905623.pdf.link @@ -0,0 +1 @@ +https://bugzilla.mozilla.org/attachment.cgi?id=9410429 diff --git a/test/test_manifest.json b/test/test_manifest.json index a8fedcd4b13181..78c4d8f592b837 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -10113,5 +10113,15 @@ "rounds": 1, "link": true, "type": "eq" + }, + { + "id": "bug1905623", + "file": "pdfs/bug1905623.pdf", + "md5": "6c180a4353bda6b3cb0c693c5e5b32c4", + "rounds": 1, + "link": true, + "firstPage": 2, + "lastPage": 2, + "type": "eq" } ]