Improve performance of canvas::rescaleAndStroke by around 30%
The pdf linked in bug 1135277 contains a lot of stroke instructions. In using the Firefox profiler, this patch helps to reduce the overall spent time in this function by 30%.
This commit is contained in:
parent
38287d9435
commit
e5454be0f2
@ -986,7 +986,7 @@ class CanvasGraphics {
|
||||
this.outputScaleY = 1;
|
||||
this.pageColors = pageColors;
|
||||
|
||||
this._cachedScaleForStroking = null;
|
||||
this._cachedScaleForStroking = [-1, 0];
|
||||
this._cachedGetSinglePixelWidth = null;
|
||||
this._cachedBitmapsMap = new Map();
|
||||
}
|
||||
@ -1395,7 +1395,7 @@ class CanvasGraphics {
|
||||
// Graphics state
|
||||
setLineWidth(width) {
|
||||
if (width !== this.current.lineWidth) {
|
||||
this._cachedScaleForStroking = null;
|
||||
this._cachedScaleForStroking[0] = -1;
|
||||
}
|
||||
this.current.lineWidth = width;
|
||||
this.ctx.lineWidth = width;
|
||||
@ -1602,7 +1602,7 @@ class CanvasGraphics {
|
||||
// Ensure that the clipping path is reset (fixes issue6413.pdf).
|
||||
this.pendingClip = null;
|
||||
|
||||
this._cachedScaleForStroking = null;
|
||||
this._cachedScaleForStroking[0] = -1;
|
||||
this._cachedGetSinglePixelWidth = null;
|
||||
}
|
||||
}
|
||||
@ -1610,7 +1610,7 @@ class CanvasGraphics {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2297,7 +2297,7 @@ class CanvasGraphics {
|
||||
if (isTextInvisible || fontSize === 0) {
|
||||
return;
|
||||
}
|
||||
this._cachedScaleForStroking = null;
|
||||
this._cachedScaleForStroking[0] = -1;
|
||||
this._cachedGetSinglePixelWidth = null;
|
||||
|
||||
ctx.save();
|
||||
@ -3160,16 +3160,23 @@ class CanvasGraphics {
|
||||
// The goal of this function is to rescale before setting the
|
||||
// lineWidth in order to have both thicknesses greater or equal
|
||||
// to 1 after transform.
|
||||
if (!this._cachedScaleForStroking) {
|
||||
if (this._cachedScaleForStroking[0] === -1) {
|
||||
const { lineWidth } = this.current;
|
||||
const m = getCurrentTransform(this.ctx);
|
||||
const { a, b, c, d } = this.ctx.getTransform();
|
||||
let scaleX, scaleY;
|
||||
|
||||
if (m[1] === 0 && m[2] === 0) {
|
||||
if (b === 0 && c === 0) {
|
||||
// Fast path
|
||||
const normX = Math.abs(m[0]);
|
||||
const normY = Math.abs(m[3]);
|
||||
if (lineWidth === 0) {
|
||||
const normX = Math.abs(a);
|
||||
const normY = Math.abs(d);
|
||||
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;
|
||||
scaleY = 1 / normY;
|
||||
} else {
|
||||
@ -3185,9 +3192,9 @@ class CanvasGraphics {
|
||||
// - heightX (orthogonal to My) has a length: |det(M)| / norm(My).
|
||||
// heightX and heightY are the thicknesses of the transformed pixel
|
||||
// and they must be both greater or equal to 1.
|
||||
const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]);
|
||||
const normX = Math.hypot(m[0], m[1]);
|
||||
const normY = Math.hypot(m[2], m[3]);
|
||||
const absDet = Math.abs(a * d - b * c);
|
||||
const normX = Math.hypot(a, b);
|
||||
const normY = Math.hypot(c, d);
|
||||
if (lineWidth === 0) {
|
||||
scaleX = normY / absDet;
|
||||
scaleY = normX / absDet;
|
||||
@ -3197,7 +3204,8 @@ class CanvasGraphics {
|
||||
scaleY = normX > baseArea ? normX / baseArea : 1;
|
||||
}
|
||||
}
|
||||
this._cachedScaleForStroking = [scaleX, scaleY];
|
||||
this._cachedScaleForStroking[0] = scaleX;
|
||||
this._cachedScaleForStroking[1] = scaleY;
|
||||
}
|
||||
return this._cachedScaleForStroking;
|
||||
}
|
||||
@ -3216,11 +3224,9 @@ class CanvasGraphics {
|
||||
return;
|
||||
}
|
||||
|
||||
let savedMatrix, savedDashes, savedDashOffset;
|
||||
const dashes = ctx.getLineDash();
|
||||
if (saveRestore) {
|
||||
savedMatrix = getCurrentTransform(ctx);
|
||||
savedDashes = ctx.getLineDash().slice();
|
||||
savedDashOffset = ctx.lineDashOffset;
|
||||
ctx.save();
|
||||
}
|
||||
|
||||
ctx.scale(scaleX, scaleY);
|
||||
@ -3232,16 +3238,16 @@ class CanvasGraphics {
|
||||
// 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.
|
||||
// Anyway, as said it's buggy when scaleX !== scaleY.
|
||||
const scale = Math.max(scaleX, scaleY);
|
||||
ctx.setLineDash(ctx.getLineDash().map(x => x / scale));
|
||||
ctx.lineDashOffset /= scale;
|
||||
if (dashes.length > 0) {
|
||||
const scale = Math.max(scaleX, scaleY);
|
||||
ctx.setLineDash(dashes.map(x => x / scale));
|
||||
ctx.lineDashOffset /= scale;
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
if (saveRestore) {
|
||||
ctx.setTransform(...savedMatrix);
|
||||
ctx.setLineDash(savedDashes);
|
||||
ctx.lineDashOffset = savedDashOffset;
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user