Merge pull request #14796 from calixteman/minmax
[api-minor] Simplify min/max computations in constructPath (bug 1135277)
This commit is contained in:
commit
f82879205e
@ -1352,6 +1352,7 @@ class PartialEvaluator {
|
||||
if (!args) {
|
||||
args = [];
|
||||
}
|
||||
let minMax;
|
||||
if (
|
||||
lastIndex < 0 ||
|
||||
operatorList.fnArray[lastIndex] !== OPS.constructPath
|
||||
@ -1368,7 +1369,8 @@ class PartialEvaluator {
|
||||
operatorList.addOp(OPS.save, null);
|
||||
}
|
||||
|
||||
operatorList.addOp(OPS.constructPath, [[fn], args]);
|
||||
minMax = [Infinity, -Infinity, Infinity, -Infinity];
|
||||
operatorList.addOp(OPS.constructPath, [[fn], args, minMax]);
|
||||
|
||||
if (parsingText) {
|
||||
operatorList.addOp(OPS.restore, null);
|
||||
@ -1377,6 +1379,28 @@ class PartialEvaluator {
|
||||
const opArgs = operatorList.argsArray[lastIndex];
|
||||
opArgs[0].push(fn);
|
||||
Array.prototype.push.apply(opArgs[1], args);
|
||||
minMax = opArgs[2];
|
||||
}
|
||||
|
||||
// Compute min/max in the worker instead of the main thread.
|
||||
// If the current matrix (when drawing) is a scaling one
|
||||
// then min/max can be easily computed in using those values.
|
||||
// Only rectangle, lineTo and moveTo are handled here since
|
||||
// Bezier stuff requires to have the starting point.
|
||||
switch (fn) {
|
||||
case OPS.rectangle:
|
||||
minMax[0] = Math.min(minMax[0], args[0], args[0] + args[2]);
|
||||
minMax[1] = Math.max(minMax[1], args[0], args[0] + args[2]);
|
||||
minMax[2] = Math.min(minMax[2], args[1], args[1] + args[3]);
|
||||
minMax[3] = Math.max(minMax[3], args[1], args[1] + args[3]);
|
||||
break;
|
||||
case OPS.moveTo:
|
||||
case OPS.lineTo:
|
||||
minMax[0] = Math.min(minMax[0], args[0]);
|
||||
minMax[1] = Math.max(minMax[1], args[0]);
|
||||
minMax[2] = Math.min(minMax[2], args[1]);
|
||||
minMax[3] = Math.max(minMax[3], args[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,8 +604,23 @@ class CanvasExtraState {
|
||||
this.maxY = Math.max(this.maxY, y);
|
||||
}
|
||||
|
||||
updateCurvePathMinMax(transform, x0, y0, x1, y1, x2, y2, x3, y3) {
|
||||
updateScalingPathMinMax(transform, minMax) {
|
||||
Util.scaleMinMax(transform, minMax);
|
||||
this.minX = Math.min(this.minX, minMax[0]);
|
||||
this.maxX = Math.max(this.maxX, minMax[1]);
|
||||
this.minY = Math.min(this.minY, minMax[2]);
|
||||
this.maxY = Math.max(this.maxY, minMax[3]);
|
||||
}
|
||||
|
||||
updateCurvePathMinMax(transform, x0, y0, x1, y1, x2, y2, x3, y3, minMax) {
|
||||
const box = Util.bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3);
|
||||
if (minMax) {
|
||||
minMax[0] = Math.min(minMax[0], box[0], box[2]);
|
||||
minMax[1] = Math.max(minMax[1], box[0], box[2]);
|
||||
minMax[2] = Math.min(minMax[2], box[1], box[3]);
|
||||
minMax[3] = Math.max(minMax[3], box[1], box[3]);
|
||||
return;
|
||||
}
|
||||
this.updatePathMinMax(transform, box[0], box[1]);
|
||||
this.updatePathMinMax(transform, box[2], box[3]);
|
||||
}
|
||||
@ -1737,12 +1752,25 @@ class CanvasGraphics {
|
||||
}
|
||||
|
||||
// Path
|
||||
constructPath(ops, args) {
|
||||
constructPath(ops, args, minMax) {
|
||||
const ctx = this.ctx;
|
||||
const current = this.current;
|
||||
let x = current.x,
|
||||
y = current.y;
|
||||
let startX, startY;
|
||||
const currentTransform = ctx.mozCurrentTransform;
|
||||
|
||||
// Most of the time the current transform is a scaling matrix
|
||||
// so we don't need to transform points before computing min/max:
|
||||
// we can compute min/max first and then smartly "apply" the
|
||||
// transform (see Util.scaleMinMax).
|
||||
// For rectangle, moveTo and lineTo, min/max are computed in the
|
||||
// worker (see evaluator.js).
|
||||
const isScalingMatrix =
|
||||
(currentTransform[0] === 0 && currentTransform[3] === 0) ||
|
||||
(currentTransform[1] === 0 && currentTransform[2] === 0);
|
||||
const minMaxForBezier = isScalingMatrix ? minMax.slice(0) : null;
|
||||
|
||||
for (let i = 0, j = 0, ii = ops.length; i < ii; i++) {
|
||||
switch (ops[i] | 0) {
|
||||
case OPS.rectangle:
|
||||
@ -1761,21 +1789,27 @@ class CanvasGraphics {
|
||||
ctx.lineTo(xw, yh);
|
||||
ctx.lineTo(x, yh);
|
||||
}
|
||||
current.updatePathMinMax(ctx.mozCurrentTransform, x, y);
|
||||
current.updatePathMinMax(ctx.mozCurrentTransform, xw, yh);
|
||||
if (!isScalingMatrix) {
|
||||
current.updatePathMinMax(currentTransform, x, y);
|
||||
current.updatePathMinMax(currentTransform, xw, yh);
|
||||
}
|
||||
ctx.closePath();
|
||||
break;
|
||||
case OPS.moveTo:
|
||||
x = args[j++];
|
||||
y = args[j++];
|
||||
ctx.moveTo(x, y);
|
||||
current.updatePathMinMax(ctx.mozCurrentTransform, x, y);
|
||||
if (!isScalingMatrix) {
|
||||
current.updatePathMinMax(currentTransform, x, y);
|
||||
}
|
||||
break;
|
||||
case OPS.lineTo:
|
||||
x = args[j++];
|
||||
y = args[j++];
|
||||
ctx.lineTo(x, y);
|
||||
current.updatePathMinMax(ctx.mozCurrentTransform, x, y);
|
||||
if (!isScalingMatrix) {
|
||||
current.updatePathMinMax(currentTransform, x, y);
|
||||
}
|
||||
break;
|
||||
case OPS.curveTo:
|
||||
startX = x;
|
||||
@ -1791,7 +1825,7 @@ class CanvasGraphics {
|
||||
y
|
||||
);
|
||||
current.updateCurvePathMinMax(
|
||||
ctx.mozCurrentTransform,
|
||||
currentTransform,
|
||||
startX,
|
||||
startY,
|
||||
args[j],
|
||||
@ -1799,7 +1833,8 @@ class CanvasGraphics {
|
||||
args[j + 2],
|
||||
args[j + 3],
|
||||
x,
|
||||
y
|
||||
y,
|
||||
minMaxForBezier
|
||||
);
|
||||
j += 6;
|
||||
break;
|
||||
@ -1815,7 +1850,7 @@ class CanvasGraphics {
|
||||
args[j + 3]
|
||||
);
|
||||
current.updateCurvePathMinMax(
|
||||
ctx.mozCurrentTransform,
|
||||
currentTransform,
|
||||
startX,
|
||||
startY,
|
||||
x,
|
||||
@ -1823,7 +1858,8 @@ class CanvasGraphics {
|
||||
args[j],
|
||||
args[j + 1],
|
||||
args[j + 2],
|
||||
args[j + 3]
|
||||
args[j + 3],
|
||||
minMaxForBezier
|
||||
);
|
||||
x = args[j + 2];
|
||||
y = args[j + 3];
|
||||
@ -1836,7 +1872,7 @@ class CanvasGraphics {
|
||||
y = args[j + 3];
|
||||
ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y);
|
||||
current.updateCurvePathMinMax(
|
||||
ctx.mozCurrentTransform,
|
||||
currentTransform,
|
||||
startX,
|
||||
startY,
|
||||
args[j],
|
||||
@ -1844,7 +1880,8 @@ class CanvasGraphics {
|
||||
x,
|
||||
y,
|
||||
x,
|
||||
y
|
||||
y,
|
||||
minMaxForBezier
|
||||
);
|
||||
j += 4;
|
||||
break;
|
||||
@ -1853,6 +1890,11 @@ class CanvasGraphics {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isScalingMatrix) {
|
||||
current.updateScalingPathMinMax(currentTransform, minMaxForBezier);
|
||||
}
|
||||
|
||||
current.setCurrentPoint(x, y);
|
||||
}
|
||||
|
||||
|
@ -720,6 +720,57 @@ class Util {
|
||||
return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`;
|
||||
}
|
||||
|
||||
// Apply a scaling matrix to some min/max values.
|
||||
// If a scaling factor is negative then min and max must be
|
||||
// swaped.
|
||||
static scaleMinMax(transform, minMax) {
|
||||
let temp;
|
||||
if (transform[0]) {
|
||||
if (transform[0] < 0) {
|
||||
temp = minMax[0];
|
||||
minMax[0] = minMax[1];
|
||||
minMax[1] = temp;
|
||||
}
|
||||
minMax[0] *= transform[0];
|
||||
minMax[1] *= transform[0];
|
||||
|
||||
if (transform[3] < 0) {
|
||||
temp = minMax[2];
|
||||
minMax[2] = minMax[3];
|
||||
minMax[3] = temp;
|
||||
}
|
||||
minMax[2] *= transform[3];
|
||||
minMax[3] *= transform[3];
|
||||
} else {
|
||||
temp = minMax[0];
|
||||
minMax[0] = minMax[2];
|
||||
minMax[2] = temp;
|
||||
temp = minMax[1];
|
||||
minMax[1] = minMax[3];
|
||||
minMax[3] = temp;
|
||||
|
||||
if (transform[1] < 0) {
|
||||
temp = minMax[2];
|
||||
minMax[2] = minMax[3];
|
||||
minMax[3] = temp;
|
||||
}
|
||||
minMax[2] *= transform[1];
|
||||
minMax[3] *= transform[1];
|
||||
|
||||
if (transform[2] < 0) {
|
||||
temp = minMax[0];
|
||||
minMax[0] = minMax[1];
|
||||
minMax[1] = temp;
|
||||
}
|
||||
minMax[0] *= transform[2];
|
||||
minMax[1] *= transform[2];
|
||||
}
|
||||
minMax[0] += transform[4];
|
||||
minMax[1] += transform[4];
|
||||
minMax[2] += transform[5];
|
||||
minMax[3] += transform[5];
|
||||
}
|
||||
|
||||
// Concatenates two transformation matrices together and returns the result.
|
||||
static transform(m1, m2) {
|
||||
return [
|
||||
|
Loading…
x
Reference in New Issue
Block a user