Merge pull request #16448 from calixteman/improve_rescaleandstroke
Improve performance of canvas::rescaleAndStroke by around 30% (bug 1135277)
This commit is contained in:
commit
65e23432cd
@ -986,7 +986,7 @@ class CanvasGraphics {
|
|||||||
this.outputScaleY = 1;
|
this.outputScaleY = 1;
|
||||||
this.pageColors = pageColors;
|
this.pageColors = pageColors;
|
||||||
|
|
||||||
this._cachedScaleForStroking = null;
|
this._cachedScaleForStroking = [-1, 0];
|
||||||
this._cachedGetSinglePixelWidth = null;
|
this._cachedGetSinglePixelWidth = null;
|
||||||
this._cachedBitmapsMap = new Map();
|
this._cachedBitmapsMap = new Map();
|
||||||
}
|
}
|
||||||
@ -1395,7 +1395,7 @@ class CanvasGraphics {
|
|||||||
// Graphics state
|
// Graphics state
|
||||||
setLineWidth(width) {
|
setLineWidth(width) {
|
||||||
if (width !== this.current.lineWidth) {
|
if (width !== this.current.lineWidth) {
|
||||||
this._cachedScaleForStroking = null;
|
this._cachedScaleForStroking[0] = -1;
|
||||||
}
|
}
|
||||||
this.current.lineWidth = width;
|
this.current.lineWidth = width;
|
||||||
this.ctx.lineWidth = width;
|
this.ctx.lineWidth = width;
|
||||||
@ -1602,7 +1602,7 @@ class CanvasGraphics {
|
|||||||
// Ensure that the clipping path is reset (fixes issue6413.pdf).
|
// Ensure that the clipping path is reset (fixes issue6413.pdf).
|
||||||
this.pendingClip = null;
|
this.pendingClip = null;
|
||||||
|
|
||||||
this._cachedScaleForStroking = null;
|
this._cachedScaleForStroking[0] = -1;
|
||||||
this._cachedGetSinglePixelWidth = null;
|
this._cachedGetSinglePixelWidth = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1610,7 +1610,7 @@ class CanvasGraphics {
|
|||||||
transform(a, b, c, d, e, f) {
|
transform(a, b, c, d, e, f) {
|
||||||
this.ctx.transform(a, b, c, d, e, f);
|
this.ctx.transform(a, b, c, d, e, f);
|
||||||
|
|
||||||
this._cachedScaleForStroking = null;
|
this._cachedScaleForStroking[0] = -1;
|
||||||
this._cachedGetSinglePixelWidth = null;
|
this._cachedGetSinglePixelWidth = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2297,7 +2297,7 @@ class CanvasGraphics {
|
|||||||
if (isTextInvisible || fontSize === 0) {
|
if (isTextInvisible || fontSize === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._cachedScaleForStroking = null;
|
this._cachedScaleForStroking[0] = -1;
|
||||||
this._cachedGetSinglePixelWidth = null;
|
this._cachedGetSinglePixelWidth = null;
|
||||||
|
|
||||||
ctx.save();
|
ctx.save();
|
||||||
@ -3160,16 +3160,23 @@ class CanvasGraphics {
|
|||||||
// The goal of this function is to rescale before setting the
|
// The goal of this function is to rescale before setting the
|
||||||
// lineWidth in order to have both thicknesses greater or equal
|
// lineWidth in order to have both thicknesses greater or equal
|
||||||
// to 1 after transform.
|
// to 1 after transform.
|
||||||
if (!this._cachedScaleForStroking) {
|
if (this._cachedScaleForStroking[0] === -1) {
|
||||||
const { lineWidth } = this.current;
|
const { lineWidth } = this.current;
|
||||||
const m = getCurrentTransform(this.ctx);
|
const { a, b, c, d } = this.ctx.getTransform();
|
||||||
let scaleX, scaleY;
|
let scaleX, scaleY;
|
||||||
|
|
||||||
if (m[1] === 0 && m[2] === 0) {
|
if (b === 0 && c === 0) {
|
||||||
// Fast path
|
// Fast path
|
||||||
const normX = Math.abs(m[0]);
|
const normX = Math.abs(a);
|
||||||
const normY = Math.abs(m[3]);
|
const normY = Math.abs(d);
|
||||||
if (lineWidth === 0) {
|
if (normX === normY) {
|
||||||
|
if (lineWidth === 0) {
|
||||||
|
scaleX = scaleY = 1 / normX;
|
||||||
|
} else {
|
||||||
|
const scaledLineWidth = normX * lineWidth;
|
||||||
|
scaleX = scaleY = scaledLineWidth < 1 ? 1 / scaledLineWidth : 1;
|
||||||
|
}
|
||||||
|
} else if (lineWidth === 0) {
|
||||||
scaleX = 1 / normX;
|
scaleX = 1 / normX;
|
||||||
scaleY = 1 / normY;
|
scaleY = 1 / normY;
|
||||||
} else {
|
} else {
|
||||||
@ -3185,9 +3192,9 @@ class CanvasGraphics {
|
|||||||
// - heightX (orthogonal to My) has a length: |det(M)| / norm(My).
|
// - heightX (orthogonal to My) has a length: |det(M)| / norm(My).
|
||||||
// heightX and heightY are the thicknesses of the transformed pixel
|
// heightX and heightY are the thicknesses of the transformed pixel
|
||||||
// and they must be both greater or equal to 1.
|
// and they must be both greater or equal to 1.
|
||||||
const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]);
|
const absDet = Math.abs(a * d - b * c);
|
||||||
const normX = Math.hypot(m[0], m[1]);
|
const normX = Math.hypot(a, b);
|
||||||
const normY = Math.hypot(m[2], m[3]);
|
const normY = Math.hypot(c, d);
|
||||||
if (lineWidth === 0) {
|
if (lineWidth === 0) {
|
||||||
scaleX = normY / absDet;
|
scaleX = normY / absDet;
|
||||||
scaleY = normX / absDet;
|
scaleY = normX / absDet;
|
||||||
@ -3197,7 +3204,8 @@ class CanvasGraphics {
|
|||||||
scaleY = normX > baseArea ? normX / baseArea : 1;
|
scaleY = normX > baseArea ? normX / baseArea : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._cachedScaleForStroking = [scaleX, scaleY];
|
this._cachedScaleForStroking[0] = scaleX;
|
||||||
|
this._cachedScaleForStroking[1] = scaleY;
|
||||||
}
|
}
|
||||||
return this._cachedScaleForStroking;
|
return this._cachedScaleForStroking;
|
||||||
}
|
}
|
||||||
@ -3216,11 +3224,9 @@ class CanvasGraphics {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let savedMatrix, savedDashes, savedDashOffset;
|
const dashes = ctx.getLineDash();
|
||||||
if (saveRestore) {
|
if (saveRestore) {
|
||||||
savedMatrix = getCurrentTransform(ctx);
|
ctx.save();
|
||||||
savedDashes = ctx.getLineDash().slice();
|
|
||||||
savedDashOffset = ctx.lineDashOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.scale(scaleX, scaleY);
|
ctx.scale(scaleX, scaleY);
|
||||||
@ -3232,16 +3238,16 @@ class CanvasGraphics {
|
|||||||
// else we'll have some bugs (but only with too thin lines).
|
// else we'll have some bugs (but only with too thin lines).
|
||||||
// Here we take the max... why not taking the min... or something else.
|
// Here we take the max... why not taking the min... or something else.
|
||||||
// Anyway, as said it's buggy when scaleX !== scaleY.
|
// Anyway, as said it's buggy when scaleX !== scaleY.
|
||||||
const scale = Math.max(scaleX, scaleY);
|
if (dashes.length > 0) {
|
||||||
ctx.setLineDash(ctx.getLineDash().map(x => x / scale));
|
const scale = Math.max(scaleX, scaleY);
|
||||||
ctx.lineDashOffset /= scale;
|
ctx.setLineDash(dashes.map(x => x / scale));
|
||||||
|
ctx.lineDashOffset /= scale;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
if (saveRestore) {
|
if (saveRestore) {
|
||||||
ctx.setTransform(...savedMatrix);
|
ctx.restore();
|
||||||
ctx.setLineDash(savedDashes);
|
|
||||||
ctx.lineDashOffset = savedDashOffset;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user