XFA -- Load fonts permanently from the pdf
- Different fonts can be used in xfa and some of them are embedded in the pdf. - Load all the fonts in window.document. Update src/core/document.js Co-authored-by: Jonas Jenwald <jonas.jenwald@gmail.com> Update src/core/worker.js Co-authored-by: Jonas Jenwald <jonas.jenwald@gmail.com>
This commit is contained in:
parent
6cf3070008
commit
7e9579045f
@ -19,6 +19,7 @@ import {
|
|||||||
bytesToString,
|
bytesToString,
|
||||||
objectSize,
|
objectSize,
|
||||||
stringToPDFString,
|
stringToPDFString,
|
||||||
|
warn,
|
||||||
} from "../shared/util.js";
|
} from "../shared/util.js";
|
||||||
import { Dict, isName, isRef, isStream, RefSet } from "./primitives.js";
|
import { Dict, isName, isRef, isStream, RefSet } from "./primitives.js";
|
||||||
|
|
||||||
@ -376,6 +377,70 @@ function encodeToXmlString(str) {
|
|||||||
return buffer.join("");
|
return buffer.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateCSSFont(cssFontInfo) {
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/CSS/font-style.
|
||||||
|
const DEFAULT_CSS_FONT_OBLIQUE = "14";
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight.
|
||||||
|
const DEFAULT_CSS_FONT_WEIGHT = "400";
|
||||||
|
const CSS_FONT_WEIGHT_VALUES = new Set([
|
||||||
|
"100",
|
||||||
|
"200",
|
||||||
|
"300",
|
||||||
|
"400",
|
||||||
|
"500",
|
||||||
|
"600",
|
||||||
|
"700",
|
||||||
|
"800",
|
||||||
|
"900",
|
||||||
|
"1000",
|
||||||
|
"normal",
|
||||||
|
"bold",
|
||||||
|
"bolder",
|
||||||
|
"lighter",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const { fontFamily, fontWeight, italicAngle } = cssFontInfo;
|
||||||
|
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/CSS/string.
|
||||||
|
if (/^".*"$/.test(fontFamily)) {
|
||||||
|
if (/[^\\]"/.test(fontFamily.slice(1, fontFamily.length - 1))) {
|
||||||
|
warn(`XFA - FontFamily contains some unescaped ": ${fontFamily}.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (/^'.*'$/.test(fontFamily)) {
|
||||||
|
if (/[^\\]'/.test(fontFamily.slice(1, fontFamily.length - 1))) {
|
||||||
|
warn(`XFA - FontFamily contains some unescaped ': ${fontFamily}.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident.
|
||||||
|
for (const ident of fontFamily.split(/[ \t]+/)) {
|
||||||
|
if (
|
||||||
|
/^([0-9]|(-([0-9]|-)))/.test(ident) ||
|
||||||
|
!/^[a-zA-Z0-9\-_\\]+$/.test(ident)
|
||||||
|
) {
|
||||||
|
warn(
|
||||||
|
`XFA - FontFamily contains some invalid <custom-ident>: ${fontFamily}.`
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const weight = fontWeight ? fontWeight.toString() : "";
|
||||||
|
cssFontInfo.fontWeight = CSS_FONT_WEIGHT_VALUES.has(weight)
|
||||||
|
? weight
|
||||||
|
: DEFAULT_CSS_FONT_WEIGHT;
|
||||||
|
|
||||||
|
const angle = parseFloat(italicAngle);
|
||||||
|
cssFontInfo.italicAngle =
|
||||||
|
isNaN(angle) || angle < -90 || angle > 90
|
||||||
|
? DEFAULT_CSS_FONT_OBLIQUE
|
||||||
|
: italicAngle.toString();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
collectActions,
|
collectActions,
|
||||||
encodeToXmlString,
|
encodeToXmlString,
|
||||||
@ -391,6 +456,7 @@ export {
|
|||||||
readUint16,
|
readUint16,
|
||||||
readUint32,
|
readUint32,
|
||||||
toRomanNumerals,
|
toRomanNumerals,
|
||||||
|
validateCSSFont,
|
||||||
XRefEntryException,
|
XRefEntryException,
|
||||||
XRefParseException,
|
XRefParseException,
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,7 @@ import {
|
|||||||
isName,
|
isName,
|
||||||
isRef,
|
isRef,
|
||||||
isStream,
|
isStream,
|
||||||
|
Name,
|
||||||
Ref,
|
Ref,
|
||||||
} from "./primitives.js";
|
} from "./primitives.js";
|
||||||
import {
|
import {
|
||||||
@ -49,6 +50,7 @@ import {
|
|||||||
getInheritableProperty,
|
getInheritableProperty,
|
||||||
isWhiteSpace,
|
isWhiteSpace,
|
||||||
MissingDataException,
|
MissingDataException,
|
||||||
|
validateCSSFont,
|
||||||
XRefEntryException,
|
XRefEntryException,
|
||||||
XRefParseException,
|
XRefParseException,
|
||||||
} from "./core_utils.js";
|
} from "./core_utils.js";
|
||||||
@ -854,6 +856,71 @@ class PDFDocument {
|
|||||||
return this.xfaFactory !== null;
|
return this.xfaFactory !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async loadXfaFonts(handler, task) {
|
||||||
|
const acroForm = await this.pdfManager.ensureCatalog("acroForm");
|
||||||
|
|
||||||
|
const resources = await acroForm.getAsync("DR");
|
||||||
|
if (!(resources instanceof Dict)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const objectLoader = new ObjectLoader(resources, ["Font"], this.xref);
|
||||||
|
await objectLoader.load();
|
||||||
|
|
||||||
|
const fontRes = resources.get("Font");
|
||||||
|
if (!(fontRes instanceof Dict)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const partialEvaluator = new PartialEvaluator({
|
||||||
|
xref: this.xref,
|
||||||
|
handler,
|
||||||
|
pageIndex: -1,
|
||||||
|
idFactory: this._globalIdFactory,
|
||||||
|
fontCache: this.catalog.fontCache,
|
||||||
|
builtInCMapCache: this.catalog.builtInCMapCache,
|
||||||
|
});
|
||||||
|
const operatorList = new OperatorList();
|
||||||
|
const initialState = {
|
||||||
|
font: null,
|
||||||
|
clone() {
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const fonts = new Map();
|
||||||
|
fontRes.forEach((fontName, font) => {
|
||||||
|
fonts.set(fontName, font);
|
||||||
|
});
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
for (const [fontName, font] of fonts) {
|
||||||
|
const descriptor = font.get("FontDescriptor");
|
||||||
|
if (descriptor instanceof Dict) {
|
||||||
|
const fontFamily = descriptor.get("FontFamily");
|
||||||
|
const fontWeight = descriptor.get("FontWeight");
|
||||||
|
const italicAngle = descriptor.get("ItalicAngle");
|
||||||
|
const cssFontInfo = { fontFamily, fontWeight, italicAngle };
|
||||||
|
|
||||||
|
if (!validateCSSFont(cssFontInfo)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const promise = partialEvaluator.handleSetFont(
|
||||||
|
resources,
|
||||||
|
[Name.get(fontName), 1],
|
||||||
|
/* fontRef = */ null,
|
||||||
|
operatorList,
|
||||||
|
task,
|
||||||
|
initialState,
|
||||||
|
/* fallbackFontDict = */ null,
|
||||||
|
/* cssFontInfo = */ cssFontInfo
|
||||||
|
);
|
||||||
|
promises.push(promise.catch(() => {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
get formInfo() {
|
get formInfo() {
|
||||||
const formInfo = {
|
const formInfo = {
|
||||||
hasFields: false,
|
hasFields: false,
|
||||||
|
@ -792,12 +792,19 @@ class PartialEvaluator {
|
|||||||
operatorList,
|
operatorList,
|
||||||
task,
|
task,
|
||||||
state,
|
state,
|
||||||
fallbackFontDict = null
|
fallbackFontDict = null,
|
||||||
|
cssFontInfo = null
|
||||||
) {
|
) {
|
||||||
const fontName =
|
const fontName =
|
||||||
fontArgs && fontArgs[0] instanceof Name ? fontArgs[0].name : null;
|
fontArgs && fontArgs[0] instanceof Name ? fontArgs[0].name : null;
|
||||||
|
|
||||||
return this.loadFont(fontName, fontRef, resources, fallbackFontDict)
|
return this.loadFont(
|
||||||
|
fontName,
|
||||||
|
fontRef,
|
||||||
|
resources,
|
||||||
|
fallbackFontDict,
|
||||||
|
cssFontInfo
|
||||||
|
)
|
||||||
.then(translated => {
|
.then(translated => {
|
||||||
if (!translated.font.isType3Font) {
|
if (!translated.font.isType3Font) {
|
||||||
return translated;
|
return translated;
|
||||||
@ -986,7 +993,13 @@ class PartialEvaluator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFont(fontName, font, resources, fallbackFontDict = null) {
|
loadFont(
|
||||||
|
fontName,
|
||||||
|
font,
|
||||||
|
resources,
|
||||||
|
fallbackFontDict = null,
|
||||||
|
cssFontInfo = null
|
||||||
|
) {
|
||||||
const errorFont = async () => {
|
const errorFont = async () => {
|
||||||
return new TranslatedFont({
|
return new TranslatedFont({
|
||||||
loadedName: "g_font_error",
|
loadedName: "g_font_error",
|
||||||
@ -1055,6 +1068,7 @@ class PartialEvaluator {
|
|||||||
let preEvaluatedFont;
|
let preEvaluatedFont;
|
||||||
try {
|
try {
|
||||||
preEvaluatedFont = this.preEvaluateFont(font);
|
preEvaluatedFont = this.preEvaluateFont(font);
|
||||||
|
preEvaluatedFont.cssFontInfo = cssFontInfo;
|
||||||
} catch (reason) {
|
} catch (reason) {
|
||||||
warn(`loadFont - preEvaluateFont failed: "${reason}".`);
|
warn(`loadFont - preEvaluateFont failed: "${reason}".`);
|
||||||
return errorFont();
|
return errorFont();
|
||||||
@ -3529,6 +3543,7 @@ class PartialEvaluator {
|
|||||||
flags: descriptor.get("Flags"),
|
flags: descriptor.get("Flags"),
|
||||||
italicAngle: descriptor.get("ItalicAngle"),
|
italicAngle: descriptor.get("ItalicAngle"),
|
||||||
isType3Font: false,
|
isType3Font: false,
|
||||||
|
cssFontInfo: preEvaluatedFont.cssFontInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (composite) {
|
if (composite) {
|
||||||
|
@ -95,6 +95,7 @@ const EXPORT_DATA_PROPERTIES = [
|
|||||||
"bold",
|
"bold",
|
||||||
"charProcOperatorList",
|
"charProcOperatorList",
|
||||||
"composite",
|
"composite",
|
||||||
|
"cssFontInfo",
|
||||||
"data",
|
"data",
|
||||||
"defaultVMetrics",
|
"defaultVMetrics",
|
||||||
"defaultWidth",
|
"defaultWidth",
|
||||||
@ -565,6 +566,7 @@ var Font = (function FontClosure() {
|
|||||||
this.loadedName = properties.loadedName;
|
this.loadedName = properties.loadedName;
|
||||||
this.isType3Font = properties.isType3Font;
|
this.isType3Font = properties.isType3Font;
|
||||||
this.missingFile = false;
|
this.missingFile = false;
|
||||||
|
this.cssFontInfo = properties.cssFontInfo;
|
||||||
|
|
||||||
this.glyphCache = Object.create(null);
|
this.glyphCache = Object.create(null);
|
||||||
|
|
||||||
@ -2963,23 +2965,31 @@ var Font = (function FontClosure() {
|
|||||||
glyphZeroId = 0;
|
glyphZeroId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converting glyphs and ids into font's cmap table
|
// When `cssFontInfo` is set, the font is used to render text in the HTML
|
||||||
var newMapping = adjustMapping(charCodeToGlyphId, hasGlyph, glyphZeroId);
|
// view (e.g. with Xfa) so nothing must be moved in the private area use.
|
||||||
this.toFontChar = newMapping.toFontChar;
|
if (!properties.cssFontInfo) {
|
||||||
tables.cmap = {
|
// Converting glyphs and ids into font's cmap table
|
||||||
tag: "cmap",
|
var newMapping = adjustMapping(
|
||||||
data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphsOut),
|
charCodeToGlyphId,
|
||||||
};
|
hasGlyph,
|
||||||
|
glyphZeroId
|
||||||
if (!tables["OS/2"] || !validateOS2Table(tables["OS/2"], font)) {
|
);
|
||||||
tables["OS/2"] = {
|
this.toFontChar = newMapping.toFontChar;
|
||||||
tag: "OS/2",
|
tables.cmap = {
|
||||||
data: createOS2Table(
|
tag: "cmap",
|
||||||
properties,
|
data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphsOut),
|
||||||
newMapping.charCodeToGlyphId,
|
|
||||||
metricsOverride
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!tables["OS/2"] || !validateOS2Table(tables["OS/2"], font)) {
|
||||||
|
tables["OS/2"] = {
|
||||||
|
tag: "OS/2",
|
||||||
|
data: createOS2Table(
|
||||||
|
properties,
|
||||||
|
newMapping.charCodeToGlyphId,
|
||||||
|
metricsOverride
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isTrueType) {
|
if (!isTrueType) {
|
||||||
|
@ -73,6 +73,10 @@ class BasePdfManager {
|
|||||||
return this.pdfDocument.fontFallback(id, handler);
|
return this.pdfDocument.fontFallback(id, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadXfaFonts(handler, task) {
|
||||||
|
return this.pdfDocument.loadXfaFonts(handler, task);
|
||||||
|
}
|
||||||
|
|
||||||
cleanup(manuallyTriggered = false) {
|
cleanup(manuallyTriggered = false) {
|
||||||
return this.pdfDocument.cleanup(manuallyTriggered);
|
return this.pdfDocument.cleanup(manuallyTriggered);
|
||||||
}
|
}
|
||||||
|
@ -193,6 +193,17 @@ class WorkerMessageHandler {
|
|||||||
pdfManager.ensureDoc("fingerprint"),
|
pdfManager.ensureDoc("fingerprint"),
|
||||||
pdfManager.ensureDoc("isPureXfa"),
|
pdfManager.ensureDoc("isPureXfa"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (isPureXfa) {
|
||||||
|
const task = new WorkerTask("Load fonts for Xfa");
|
||||||
|
startWorkerTask(task);
|
||||||
|
await pdfManager
|
||||||
|
.loadXfaFonts(handler, task)
|
||||||
|
.catch(reason => {
|
||||||
|
// Ignore errors, to allow the document to load.
|
||||||
|
})
|
||||||
|
.then(() => finishWorkerTask(task));
|
||||||
|
}
|
||||||
return { numPages, fingerprint, isPureXfa };
|
return { numPages, fingerprint, isPureXfa };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +370,22 @@ class FontFaceObject {
|
|||||||
if (!this.data || this.disableFontFace) {
|
if (!this.data || this.disableFontFace) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const nativeFontFace = new FontFace(this.loadedName, this.data, {});
|
let nativeFontFace;
|
||||||
|
if (!this.cssFontInfo) {
|
||||||
|
nativeFontFace = new FontFace(this.loadedName, this.data, {});
|
||||||
|
} else {
|
||||||
|
const css = {
|
||||||
|
weight: this.cssFontInfo.fontWeight,
|
||||||
|
};
|
||||||
|
if (this.cssFontInfo.italicAngle) {
|
||||||
|
css.style = `oblique ${this.cssFontInfo.italicAngle}deg`;
|
||||||
|
}
|
||||||
|
nativeFontFace = new FontFace(
|
||||||
|
this.cssFontInfo.fontFamily,
|
||||||
|
this.data,
|
||||||
|
css
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.fontRegistry) {
|
if (this.fontRegistry) {
|
||||||
this.fontRegistry.registerFont(this);
|
this.fontRegistry.registerFont(this);
|
||||||
@ -385,7 +400,16 @@ class FontFaceObject {
|
|||||||
const data = bytesToString(new Uint8Array(this.data));
|
const data = bytesToString(new Uint8Array(this.data));
|
||||||
// Add the @font-face rule to the document.
|
// Add the @font-face rule to the document.
|
||||||
const url = `url(data:${this.mimetype};base64,${btoa(data)});`;
|
const url = `url(data:${this.mimetype};base64,${btoa(data)});`;
|
||||||
const rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`;
|
let rule;
|
||||||
|
if (!this.cssFontInfo) {
|
||||||
|
rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`;
|
||||||
|
} else {
|
||||||
|
let css = `font-weight: ${this.cssFontInfo.fontWeight};`;
|
||||||
|
if (this.cssFontInfo.italicAngle) {
|
||||||
|
css += `font-style: oblique ${this.cssFontInfo.italicAngle}deg;`;
|
||||||
|
}
|
||||||
|
rule = `@font-face {font-family:"${this.cssFontInfo.fontFamily}";${css}src:${url}}`;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.fontRegistry) {
|
if (this.fontRegistry) {
|
||||||
this.fontRegistry.registerFont(this, url);
|
this.fontRegistry.registerFont(this, url);
|
||||||
|
@ -22,6 +22,7 @@ import {
|
|||||||
log2,
|
log2,
|
||||||
parseXFAPath,
|
parseXFAPath,
|
||||||
toRomanNumerals,
|
toRomanNumerals,
|
||||||
|
validateCSSFont,
|
||||||
} from "../../src/core/core_utils.js";
|
} from "../../src/core/core_utils.js";
|
||||||
import { XRefMock } from "./test_utils.js";
|
import { XRefMock } from "./test_utils.js";
|
||||||
|
|
||||||
@ -233,4 +234,103 @@ describe("core_utils", function () {
|
|||||||
expect(encodeToXmlString(str)).toEqual(str);
|
expect(encodeToXmlString(str)).toEqual(str);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("validateCSSFont", function () {
|
||||||
|
it("Check font family", function () {
|
||||||
|
const cssFontInfo = {
|
||||||
|
fontFamily: `"blah blah " blah blah"`,
|
||||||
|
fontWeight: 0,
|
||||||
|
italicAngle: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = `"blah blah \\" blah blah"`;
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(true);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = `'blah blah ' blah blah'`;
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = `'blah blah \\' blah blah'`;
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(true);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = `"blah blah `;
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = `blah blah"`;
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = `'blah blah `;
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = `blah blah'`;
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = "blah blah blah";
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(true);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = "blah 0blah blah";
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = "blah blah -0blah";
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = "blah blah --blah";
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = "blah blah -blah";
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(true);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = "blah fdqAJqjHJK23kl23__--Kj blah";
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(true);
|
||||||
|
|
||||||
|
cssFontInfo.fontFamily = "blah fdqAJqjH$JK23kl23__--Kj blah";
|
||||||
|
expect(validateCSSFont(cssFontInfo)).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Check font weight", function () {
|
||||||
|
const cssFontInfo = {
|
||||||
|
fontFamily: "blah",
|
||||||
|
fontWeight: 100,
|
||||||
|
italicAngle: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
validateCSSFont(cssFontInfo);
|
||||||
|
expect(cssFontInfo.fontWeight).toEqual("100");
|
||||||
|
|
||||||
|
cssFontInfo.fontWeight = "700";
|
||||||
|
validateCSSFont(cssFontInfo);
|
||||||
|
expect(cssFontInfo.fontWeight).toEqual("700");
|
||||||
|
|
||||||
|
cssFontInfo.fontWeight = "normal";
|
||||||
|
validateCSSFont(cssFontInfo);
|
||||||
|
expect(cssFontInfo.fontWeight).toEqual("normal");
|
||||||
|
|
||||||
|
cssFontInfo.fontWeight = 314;
|
||||||
|
validateCSSFont(cssFontInfo);
|
||||||
|
expect(cssFontInfo.fontWeight).toEqual("400");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Check italic angle", function () {
|
||||||
|
const cssFontInfo = {
|
||||||
|
fontFamily: "blah",
|
||||||
|
fontWeight: 100,
|
||||||
|
italicAngle: 10,
|
||||||
|
};
|
||||||
|
validateCSSFont(cssFontInfo);
|
||||||
|
expect(cssFontInfo.italicAngle).toEqual("10");
|
||||||
|
|
||||||
|
cssFontInfo.italicAngle = -123;
|
||||||
|
validateCSSFont(cssFontInfo);
|
||||||
|
expect(cssFontInfo.italicAngle).toEqual("14");
|
||||||
|
|
||||||
|
cssFontInfo.italicAngle = "91";
|
||||||
|
validateCSSFont(cssFontInfo);
|
||||||
|
expect(cssFontInfo.italicAngle).toEqual("14");
|
||||||
|
|
||||||
|
cssFontInfo.italicAngle = 2.718;
|
||||||
|
validateCSSFont(cssFontInfo);
|
||||||
|
expect(cssFontInfo.italicAngle).toEqual("2.718");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user