Use CIDToGIDMap when the font is a type 2 with an OpenType font

It fixes #18062.
This commit is contained in:
calixteman 2025-12-25 22:55:54 +01:00
parent 1990fa7cd0
commit 5518c8a544
No known key found for this signature in database
GPG Key ID: 0C5442631EE0691F
4 changed files with 42 additions and 30 deletions

View File

@ -255,6 +255,8 @@ class CFFParser {
const charStringOffset = topDict.getByName("CharStrings");
const charStringIndex = this.parseIndex(charStringOffset).obj;
cff.charStringCount = charStringIndex.count;
const fontMatrix = topDict.getByName("FontMatrix");
if (fontMatrix) {
properties.fontMatrix = fontMatrix;
@ -1005,6 +1007,7 @@ class CFF {
this.fdSelect = null;
this.isCIDFont = false;
this.charStringCount = 0;
}
duplicateFirstGlyph() {

View File

@ -60,7 +60,6 @@ import { CFFFont } from "./cff_font.js";
import { FontRendererFactory } from "./font_renderer.js";
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";
@ -2638,27 +2637,23 @@ class Font {
header = readOpenTypeHeader(font);
tables = readTables(font, header.numTables);
}
let cff, cffFile;
const isTrueType = !tables["CFF "];
if (!isTrueType) {
const isComposite =
properties.composite &&
(properties.cidToGidMap?.length > 0 ||
!(properties.cMap instanceof IdentityCMap));
// OpenType font (skip composite fonts with non-default glyph mapping).
if (
(header.version === "OTTO" && !isComposite) ||
(header.version === "OTTO" && !properties.composite) ||
!tables.head ||
!tables.hhea ||
!tables.maxp ||
!tables.post
) {
// No major tables: throwing everything at `CFFFont`.
cffFile = new Stream(tables["CFF "].data);
cff = new CFFFont(cffFile, properties);
return this.convert(name, cff, properties);
return this.convert(
name,
new CFFFont(new Stream(tables["CFF "].data), properties),
properties
);
}
delete tables.glyf;
@ -2686,9 +2681,32 @@ class Font {
throw new FormatError('Required "maxp" table is not found');
}
let numGlyphsFromCFF;
if (!isTrueType) {
try {
// Trying to repair CFF file
const parser = new CFFParser(
new Stream(tables["CFF "].data),
properties,
SEAC_ANALYSIS_ENABLED
);
const cff = parser.parse();
cff.duplicateFirstGlyph();
const compiler = new CFFCompiler(cff);
tables["CFF "].data = compiler.compile();
numGlyphsFromCFF = cff.charStringCount;
} catch {
warn("Failed to compile font " + properties.loadedName);
}
}
font.pos = (font.start || 0) + tables.maxp.offset;
let version = font.getInt32();
const numGlyphs = font.getUint16();
const numGlyphs = numGlyphsFromCFF ?? font.getUint16();
if (version === 0x00005000 && tables.maxp.length !== 6) {
tables.maxp.data = tables.maxp.data.subarray(0, 6);
tables.maxp.length = 6;
}
if (version !== 0x00010000 && version !== 0x00005000) {
// https://learn.microsoft.com/en-us/typography/opentype/spec/maxp
@ -3099,24 +3117,6 @@ class Font {
}
}
if (!isTrueType) {
try {
// Trying to repair CFF file
cffFile = new Stream(tables["CFF "].data);
const parser = new CFFParser(
cffFile,
properties,
SEAC_ANALYSIS_ENABLED
);
cff = parser.parse();
cff.duplicateFirstGlyph();
const compiler = new CFFCompiler(cff);
tables["CFF "].data = compiler.compile();
} catch {
warn("Failed to compile font " + properties.loadedName);
}
}
// Re-creating 'name' table
if (!tables.name) {
tables.name = {

View File

@ -0,0 +1 @@
https://github.com/mozilla/pdf.js/files/15274065/1.pdf

View File

@ -13123,5 +13123,13 @@
"rounds": 1,
"link": true,
"type": "eq"
},
{
"id": "issue18062",
"file": "pdfs/issue18062.pdf",
"md5": "b8fb6d5622f0a2f45be8e26da7de969c",
"rounds": 1,
"link": true,
"type": "eq"
}
]