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,
 | 
			
		||||
  objectSize,
 | 
			
		||||
  stringToPDFString,
 | 
			
		||||
  warn,
 | 
			
		||||
} from "../shared/util.js";
 | 
			
		||||
import { Dict, isName, isRef, isStream, RefSet } from "./primitives.js";
 | 
			
		||||
 | 
			
		||||
@ -376,6 +377,70 @@ function encodeToXmlString(str) {
 | 
			
		||||
  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 {
 | 
			
		||||
  collectActions,
 | 
			
		||||
  encodeToXmlString,
 | 
			
		||||
@ -391,6 +456,7 @@ export {
 | 
			
		||||
  readUint16,
 | 
			
		||||
  readUint32,
 | 
			
		||||
  toRomanNumerals,
 | 
			
		||||
  validateCSSFont,
 | 
			
		||||
  XRefEntryException,
 | 
			
		||||
  XRefParseException,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,7 @@ import {
 | 
			
		||||
  isName,
 | 
			
		||||
  isRef,
 | 
			
		||||
  isStream,
 | 
			
		||||
  Name,
 | 
			
		||||
  Ref,
 | 
			
		||||
} from "./primitives.js";
 | 
			
		||||
import {
 | 
			
		||||
@ -49,6 +50,7 @@ import {
 | 
			
		||||
  getInheritableProperty,
 | 
			
		||||
  isWhiteSpace,
 | 
			
		||||
  MissingDataException,
 | 
			
		||||
  validateCSSFont,
 | 
			
		||||
  XRefEntryException,
 | 
			
		||||
  XRefParseException,
 | 
			
		||||
} from "./core_utils.js";
 | 
			
		||||
@ -854,6 +856,71 @@ class PDFDocument {
 | 
			
		||||
    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() {
 | 
			
		||||
    const formInfo = {
 | 
			
		||||
      hasFields: false,
 | 
			
		||||
 | 
			
		||||
@ -792,12 +792,19 @@ class PartialEvaluator {
 | 
			
		||||
    operatorList,
 | 
			
		||||
    task,
 | 
			
		||||
    state,
 | 
			
		||||
    fallbackFontDict = null
 | 
			
		||||
    fallbackFontDict = null,
 | 
			
		||||
    cssFontInfo = null
 | 
			
		||||
  ) {
 | 
			
		||||
    const fontName =
 | 
			
		||||
      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 => {
 | 
			
		||||
        if (!translated.font.isType3Font) {
 | 
			
		||||
          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 () => {
 | 
			
		||||
      return new TranslatedFont({
 | 
			
		||||
        loadedName: "g_font_error",
 | 
			
		||||
@ -1055,6 +1068,7 @@ class PartialEvaluator {
 | 
			
		||||
    let preEvaluatedFont;
 | 
			
		||||
    try {
 | 
			
		||||
      preEvaluatedFont = this.preEvaluateFont(font);
 | 
			
		||||
      preEvaluatedFont.cssFontInfo = cssFontInfo;
 | 
			
		||||
    } catch (reason) {
 | 
			
		||||
      warn(`loadFont - preEvaluateFont failed: "${reason}".`);
 | 
			
		||||
      return errorFont();
 | 
			
		||||
@ -3529,6 +3543,7 @@ class PartialEvaluator {
 | 
			
		||||
      flags: descriptor.get("Flags"),
 | 
			
		||||
      italicAngle: descriptor.get("ItalicAngle"),
 | 
			
		||||
      isType3Font: false,
 | 
			
		||||
      cssFontInfo: preEvaluatedFont.cssFontInfo,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (composite) {
 | 
			
		||||
 | 
			
		||||
@ -95,6 +95,7 @@ const EXPORT_DATA_PROPERTIES = [
 | 
			
		||||
  "bold",
 | 
			
		||||
  "charProcOperatorList",
 | 
			
		||||
  "composite",
 | 
			
		||||
  "cssFontInfo",
 | 
			
		||||
  "data",
 | 
			
		||||
  "defaultVMetrics",
 | 
			
		||||
  "defaultWidth",
 | 
			
		||||
@ -565,6 +566,7 @@ var Font = (function FontClosure() {
 | 
			
		||||
    this.loadedName = properties.loadedName;
 | 
			
		||||
    this.isType3Font = properties.isType3Font;
 | 
			
		||||
    this.missingFile = false;
 | 
			
		||||
    this.cssFontInfo = properties.cssFontInfo;
 | 
			
		||||
 | 
			
		||||
    this.glyphCache = Object.create(null);
 | 
			
		||||
 | 
			
		||||
@ -2963,8 +2965,15 @@ var Font = (function FontClosure() {
 | 
			
		||||
        glyphZeroId = 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // When `cssFontInfo` is set, the font is used to render text in the HTML
 | 
			
		||||
      // view (e.g. with Xfa) so nothing must be moved in the private area use.
 | 
			
		||||
      if (!properties.cssFontInfo) {
 | 
			
		||||
        // Converting glyphs and ids into font's cmap table
 | 
			
		||||
      var newMapping = adjustMapping(charCodeToGlyphId, hasGlyph, glyphZeroId);
 | 
			
		||||
        var newMapping = adjustMapping(
 | 
			
		||||
          charCodeToGlyphId,
 | 
			
		||||
          hasGlyph,
 | 
			
		||||
          glyphZeroId
 | 
			
		||||
        );
 | 
			
		||||
        this.toFontChar = newMapping.toFontChar;
 | 
			
		||||
        tables.cmap = {
 | 
			
		||||
          tag: "cmap",
 | 
			
		||||
@ -2981,6 +2990,7 @@ var Font = (function FontClosure() {
 | 
			
		||||
            ),
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!isTrueType) {
 | 
			
		||||
        try {
 | 
			
		||||
 | 
			
		||||
@ -73,6 +73,10 @@ class BasePdfManager {
 | 
			
		||||
    return this.pdfDocument.fontFallback(id, handler);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadXfaFonts(handler, task) {
 | 
			
		||||
    return this.pdfDocument.loadXfaFonts(handler, task);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cleanup(manuallyTriggered = false) {
 | 
			
		||||
    return this.pdfDocument.cleanup(manuallyTriggered);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -193,6 +193,17 @@ class WorkerMessageHandler {
 | 
			
		||||
        pdfManager.ensureDoc("fingerprint"),
 | 
			
		||||
        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 };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -370,7 +370,22 @@ class FontFaceObject {
 | 
			
		||||
    if (!this.data || this.disableFontFace) {
 | 
			
		||||
      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) {
 | 
			
		||||
      this.fontRegistry.registerFont(this);
 | 
			
		||||
@ -385,7 +400,16 @@ class FontFaceObject {
 | 
			
		||||
    const data = bytesToString(new Uint8Array(this.data));
 | 
			
		||||
    // Add the @font-face rule to the document.
 | 
			
		||||
    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) {
 | 
			
		||||
      this.fontRegistry.registerFont(this, url);
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@ import {
 | 
			
		||||
  log2,
 | 
			
		||||
  parseXFAPath,
 | 
			
		||||
  toRomanNumerals,
 | 
			
		||||
  validateCSSFont,
 | 
			
		||||
} from "../../src/core/core_utils.js";
 | 
			
		||||
import { XRefMock } from "./test_utils.js";
 | 
			
		||||
 | 
			
		||||
@ -233,4 +234,103 @@ describe("core_utils", function () {
 | 
			
		||||
      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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user