1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-26 10:08:06 +02:00

XFA - Fix font scale factors (bug 1720888)

- All the scale factors in for the substitution font were wrong because of different glyph positions between Liberation and the other ones:
    - regenerate all the factors
  - Text may have polish chars for example and in this case the glyph widths were wrong:
    - treat substitution font as a composite one
    - add a map glyphIndex to unicode for Liberation in order to generate width array for cid font
This commit is contained in:
Calixte Denizet 2021-07-28 18:30:22 +02:00
parent ac5c4b7fd0
commit 4a4591bd2c
17 changed files with 1614 additions and 1248 deletions

View file

@ -23,6 +23,7 @@ import {
CalibriRegularFactors,
CalibriRegularMetrics,
} from "./calibri_factors.js";
import { Dict, Name } from "./primitives.js";
import {
HelveticaBoldFactors,
HelveticaBoldItalicFactors,
@ -34,9 +35,13 @@ import {
HelveticaRegularMetrics,
} from "./helvetica_factors.js";
import {
LiberationSansBoldItalicMapping,
LiberationSansBoldItalicWidths,
LiberationSansBoldMapping,
LiberationSansBoldWidths,
LiberationSansItalicMapping,
LiberationSansItalicWidths,
LiberationSansRegularMapping,
LiberationSansRegularWidths,
} from "./liberationsans_widths.js";
import {
@ -67,12 +72,14 @@ const getXFAFontMap = getLookupTableFactory(function (t) {
name: "LiberationSans-Regular",
factors: MyriadProRegularFactors,
baseWidths: LiberationSansRegularWidths,
baseMapping: LiberationSansRegularMapping,
metrics: MyriadProRegularMetrics,
};
t["MyriadPro-Bold"] = t["PdfJS-Fallback-Bold"] = {
name: "LiberationSans-Bold",
factors: MyriadProBoldFactors,
baseWidths: LiberationSansBoldWidths,
baseMapping: LiberationSansBoldMapping,
metrics: MyriadProBoldMetrics,
};
t["MyriadPro-It"] =
@ -82,6 +89,7 @@ const getXFAFontMap = getLookupTableFactory(function (t) {
name: "LiberationSans-Italic",
factors: MyriadProItalicFactors,
baseWidths: LiberationSansItalicWidths,
baseMapping: LiberationSansItalicMapping,
metrics: MyriadProItalicMetrics,
};
t["MyriadPro-BoldIt"] =
@ -91,6 +99,7 @@ const getXFAFontMap = getLookupTableFactory(function (t) {
name: "LiberationSans-BoldItalic",
factors: MyriadProBoldItalicFactors,
baseWidths: LiberationSansBoldItalicWidths,
baseMapping: LiberationSansBoldItalicMapping,
metrics: MyriadProBoldItalicMetrics,
};
t.ArialMT =
@ -99,89 +108,105 @@ const getXFAFontMap = getLookupTableFactory(function (t) {
{
name: "LiberationSans-Regular",
baseWidths: LiberationSansRegularWidths,
baseMapping: LiberationSansRegularMapping,
};
t["Arial-BoldMT"] = t["Arial-Bold"] = {
name: "LiberationSans-Bold",
baseWidths: LiberationSansBoldWidths,
baseMapping: LiberationSansBoldMapping,
};
t["Arial-ItalicMT"] = t["Arial-Italic"] = {
name: "LiberationSans-Italic",
baseWidths: LiberationSansItalicWidths,
baseMapping: LiberationSansItalicMapping,
};
t["Arial-BoldItalicMT"] = t["Arial-BoldItalic"] = {
name: "LiberationSans-BoldItalic",
baseWidths: LiberationSansBoldItalicWidths,
baseMapping: LiberationSansBoldItalicMapping,
};
t["Calibri-Regular"] = {
name: "LiberationSans-Regular",
factors: CalibriRegularFactors,
baseWidths: LiberationSansRegularWidths,
baseMapping: LiberationSansRegularMapping,
metrics: CalibriRegularMetrics,
};
t["Calibri-Bold"] = {
name: "LiberationSans-Bold",
factors: CalibriBoldFactors,
baseWidths: LiberationSansBoldWidths,
baseMapping: LiberationSansBoldMapping,
metrics: CalibriBoldMetrics,
};
t["Calibri-Italic"] = {
name: "LiberationSans-Italic",
factors: CalibriItalicFactors,
baseWidths: LiberationSansItalicWidths,
baseMapping: LiberationSansItalicMapping,
metrics: CalibriItalicMetrics,
};
t["Calibri-BoldItalic"] = {
name: "LiberationSans-BoldItalic",
factors: CalibriBoldItalicFactors,
baseWidths: LiberationSansBoldItalicWidths,
baseMapping: LiberationSansBoldItalicMapping,
metrics: CalibriBoldItalicMetrics,
};
t["Segoeui-Regular"] = {
name: "LiberationSans-Regular",
factors: SegoeuiRegularFactors,
baseWidths: LiberationSansRegularWidths,
baseMapping: LiberationSansRegularMapping,
metrics: SegoeuiRegularMetrics,
};
t["Segoeui-Bold"] = {
name: "LiberationSans-Bold",
factors: SegoeuiBoldFactors,
baseWidths: LiberationSansBoldWidths,
baseMapping: LiberationSansBoldMapping,
metrics: SegoeuiBoldMetrics,
};
t["Segoeui-Italic"] = {
name: "LiberationSans-Italic",
factors: SegoeuiItalicFactors,
baseWidths: LiberationSansItalicWidths,
baseMapping: LiberationSansItalicMapping,
metrics: SegoeuiItalicMetrics,
};
t["Segoeui-BoldItalic"] = {
name: "LiberationSans-BoldItalic",
factors: SegoeuiBoldItalicFactors,
baseWidths: LiberationSansBoldItalicWidths,
baseMapping: LiberationSansBoldItalicMapping,
metrics: SegoeuiBoldItalicMetrics,
};
t["Helvetica-Regular"] = t.Helvetica = {
name: "LiberationSans-Regular",
factors: HelveticaRegularFactors,
baseWidths: LiberationSansRegularWidths,
baseMapping: LiberationSansRegularMapping,
metrics: HelveticaRegularMetrics,
};
t["Helvetica-Bold"] = {
name: "LiberationSans-Bold",
factors: HelveticaBoldFactors,
baseWidths: LiberationSansBoldWidths,
baseMapping: LiberationSansBoldMapping,
metrics: HelveticaBoldMetrics,
};
t["Helvetica-Italic"] = {
name: "LiberationSans-Italic",
factors: HelveticaItalicFactors,
baseWidths: LiberationSansItalicWidths,
baseMapping: LiberationSansItalicMapping,
metrics: HelveticaItalicMetrics,
};
t["Helvetica-BoldItalic"] = {
name: "LiberationSans-BoldItalic",
factors: HelveticaBoldItalicFactors,
baseWidths: LiberationSansBoldItalicWidths,
baseMapping: LiberationSansBoldItalicMapping,
metrics: HelveticaBoldItalicMetrics,
};
});
@ -198,11 +223,80 @@ function getXfaFontWidths(name) {
return null;
}
const { baseWidths, factors } = info;
const { baseWidths, baseMapping, factors } = info;
let rescaledBaseWidths;
if (!factors) {
return baseWidths;
rescaledBaseWidths = baseWidths;
} else {
rescaledBaseWidths = baseWidths.map((w, i) => w * factors[i]);
}
return baseWidths.map((w, i) => w * factors[i]);
let currentCode = -2;
let currentArray;
// Widths array for composite font is:
// CharCode1 [10, 20, 30] ...
// which means:
// - CharCode1 has a width equal to 10
// - CharCode1+1 has a width equal to 20
// - CharCode1+2 has a width equal to 30
//
// The baseMapping array contains a map for glyph index to unicode.
// So from baseMapping we'll get sorted unicodes and their positions
// (i.e. glyph indices) and then we put widths in an array for the
// the consecutive unicodes.
const newWidths = [];
for (const [unicode, glyphIndex] of baseMapping
.map(
(charUnicode, index) => [
charUnicode,
index,
] /* collect unicode and glyph index */
)
.sort(
([unicode1], [unicode2]) =>
unicode1 - unicode2 /* order by unicode only */
)) {
if (unicode === -1) {
continue;
}
if (unicode === currentCode + 1) {
currentArray.push(rescaledBaseWidths[glyphIndex]);
currentCode += 1;
} else {
currentCode = unicode;
currentArray = [rescaledBaseWidths[glyphIndex]];
newWidths.push(unicode, currentArray);
}
}
return newWidths;
}
export { getXfaFontName, getXfaFontWidths };
function getXfaFontDict(name) {
const widths = getXfaFontWidths(name);
const dict = new Dict(null);
dict.set("BaseFont", Name.get(name));
dict.set("Type", Name.get("Font"));
dict.set("Subtype", Name.get("CIDFontType2"));
dict.set("Encoding", Name.get("Identity-H"));
dict.set("CIDToGIDMap", Name.get("Identity"));
dict.set("W", widths);
dict.set("FirstChar", widths[0]);
dict.set(
"LastChar",
widths[widths.length - 2] + widths[widths.length - 1].length - 1
);
const descriptor = new Dict(null);
dict.set("FontDescriptor", descriptor);
const systemInfo = new Dict(null);
systemInfo.set("Ordering", "Identity");
systemInfo.set("Registry", "Adobe");
systemInfo.set("Supplement", 0);
dict.set("CIDSystemInfo", systemInfo);
return dict;
}
export { getXfaFontDict, getXfaFontName };