Skip to content

Commit

Permalink
Introduce helper functions for parsing /Matrix and /BBox arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
Snuffleupagus committed May 3, 2024
1 parent 0c08809 commit 14707f9
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 65 deletions.
41 changes: 15 additions & 26 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import {
getRotationMatrix,
isAscii,
isNumberArray,
lookupMatrix,
lookupRect,
numberToString,
stringToUTF16String,
} from "./core_utils.js";
Expand Down Expand Up @@ -915,9 +917,7 @@ class Annotation {
* @param {Array} rectangle - The rectangle array with exactly four entries
*/
setRectangle(rectangle) {
this.rectangle = isNumberArray(rectangle, 4)
? Util.normalizeRect(rectangle)
: [0, 0, 0, 0];
this.rectangle = lookupRect(rectangle, [0, 0, 0, 0]);
}

/**
Expand Down Expand Up @@ -1150,14 +1150,11 @@ class Annotation {
["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"],
appearance
);
let bbox = appearanceDict.getArray("BBox");
if (!isNumberArray(bbox, 4)) {
bbox = [0, 0, 1, 1];
}
let matrix = appearanceDict.getArray("Matrix");
if (!isNumberArray(matrix, 6)) {
matrix = [1, 0, 0, 1, 0, 0];
}
const bbox = lookupRect(appearanceDict.getArray("BBox"), [0, 0, 1, 1]);
const matrix = lookupMatrix(
appearanceDict.getArray("Matrix"),
IDENTITY_MATRIX
);
const transform = getTransformMatrix(rect, bbox, matrix);

const opList = new OperatorList();
Expand Down Expand Up @@ -1254,14 +1251,8 @@ class Annotation {

if (text.length > 1 || text[0]) {
const appearanceDict = this.appearance.dict;
let bbox = appearanceDict.getArray("BBox");
if (!isNumberArray(bbox, 4)) {
bbox = null;
}
let matrix = appearanceDict.getArray("Matrix");
if (!isNumberArray(matrix, 6)) {
matrix = null;
}
const bbox = lookupRect(appearanceDict.getArray("BBox"), null);
const matrix = lookupMatrix(appearanceDict.getArray("Matrix"), null);

this.data.textPosition = this._transformPoint(
firstPosition,
Expand Down Expand Up @@ -2987,8 +2978,10 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
: this.uncheckedAppearance;
if (appearance) {
const savedAppearance = this.appearance;
const matrix = appearance.dict.getArray("Matrix");
const savedMatrix = isNumberArray(matrix, 6) ? matrix : IDENTITY_MATRIX;
const savedMatrix = lookupMatrix(
appearance.dict.getArray("Matrix"),
IDENTITY_MATRIX
);

if (rotation) {
appearance.dict.set(
Expand Down Expand Up @@ -3753,11 +3746,7 @@ class PopupAnnotation extends Annotation {
warn("Popup annotation has a missing or invalid parent annotation.");
return;
}

const parentRect = parentItem.getArray("Rect");
this.data.parentRect = isNumberArray(parentRect, 4)
? Util.normalizeRect(parentRect)
: null;
this.data.parentRect = lookupRect(parentItem.getArray("Rect"), null);

const rt = parentItem.get("RT");
if (isName(rt, AnnotationReplyType.GROUP)) {
Expand Down
13 changes: 13 additions & 0 deletions src/core/core_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
BaseException,
objectSize,
stringToPDFString,
Util,
warn,
} from "../shared/util.js";
import { Dict, isName, Ref, RefSet } from "./primitives.js";
Expand Down Expand Up @@ -248,6 +249,16 @@ function isNumberArray(arr, len) {
);
}

// Returns the matrix, or the fallback value if it's invalid.
function lookupMatrix(arr, fallback) {
return isNumberArray(arr, 6) ? arr : fallback;
}

// Returns the normalized rectangle, or the fallback value if it's invalid.
function lookupRect(arr, fallback) {
return isNumberArray(arr, 4) ? Util.normalizeRect(arr) : fallback;
}

/**
* AcroForm field names use an array like notation to refer to
* repeated XFA elements e.g. foo.bar[nnn].
Expand Down Expand Up @@ -671,6 +682,8 @@ export {
isNumberArray,
isWhiteSpace,
log2,
lookupMatrix,
lookupRect,
MissingDataException,
numberToString,
ParserEOFException,
Expand Down
10 changes: 6 additions & 4 deletions src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ import {
collectActions,
getInheritableProperty,
getNewAnnotationsMap,
isNumberArray,
isWhiteSpace,
lookupRect,
MissingDataException,
PDF_VERSION_REGEXP,
validateCSSFont,
Expand Down Expand Up @@ -161,10 +161,12 @@ class Page {
if (this.xfaData) {
return this.xfaData.bbox;
}
let box = this._getInheritableProperty(name, /* getArray = */ true);
const box = lookupRect(
this._getInheritableProperty(name, /* getArray = */ true),
null
);

if (isNumberArray(box, 4)) {
box = Util.normalizeRect(box);
if (box) {
if (box[2] - box[0] > 0 && box[3] - box[1] > 0) {
return box;
}
Expand Down
40 changes: 15 additions & 25 deletions src/core/evaluator.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
import { getTilingPatternIR, Pattern } from "./pattern.js";
import { getXfaFontDict, getXfaFontName } from "./xfa_fonts.js";
import { IdentityToUnicodeMap, ToUnicodeMap } from "./to_unicode_map.js";
import { isNumberArray, lookupMatrix, lookupRect } from "./core_utils.js";
import { isPDFFunction, PDFFunctionFactory } from "./function.js";
import { Lexer, Parser } from "./parser.js";
import {
Expand All @@ -73,7 +74,6 @@ import { getGlyphsUnicode } from "./glyphlist.js";
import { getMetrics } from "./metrics.js";
import { getUnicodeForGlyph } from "./unicode.js";
import { ImageResizer } from "./image_resizer.js";
import { isNumberArray } from "./core_utils.js";
import { MurmurHash3_64 } from "../shared/murmurhash3.js";
import { OperatorList } from "./operator_list.js";
import { PDFImage } from "./image.js";
Expand Down Expand Up @@ -460,12 +460,8 @@ class PartialEvaluator {
localColorSpaceCache
) {
const dict = xobj.dict;
let matrix = dict.getArray("Matrix");
if (!isNumberArray(matrix, 6)) {
matrix = null;
}
let bbox = dict.getArray("BBox");
bbox = isNumberArray(bbox, 4) ? Util.normalizeRect(bbox) : null;
const matrix = lookupMatrix(dict.getArray("Matrix"), null);
const bbox = lookupRect(dict.getArray("BBox"), null);

let optionalContent, groupOptions;
if (dict.has("OC")) {
Expand Down Expand Up @@ -1578,10 +1574,7 @@ class PartialEvaluator {
localShadingPatternCache,
});
if (objId) {
let matrix = dict.getArray("Matrix");
if (!isNumberArray(matrix, 6)) {
matrix = null;
}
const matrix = lookupMatrix(dict.getArray("Matrix"), null);
operatorList.addOp(fn, ["Shading", objId, matrix]);
}
return undefined;
Expand Down Expand Up @@ -3268,8 +3261,8 @@ class PartialEvaluator {
const currentState = stateManager.state.clone();
const xObjStateManager = new StateManager(currentState);

const matrix = xobj.dict.getArray("Matrix");
if (isNumberArray(matrix, 6)) {
const matrix = lookupMatrix(xobj.dict.getArray("Matrix"), null);
if (matrix) {
xObjStateManager.transform(matrix);
}

Expand Down Expand Up @@ -4247,10 +4240,7 @@ class PartialEvaluator {

if (!descriptor) {
if (isType3Font) {
let bbox = dict.getArray("FontBBox");
if (!isNumberArray(bbox, 4)) {
bbox = [0, 0, 0, 0];
}
const bbox = lookupRect(dict.getArray("FontBBox"), [0, 0, 0, 0]);
// FontDescriptor is only required for Type3 fonts when the document
// is a tagged pdf. Create a barbebones one to get by.
descriptor = new Dict(null);
Expand Down Expand Up @@ -4440,14 +4430,14 @@ class PartialEvaluator {
}
}

let fontMatrix = dict.getArray("FontMatrix");
if (!isNumberArray(fontMatrix, 6)) {
fontMatrix = FONT_IDENTITY_MATRIX;
}
let bbox = descriptor.getArray("FontBBox") || dict.getArray("FontBBox");
if (!isNumberArray(bbox, 4)) {
bbox = undefined;
}
const fontMatrix = lookupMatrix(
dict.getArray("FontMatrix"),
FONT_IDENTITY_MATRIX
);
const bbox = lookupRect(
descriptor.getArray("FontBBox") || dict.getArray("FontBBox"),
undefined
);
let ascent = descriptor.get("Ascent");
if (typeof ascent !== "number") {
ascent = undefined;
Expand Down
16 changes: 6 additions & 10 deletions src/core/pattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
import {
isBooleanArray,
isNumberArray,
lookupMatrix,
lookupRect,
MissingDataException,
} from "./core_utils.js";
import { BaseStream } from "./base_stream.js";
Expand Down Expand Up @@ -128,8 +130,7 @@ class RadialAxialShading extends BaseShading {
pdfFunctionFactory,
localColorSpaceCache,
});
const bbox = dict.getArray("BBox");
this.bbox = isNumberArray(bbox, 4) ? Util.normalizeRect(bbox) : null;
this.bbox = lookupRect(dict.getArray("BBox"), null);

let t0 = 0.0,
t1 = 1.0;
Expand Down Expand Up @@ -460,8 +461,7 @@ class MeshShading extends BaseShading {
}
const dict = stream.dict;
this.shadingType = dict.get("ShadingType");
const bbox = dict.getArray("BBox");
this.bbox = isNumberArray(bbox, 4) ? Util.normalizeRect(bbox) : null;
this.bbox = lookupRect(dict.getArray("BBox"), null);
const cs = ColorSpace.parse({
cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"),
xref,
Expand Down Expand Up @@ -987,12 +987,8 @@ class DummyShading extends BaseShading {
}

function getTilingPatternIR(operatorList, dict, color) {
let matrix = dict.getArray("Matrix");
if (!isNumberArray(matrix, 6)) {
matrix = null;
}
let bbox = dict.getArray("BBox");
bbox = isNumberArray(bbox, 4) ? Util.normalizeRect(bbox) : null;
const matrix = lookupMatrix(dict.getArray("Matrix"), null);
const bbox = lookupRect(dict.getArray("BBox"), null);
// Ensure that the pattern has a non-zero width and height, to prevent errors
// in `pattern_helper.js` (fixes issue8330.pdf).
if (!bbox || bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) {
Expand Down

0 comments on commit 14707f9

Please sign in to comment.