mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
[api-minor] Simplify how the list of points are structured
Instead of sending to the main thread an array of Objects for a list of points (or quadpoints), we'll send just a basic float buffer. It should slightly improve performances (especially when cloning the data) and use slightly less memory.
This commit is contained in:
parent
24e12d515d
commit
6fa98ac99f
5 changed files with 162 additions and 202 deletions
|
@ -561,24 +561,16 @@ function getQuadPoints(dict, rect) {
|
|||
return null;
|
||||
}
|
||||
|
||||
const quadPointsLists = [];
|
||||
for (let i = 0, ii = quadPoints.length / 8; i < ii; i++) {
|
||||
const newQuadPoints = new Float32Array(quadPoints.length);
|
||||
for (let i = 0, ii = quadPoints.length; i < ii; i += 8) {
|
||||
// Each series of eight numbers represents the coordinates for one
|
||||
// quadrilateral in the order [x1, y1, x2, y2, x3, y3, x4, y4].
|
||||
// Convert this to an array of objects with x and y coordinates.
|
||||
let minX = Infinity,
|
||||
maxX = -Infinity,
|
||||
minY = Infinity,
|
||||
maxY = -Infinity;
|
||||
for (let j = i * 8, jj = i * 8 + 8; j < jj; j += 2) {
|
||||
const x = quadPoints[j];
|
||||
const y = quadPoints[j + 1];
|
||||
|
||||
minX = Math.min(x, minX);
|
||||
maxX = Math.max(x, maxX);
|
||||
minY = Math.min(y, minY);
|
||||
maxY = Math.max(y, maxY);
|
||||
}
|
||||
const [x1, y1, x2, y2, x3, y3, x4, y4] = quadPoints.slice(i, i + 8);
|
||||
const minX = Math.min(x1, x2, x3, x4);
|
||||
const maxX = Math.max(x1, x2, x3, x4);
|
||||
const minY = Math.min(y1, y2, y3, y4);
|
||||
const maxY = Math.max(y1, y2, y3, y4);
|
||||
// The quadpoints should be ignored if any coordinate in the array
|
||||
// lies outside the region specified by the rectangle. The rectangle
|
||||
// can be `null` for markup annotations since their rectangle may be
|
||||
|
@ -601,14 +593,9 @@ function getQuadPoints(dict, rect) {
|
|||
// top right, bottom right and bottom left. To avoid inconsistency and
|
||||
// broken rendering, we normalize all lists to put the quadpoints in the
|
||||
// same standard order (see https://stackoverflow.com/a/10729881).
|
||||
quadPointsLists.push([
|
||||
{ x: minX, y: maxY },
|
||||
{ x: maxX, y: maxY },
|
||||
{ x: minX, y: minY },
|
||||
{ x: maxX, y: minY },
|
||||
]);
|
||||
newQuadPoints.set([minX, maxY, maxX, maxY, minX, minY, maxX, minY], i);
|
||||
}
|
||||
return quadPointsLists;
|
||||
return newQuadPoints;
|
||||
}
|
||||
|
||||
function getTransformMatrix(rect, bbox, matrix) {
|
||||
|
@ -1661,18 +1648,23 @@ class MarkupAnnotation extends Annotation {
|
|||
// If there are no quadpoints, the rectangle should be used instead.
|
||||
// Convert the rectangle definition to a points array similar to how the
|
||||
// quadpoints are defined.
|
||||
pointsArray = [
|
||||
[
|
||||
{ x: this.rectangle[0], y: this.rectangle[3] },
|
||||
{ x: this.rectangle[2], y: this.rectangle[3] },
|
||||
{ x: this.rectangle[0], y: this.rectangle[1] },
|
||||
{ x: this.rectangle[2], y: this.rectangle[1] },
|
||||
],
|
||||
];
|
||||
pointsArray = Float32Array.from([
|
||||
this.rectangle[0],
|
||||
this.rectangle[3],
|
||||
this.rectangle[2],
|
||||
this.rectangle[3],
|
||||
this.rectangle[0],
|
||||
this.rectangle[1],
|
||||
this.rectangle[2],
|
||||
this.rectangle[1],
|
||||
]);
|
||||
}
|
||||
|
||||
for (const points of pointsArray) {
|
||||
const [mX, MX, mY, MY] = pointsCallback(buffer, points);
|
||||
for (let i = 0, ii = pointsArray.length; i < ii; i += 8) {
|
||||
const [mX, MX, mY, MY] = pointsCallback(
|
||||
buffer,
|
||||
pointsArray.subarray(i, i + 8)
|
||||
);
|
||||
minX = Math.min(minX, mX);
|
||||
maxX = Math.max(maxX, MX);
|
||||
minY = Math.min(minY, mY);
|
||||
|
@ -4083,10 +4075,10 @@ class LineAnnotation extends MarkupAnnotation {
|
|||
"S"
|
||||
);
|
||||
return [
|
||||
points[0].x - borderWidth,
|
||||
points[1].x + borderWidth,
|
||||
points[3].y - borderWidth,
|
||||
points[1].y + borderWidth,
|
||||
points[0] - borderWidth,
|
||||
points[2] + borderWidth,
|
||||
points[7] - borderWidth,
|
||||
points[3] + borderWidth,
|
||||
];
|
||||
},
|
||||
});
|
||||
|
@ -4126,17 +4118,17 @@ class SquareAnnotation extends MarkupAnnotation {
|
|||
strokeAlpha,
|
||||
fillAlpha,
|
||||
pointsCallback: (buffer, points) => {
|
||||
const x = points[2].x + this.borderStyle.width / 2;
|
||||
const y = points[2].y + this.borderStyle.width / 2;
|
||||
const width = points[3].x - points[2].x - this.borderStyle.width;
|
||||
const height = points[1].y - points[3].y - this.borderStyle.width;
|
||||
const x = points[4] + this.borderStyle.width / 2;
|
||||
const y = points[5] + this.borderStyle.width / 2;
|
||||
const width = points[6] - points[4] - this.borderStyle.width;
|
||||
const height = points[3] - points[7] - this.borderStyle.width;
|
||||
buffer.push(`${x} ${y} ${width} ${height} re`);
|
||||
if (fillColor) {
|
||||
buffer.push("B");
|
||||
} else {
|
||||
buffer.push("S");
|
||||
}
|
||||
return [points[0].x, points[1].x, points[3].y, points[1].y];
|
||||
return [points[0], points[2], points[7], points[3]];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -4178,10 +4170,10 @@ class CircleAnnotation extends MarkupAnnotation {
|
|||
strokeAlpha,
|
||||
fillAlpha,
|
||||
pointsCallback: (buffer, points) => {
|
||||
const x0 = points[0].x + this.borderStyle.width / 2;
|
||||
const y0 = points[0].y - this.borderStyle.width / 2;
|
||||
const x1 = points[3].x - this.borderStyle.width / 2;
|
||||
const y1 = points[3].y + this.borderStyle.width / 2;
|
||||
const x0 = points[0] + this.borderStyle.width / 2;
|
||||
const y0 = points[1] - this.borderStyle.width / 2;
|
||||
const x1 = points[6] - this.borderStyle.width / 2;
|
||||
const y1 = points[7] + this.borderStyle.width / 2;
|
||||
const xMid = x0 + (x1 - x0) / 2;
|
||||
const yMid = y0 + (y1 - y0) / 2;
|
||||
const xOffset = ((x1 - x0) / 2) * controlPointsDistance;
|
||||
|
@ -4200,7 +4192,7 @@ class CircleAnnotation extends MarkupAnnotation {
|
|||
} else {
|
||||
buffer.push("S");
|
||||
}
|
||||
return [points[0].x, points[1].x, points[3].y, points[1].y];
|
||||
return [points[0], points[2], points[7], points[3]];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -4215,7 +4207,7 @@ class PolylineAnnotation extends MarkupAnnotation {
|
|||
this.data.annotationType = AnnotationType.POLYLINE;
|
||||
this.data.hasOwnCanvas = this.data.noRotate;
|
||||
this.data.noHTML = false;
|
||||
this.data.vertices = [];
|
||||
this.data.vertices = null;
|
||||
|
||||
if (
|
||||
(typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) &&
|
||||
|
@ -4233,12 +4225,7 @@ class PolylineAnnotation extends MarkupAnnotation {
|
|||
if (!isNumberArray(rawVertices, null)) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0, ii = rawVertices.length; i < ii; i += 2) {
|
||||
this.data.vertices.push({
|
||||
x: rawVertices[i],
|
||||
y: rawVertices[i + 1],
|
||||
});
|
||||
}
|
||||
const vertices = (this.data.vertices = Float32Array.from(rawVertices));
|
||||
|
||||
if (!this.appearance) {
|
||||
// The default stroke color is black.
|
||||
|
@ -4251,11 +4238,11 @@ class PolylineAnnotation extends MarkupAnnotation {
|
|||
// If the /Rect-entry is empty/wrong, create a fallback rectangle so that
|
||||
// we get similar rendering/highlighting behaviour as in Adobe Reader.
|
||||
const bbox = [Infinity, Infinity, -Infinity, -Infinity];
|
||||
for (const vertex of this.data.vertices) {
|
||||
bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust);
|
||||
bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust);
|
||||
bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust);
|
||||
bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust);
|
||||
for (let i = 0, ii = vertices.length; i < ii; i += 2) {
|
||||
bbox[0] = Math.min(bbox[0], vertices[i] - borderAdjust);
|
||||
bbox[1] = Math.min(bbox[1], vertices[i + 1] - borderAdjust);
|
||||
bbox[2] = Math.max(bbox[2], vertices[i] + borderAdjust);
|
||||
bbox[3] = Math.max(bbox[3], vertices[i + 1] + borderAdjust);
|
||||
}
|
||||
if (!Util.intersect(this.rectangle, bbox)) {
|
||||
this.rectangle = bbox;
|
||||
|
@ -4267,14 +4254,13 @@ class PolylineAnnotation extends MarkupAnnotation {
|
|||
strokeColor,
|
||||
strokeAlpha,
|
||||
pointsCallback: (buffer, points) => {
|
||||
const vertices = this.data.vertices;
|
||||
for (let i = 0, ii = vertices.length; i < ii; i++) {
|
||||
for (let i = 0, ii = vertices.length; i < ii; i += 2) {
|
||||
buffer.push(
|
||||
`${vertices[i].x} ${vertices[i].y} ${i === 0 ? "m" : "l"}`
|
||||
`${vertices[i]} ${vertices[i + 1]} ${i === 0 ? "m" : "l"}`
|
||||
);
|
||||
}
|
||||
buffer.push("S");
|
||||
return [points[0].x, points[1].x, points[3].y, points[1].y];
|
||||
return [points[0], points[2], points[7], points[3]];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -4318,15 +4304,17 @@ class InkAnnotation extends MarkupAnnotation {
|
|||
// the alternating horizontal and vertical coordinates, respectively,
|
||||
// of each vertex. Convert this to an array of objects with x and y
|
||||
// coordinates.
|
||||
this.data.inkLists.push([]);
|
||||
if (!Array.isArray(rawInkLists[i])) {
|
||||
continue;
|
||||
}
|
||||
const inkList = new Float32Array(rawInkLists[i].length);
|
||||
this.data.inkLists.push(inkList);
|
||||
for (let j = 0, jj = rawInkLists[i].length; j < jj; j += 2) {
|
||||
const x = xref.fetchIfRef(rawInkLists[i][j]),
|
||||
y = xref.fetchIfRef(rawInkLists[i][j + 1]);
|
||||
if (typeof x === "number" && typeof y === "number") {
|
||||
this.data.inkLists[i].push({ x, y });
|
||||
inkList[j] = x;
|
||||
inkList[j + 1] = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4342,12 +4330,12 @@ class InkAnnotation extends MarkupAnnotation {
|
|||
// If the /Rect-entry is empty/wrong, create a fallback rectangle so that
|
||||
// we get similar rendering/highlighting behaviour as in Adobe Reader.
|
||||
const bbox = [Infinity, Infinity, -Infinity, -Infinity];
|
||||
for (const inkLists of this.data.inkLists) {
|
||||
for (const vertex of inkLists) {
|
||||
bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust);
|
||||
bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust);
|
||||
bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust);
|
||||
bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust);
|
||||
for (const inkList of this.data.inkLists) {
|
||||
for (let i = 0, ii = inkList.length; i < ii; i += 2) {
|
||||
bbox[0] = Math.min(bbox[0], inkList[i] - borderAdjust);
|
||||
bbox[1] = Math.min(bbox[1], inkList[i + 1] - borderAdjust);
|
||||
bbox[2] = Math.max(bbox[2], inkList[i] + borderAdjust);
|
||||
bbox[3] = Math.max(bbox[3], inkList[i + 1] + borderAdjust);
|
||||
}
|
||||
}
|
||||
if (!Util.intersect(this.rectangle, bbox)) {
|
||||
|
@ -4365,14 +4353,14 @@ class InkAnnotation extends MarkupAnnotation {
|
|||
// curves in an implementation-dependent way.
|
||||
// In order to simplify things, we utilize straight lines for now.
|
||||
for (const inkList of this.data.inkLists) {
|
||||
for (let i = 0, ii = inkList.length; i < ii; i++) {
|
||||
for (let i = 0, ii = inkList.length; i < ii; i += 2) {
|
||||
buffer.push(
|
||||
`${inkList[i].x} ${inkList[i].y} ${i === 0 ? "m" : "l"}`
|
||||
`${inkList[i]} ${inkList[i + 1]} ${i === 0 ? "m" : "l"}`
|
||||
);
|
||||
}
|
||||
buffer.push("S");
|
||||
}
|
||||
return [points[0].x, points[1].x, points[3].y, points[1].y];
|
||||
return [points[0], points[2], points[7], points[3]];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -4581,13 +4569,13 @@ class HighlightAnnotation extends MarkupAnnotation {
|
|||
fillAlpha,
|
||||
pointsCallback: (buffer, points) => {
|
||||
buffer.push(
|
||||
`${points[0].x} ${points[0].y} m`,
|
||||
`${points[1].x} ${points[1].y} l`,
|
||||
`${points[3].x} ${points[3].y} l`,
|
||||
`${points[2].x} ${points[2].y} l`,
|
||||
`${points[0]} ${points[1]} m`,
|
||||
`${points[2]} ${points[3]} l`,
|
||||
`${points[6]} ${points[7]} l`,
|
||||
`${points[4]} ${points[5]} l`,
|
||||
"f"
|
||||
);
|
||||
return [points[0].x, points[1].x, points[3].y, points[1].y];
|
||||
return [points[0], points[2], points[7], points[3]];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -4709,11 +4697,11 @@ class UnderlineAnnotation extends MarkupAnnotation {
|
|||
strokeAlpha,
|
||||
pointsCallback: (buffer, points) => {
|
||||
buffer.push(
|
||||
`${points[2].x} ${points[2].y + 1.3} m`,
|
||||
`${points[3].x} ${points[3].y + 1.3} l`,
|
||||
`${points[4]} ${points[5] + 1.3} m`,
|
||||
`${points[6]} ${points[7] + 1.3} l`,
|
||||
"S"
|
||||
);
|
||||
return [points[0].x, points[1].x, points[3].y, points[1].y];
|
||||
return [points[0], points[2], points[7], points[3]];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -4745,11 +4733,11 @@ class SquigglyAnnotation extends MarkupAnnotation {
|
|||
strokeColor,
|
||||
strokeAlpha,
|
||||
pointsCallback: (buffer, points) => {
|
||||
const dy = (points[0].y - points[2].y) / 6;
|
||||
const dy = (points[1] - points[5]) / 6;
|
||||
let shift = dy;
|
||||
let x = points[2].x;
|
||||
const y = points[2].y;
|
||||
const xEnd = points[3].x;
|
||||
let x = points[4];
|
||||
const y = points[5];
|
||||
const xEnd = points[6];
|
||||
buffer.push(`${x} ${y + shift} m`);
|
||||
do {
|
||||
x += 2;
|
||||
|
@ -4757,7 +4745,7 @@ class SquigglyAnnotation extends MarkupAnnotation {
|
|||
buffer.push(`${x} ${y + shift} l`);
|
||||
} while (x < xEnd);
|
||||
buffer.push("S");
|
||||
return [points[2].x, xEnd, y - 2 * dy, y + 2 * dy];
|
||||
return [points[4], xEnd, y - 2 * dy, y + 2 * dy];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -4790,13 +4778,13 @@ class StrikeOutAnnotation extends MarkupAnnotation {
|
|||
strokeAlpha,
|
||||
pointsCallback: (buffer, points) => {
|
||||
buffer.push(
|
||||
`${(points[0].x + points[2].x) / 2} ` +
|
||||
`${(points[0].y + points[2].y) / 2} m`,
|
||||
`${(points[1].x + points[3].x) / 2} ` +
|
||||
`${(points[1].y + points[3].y) / 2} l`,
|
||||
`${(points[0] + points[4]) / 2} ` +
|
||||
`${(points[1] + points[5]) / 2} m`,
|
||||
`${(points[2] + points[6]) / 2} ` +
|
||||
`${(points[3] + points[7]) / 2} l`,
|
||||
"S"
|
||||
);
|
||||
return [points[0].x, points[1].x, points[3].y, points[1].y];
|
||||
return [points[0], points[2], points[7], points[3]];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -528,10 +528,12 @@ class AnnotationElement {
|
|||
return;
|
||||
}
|
||||
|
||||
const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect;
|
||||
const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect.map(x =>
|
||||
Math.fround(x)
|
||||
);
|
||||
|
||||
if (quadPoints.length === 1) {
|
||||
const [, { x: trX, y: trY }, { x: blX, y: blY }] = quadPoints[0];
|
||||
if (quadPoints.length === 8) {
|
||||
const [trX, trY, blX, blY] = quadPoints.subarray(2, 6);
|
||||
if (
|
||||
rectTrX === trX &&
|
||||
rectTrY === trY &&
|
||||
|
@ -578,7 +580,11 @@ class AnnotationElement {
|
|||
clipPath.setAttribute("clipPathUnits", "objectBoundingBox");
|
||||
defs.append(clipPath);
|
||||
|
||||
for (const [, { x: trX, y: trY }, { x: blX, y: blY }] of quadPoints) {
|
||||
for (let i = 2, ii = quadPoints.length; i < ii; i += 8) {
|
||||
const trX = quadPoints[i];
|
||||
const trY = quadPoints[i + 1];
|
||||
const blX = quadPoints[i + 2];
|
||||
const blY = quadPoints[i + 3];
|
||||
const rect = svgFactory.createElement("rect");
|
||||
const x = (blX - rectBlX) / width;
|
||||
const y = (rectTrY - trY) / height;
|
||||
|
@ -2716,8 +2722,13 @@ class PolylineAnnotationElement extends AnnotationElement {
|
|||
// Create an invisible polyline with the same points that acts as the
|
||||
// trigger for the popup. Only the polyline itself should trigger the
|
||||
// popup, not the entire container.
|
||||
const data = this.data;
|
||||
const { width, height } = getRectDims(data.rect);
|
||||
const {
|
||||
data: { rect, vertices, borderStyle, popupRef },
|
||||
} = this;
|
||||
if (!vertices) {
|
||||
return this.container;
|
||||
}
|
||||
const { width, height } = getRectDims(rect);
|
||||
const svg = this.svgFactory.create(
|
||||
width,
|
||||
height,
|
||||
|
@ -2729,10 +2740,10 @@ class PolylineAnnotationElement extends AnnotationElement {
|
|||
// calculated from a bottom left origin, so transform the polyline
|
||||
// coordinates to a top left origin for the SVG element.
|
||||
let points = [];
|
||||
for (const coordinate of data.vertices) {
|
||||
const x = coordinate.x - data.rect[0];
|
||||
const y = data.rect[3] - coordinate.y;
|
||||
points.push(x + "," + y);
|
||||
for (let i = 0, ii = vertices.length; i < ii; i += 2) {
|
||||
const x = vertices[i] - rect[0];
|
||||
const y = rect[3] - vertices[i + 1];
|
||||
points.push(`${x},${y}`);
|
||||
}
|
||||
points = points.join(" ");
|
||||
|
||||
|
@ -2742,7 +2753,7 @@ class PolylineAnnotationElement extends AnnotationElement {
|
|||
polyline.setAttribute("points", points);
|
||||
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
||||
// won't be possible to open/close the popup (note e.g. issue 11122).
|
||||
polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
|
||||
polyline.setAttribute("stroke-width", borderStyle.width || 1);
|
||||
polyline.setAttribute("stroke", "transparent");
|
||||
polyline.setAttribute("fill", "transparent");
|
||||
|
||||
|
@ -2751,7 +2762,7 @@ class PolylineAnnotationElement extends AnnotationElement {
|
|||
|
||||
// Create the popup ourselves so that we can bind it to the polyline
|
||||
// instead of to the entire container (which is the default).
|
||||
if (!data.popupRef && this.hasPopupData) {
|
||||
if (!popupRef && this.hasPopupData) {
|
||||
this._createPopup();
|
||||
}
|
||||
|
||||
|
@ -2811,23 +2822,25 @@ class InkAnnotationElement extends AnnotationElement {
|
|||
|
||||
// Create an invisible polyline with the same points that acts as the
|
||||
// trigger for the popup.
|
||||
const data = this.data;
|
||||
const { width, height } = getRectDims(data.rect);
|
||||
const {
|
||||
data: { rect, inkLists, borderStyle, popupRef },
|
||||
} = this;
|
||||
const { width, height } = getRectDims(rect);
|
||||
const svg = this.svgFactory.create(
|
||||
width,
|
||||
height,
|
||||
/* skipDimensions = */ true
|
||||
);
|
||||
|
||||
for (const inkList of data.inkLists) {
|
||||
for (const inkList of inkLists) {
|
||||
// Convert the ink list to a single points string that the SVG
|
||||
// polyline element expects ("x1,y1 x2,y2 ..."). PDF coordinates are
|
||||
// calculated from a bottom left origin, so transform the polyline
|
||||
// coordinates to a top left origin for the SVG element.
|
||||
let points = [];
|
||||
for (const coordinate of inkList) {
|
||||
const x = coordinate.x - data.rect[0];
|
||||
const y = data.rect[3] - coordinate.y;
|
||||
for (let i = 0, ii = inkList.length; i < ii; i += 2) {
|
||||
const x = inkList[i] - rect[0];
|
||||
const y = rect[3] - inkList[i + 1];
|
||||
points.push(`${x},${y}`);
|
||||
}
|
||||
points = points.join(" ");
|
||||
|
@ -2837,13 +2850,13 @@ class InkAnnotationElement extends AnnotationElement {
|
|||
polyline.setAttribute("points", points);
|
||||
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
||||
// won't be possible to open/close the popup (note e.g. issue 11122).
|
||||
polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
|
||||
polyline.setAttribute("stroke-width", borderStyle.width || 1);
|
||||
polyline.setAttribute("stroke", "transparent");
|
||||
polyline.setAttribute("fill", "transparent");
|
||||
|
||||
// Create the popup ourselves so that we can bind it to the polyline
|
||||
// instead of to the entire container (which is the default).
|
||||
if (!data.popupRef && this.hasPopupData) {
|
||||
if (!popupRef && this.hasPopupData) {
|
||||
this._createPopup();
|
||||
}
|
||||
|
||||
|
|
|
@ -670,7 +670,7 @@ class HighlightEditor extends AnnotationEditor {
|
|||
}
|
||||
const [pageWidth, pageHeight] = this.pageDimensions;
|
||||
const boxes = this.#boxes;
|
||||
const quadPoints = new Array(boxes.length * 8);
|
||||
const quadPoints = new Float32Array(boxes.length * 8);
|
||||
let i = 0;
|
||||
for (const { x, y, width, height } of boxes) {
|
||||
const sx = x * pageWidth;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue