mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-02-08 00:21:11 +01:00
Avoid pattern creation with some basic gradients
Some gradients are represented as patterns in PDF.js, because they mustn't be affected by the current transform. But in most of the cases, the gradient is attached to the origin and the current transform is very basic (dilatation + orthogonal + translation). In those cases, we can avoid creating the pattern because the gradient is transformed into another gradient when the inverse transform is applied.
This commit is contained in:
parent
9f4db380aa
commit
4ff582acbe
@ -71,23 +71,51 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
|
||||
this.matrix = null;
|
||||
}
|
||||
|
||||
_createGradient(ctx) {
|
||||
isOriginBased() {
|
||||
return (
|
||||
this._p0[0] === 0 &&
|
||||
this._p0[1] === 0 &&
|
||||
(!this.isRadial() || (this._p1[0] === 0 && this._p1[1] === 0))
|
||||
);
|
||||
}
|
||||
|
||||
isRadial() {
|
||||
return this._type === "radial";
|
||||
}
|
||||
|
||||
_createGradient(ctx, transform = null) {
|
||||
let grad;
|
||||
let firstPoint = this._p0;
|
||||
let secondPoint = this._p1;
|
||||
if (transform) {
|
||||
firstPoint = firstPoint.slice();
|
||||
secondPoint = secondPoint.slice();
|
||||
Util.applyTransform(firstPoint, transform);
|
||||
Util.applyTransform(secondPoint, transform);
|
||||
}
|
||||
if (this._type === "axial") {
|
||||
grad = ctx.createLinearGradient(
|
||||
this._p0[0],
|
||||
this._p0[1],
|
||||
this._p1[0],
|
||||
this._p1[1]
|
||||
firstPoint[0],
|
||||
firstPoint[1],
|
||||
secondPoint[0],
|
||||
secondPoint[1]
|
||||
);
|
||||
} else if (this._type === "radial") {
|
||||
let r0 = this._r0;
|
||||
let r1 = this._r1;
|
||||
if (transform) {
|
||||
const scale = new Float32Array(2);
|
||||
Util.singularValueDecompose2dScale(transform, scale);
|
||||
r0 *= scale[0];
|
||||
r1 *= scale[0];
|
||||
}
|
||||
grad = ctx.createRadialGradient(
|
||||
this._p0[0],
|
||||
this._p0[1],
|
||||
this._r0,
|
||||
this._p1[0],
|
||||
this._p1[1],
|
||||
this._r1
|
||||
firstPoint[0],
|
||||
firstPoint[1],
|
||||
r0,
|
||||
secondPoint[0],
|
||||
secondPoint[1],
|
||||
r1
|
||||
);
|
||||
}
|
||||
|
||||
@ -100,6 +128,32 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
|
||||
getPattern(ctx, owner, inverse, pathType) {
|
||||
let pattern;
|
||||
if (pathType === PathType.STROKE || pathType === PathType.FILL) {
|
||||
if (this.isOriginBased()) {
|
||||
let transf = Util.transform(inverse, owner.baseTransform);
|
||||
if (this.matrix) {
|
||||
transf = Util.transform(transf, this.matrix);
|
||||
}
|
||||
const precision = 1e-3;
|
||||
const n1 = Math.hypot(transf[0], transf[1]);
|
||||
const n2 = Math.hypot(transf[2], transf[3]);
|
||||
const ps = (transf[0] * transf[2] + transf[1] * transf[3]) / (n1 * n2);
|
||||
if (Math.abs(ps) < precision) {
|
||||
// The images of the basis vectors are orthogonal.
|
||||
if (this.isRadial()) {
|
||||
// If the images of the basis vectors are a square then the
|
||||
// circles are transformed to circles and we can use a gradient
|
||||
// directly.
|
||||
if (Math.abs(n1 - n2) < precision) {
|
||||
return this._createGradient(ctx, transf);
|
||||
}
|
||||
} else {
|
||||
// The rectangles are transformed to rectangles and we can use a
|
||||
// gradient directly.
|
||||
return this._createGradient(ctx, transf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ownerBBox = owner.current.getClippedPathBoundingBox(
|
||||
pathType,
|
||||
getCurrentTransform(ctx)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user