1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-19 22:58:07 +02:00

Introduce Math.sumPrecise usage in the code-base

This is a new JavaScript feature that makes it easy to compute the sum of list of values; see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sumPrecise

This allows us to remove most cases of `Array.prototype.reduce`, which helps improve readability since that (in my opinion) often isn't the most intuitive code.
This commit is contained in:
Jonas Jenwald 2025-03-23 09:30:37 +01:00
parent 80d4d7058f
commit e73224ded7
9 changed files with 40 additions and 35 deletions

View file

@ -2572,11 +2572,7 @@ class WidgetAnnotation extends Annotation {
}
_getTextWidth(text, font) {
return (
font
.charsToGlyphs(text)
.reduce((width, glyph) => width + glyph.width, 0) / 1000
);
return Math.sumPrecise(font.charsToGlyphs(text).map(g => g.width)) / 1000;
}
_computeFontSize(height, width, text, font, lineCount) {

View file

@ -720,7 +720,7 @@ class PDF20 extends PDFBase {
// The number is e0 + 256 * e1 + 256^2 * e2... and 256 % 3 === 1, hence
// the powers of 256 are === 1 modulo 3 and finally the number modulo 3
// is equal to the remainder modulo 3 of the sum of the e_n.
const remainder = e.slice(0, 16).reduce((a, b) => a + b, 0) % 3;
const remainder = Math.sumPrecise(e.slice(0, 16)) % 3;
if (remainder === 0) {
k = calculateSHA256(e, 0, e.length);
} else if (remainder === 1) {

View file

@ -81,11 +81,10 @@ class GlyfTable {
}
getSize() {
return this.glyphs.reduce((a, g) => {
const size = g.getSize();
return Math.sumPrecise(
// Round to next multiple of 4 if needed.
return a + ((size + 3) & ~3);
}, 0);
this.glyphs.map(g => (g.getSize() + 3) & ~3)
);
}
write() {
@ -169,7 +168,7 @@ class Glyph {
}
const size = this.simple
? this.simple.getSize()
: this.composites.reduce((a, c) => a + c.getSize(), 0);
: Math.sumPrecise(this.composites.map(c => c.getSize()));
return this.header.getSize() + size;
}

View file

@ -184,7 +184,7 @@ function computeMD5(filesize, xrefInfo) {
filesize.toString(),
...Object.values(xrefInfo.info),
];
const md5BufferLen = md5Buffer.reduce((a, str) => a + str.length, 0);
const md5BufferLen = Math.sumPrecise(md5Buffer.map(str => str.length));
const array = new Uint8Array(md5BufferLen);
let offset = 0;
@ -352,7 +352,7 @@ async function getXRefStreamTable(
newXref.set("W", sizes);
computeIDs(baseOffset, xrefInfo, newXref);
const structSize = sizes.reduce((a, x) => a + x, 0);
const structSize = Math.sumPrecise(sizes);
const data = new Uint8Array(structSize * xrefTableData.length);
const stream = new Stream(data);
stream.dict = newXref;
@ -467,10 +467,8 @@ async function incrementalUpdate({
? getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer)
: getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer));
const totalLength = buffer.reduce(
(a, str) => a + str.length,
originalData.length
);
const totalLength =
originalData.length + Math.sumPrecise(buffer.map(str => str.length));
const array = new Uint8Array(totalLength);
// Original data

View file

@ -86,14 +86,15 @@ const converters = {
const colSpan = node.colSpan;
let w;
if (colSpan === -1) {
w = extra.columnWidths
.slice(extra.currentColumn)
.reduce((a, x) => a + x, 0);
w = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn));
extra.currentColumn = 0;
} else {
w = extra.columnWidths
.slice(extra.currentColumn, extra.currentColumn + colSpan)
.reduce((a, x) => a + x, 0);
w = Math.sumPrecise(
extra.columnWidths.slice(
extra.currentColumn,
extra.currentColumn + colSpan
)
);
extra.currentColumn =
(extra.currentColumn + node.colSpan) % extra.columnWidths.length;
}
@ -328,13 +329,14 @@ function fixDimensions(node) {
const colSpan = node.colSpan;
let width;
if (colSpan === -1) {
width = extra.columnWidths
.slice(extra.currentColumn)
.reduce((a, w) => a + w, 0);
width = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn));
} else {
width = extra.columnWidths
.slice(extra.currentColumn, extra.currentColumn + colSpan)
.reduce((a, w) => a + w, 0);
width = Math.sumPrecise(
extra.columnWidths.slice(
extra.currentColumn,
extra.currentColumn + colSpan
)
);
}
if (!isNaN(width)) {
node.w = width;
@ -348,7 +350,7 @@ function fixDimensions(node) {
if (node.layout === "table") {
if (node.w === "" && Array.isArray(node.columnWidths)) {
node.w = node.columnWidths.reduce((a, x) => a + x, 0);
node.w = Math.sumPrecise(node.columnWidths);
}
}
}

View file

@ -183,9 +183,9 @@ function getAvailableSpace(node) {
};
case "rl-row":
case "row":
const width = node[$extra].columnWidths
.slice(node[$extra].currentColumn)
.reduce((a, x) => a + x);
const width = Math.sumPrecise(
node[$extra].columnWidths.slice(node[$extra].currentColumn)
);
return { width, height: availableSpace.height - marginH };
case "table":
case "tb":

View file

@ -718,7 +718,7 @@ class FreeTextEditor extends AnnotationEditor {
// Set the caret at the right position.
const newRange = new Range();
let beforeLength = bufferBefore.reduce((acc, line) => acc + line.length, 0);
let beforeLength = Math.sumPrecise(bufferBefore.map(line => line.length));
for (const { firstChild } of this.editorDiv.childNodes) {
// Each child is either a div with a text node or a br element.
if (firstChild.nodeType === Node.TEXT_NODE) {

View file

@ -1130,6 +1130,16 @@ if (
};
}
// TODO: Remove this once the `javascript.options.experimental.math_sumprecise`
// preference is removed from Firefox.
if (typeof Math.sumPrecise !== "function") {
// Note that this isn't a "proper" polyfill, but since we're only using it to
// replace `Array.prototype.reduce()` invocations it should be fine.
Math.sumPrecise = function (numbers) {
return numbers.reduce((a, b) => a + b, 0);
};
}
if (
typeof PDFJSDev !== "undefined" &&
!PDFJSDev.test("SKIP_BABEL") &&

View file

@ -128,7 +128,7 @@ function testSearch({
}
}
const totalMatches = matchesPerPage.reduce((a, b) => a + b);
const totalMatches = Math.sumPrecise(matchesPerPage);
if (updateFindControlState) {
eventBus.on(