Merge pull request #13565 from brendandahl/fix-pattern-mask

Fix how patterns are applied to image mask objects.
This commit is contained in:
Brendan Dahl 2021-06-16 20:07:57 -07:00 committed by GitHub
commit d6deb95f11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 12 deletions

View File

@ -13,6 +13,11 @@
* limitations under the License. * limitations under the License.
*/ */
import {
createMatrix,
getShadingPattern,
TilingPattern,
} from "./pattern_helper.js";
import { import {
FONT_IDENTITY_MATRIX, FONT_IDENTITY_MATRIX,
IDENTITY_MATRIX, IDENTITY_MATRIX,
@ -27,7 +32,6 @@ import {
Util, Util,
warn, warn,
} from "../shared/util.js"; } from "../shared/util.js";
import { getShadingPattern, TilingPattern } from "./pattern_helper.js";
// <canvas> contexts store most of the state we need natively. // <canvas> contexts store most of the state we need natively.
// However, PDF needs a bit more state, which we store here. // However, PDF needs a bit more state, which we store here.
@ -193,6 +197,17 @@ function addContextCurrentTransform(ctx) {
}; };
} }
function getAdjustmentTransformation(transform, width, height) {
// The pattern will be created at the size of the current page or form object,
// but the mask is usually scaled differently and offset, so we must account
// for these to shift and rescale the pattern to the correctly location.
let patternTransform = createMatrix(transform);
patternTransform = patternTransform.scale(1 / width, -1 / height);
patternTransform = patternTransform.translate(0, -height);
patternTransform = patternTransform.inverse();
return patternTransform;
}
class CachedCanvases { class CachedCanvases {
constructor(canvasFactory) { constructor(canvasFactory) {
this.canvasFactory = canvasFactory; this.canvasFactory = canvasFactory;
@ -2294,8 +2309,16 @@ const CanvasGraphics = (function CanvasGraphicsClosure() {
maskCtx.globalCompositeOperation = "source-in"; maskCtx.globalCompositeOperation = "source-in";
let patternTransform = null;
if (isPatternFill) {
patternTransform = getAdjustmentTransformation(
ctx.mozCurrentTransform,
width,
height
);
}
maskCtx.fillStyle = isPatternFill maskCtx.fillStyle = isPatternFill
? fillColor.getPattern(maskCtx, this) ? fillColor.getPattern(maskCtx, this, false, patternTransform)
: fillColor; : fillColor;
maskCtx.fillRect(0, 0, width, height); maskCtx.fillRect(0, 0, width, height);
@ -2332,14 +2355,23 @@ const CanvasGraphics = (function CanvasGraphicsClosure() {
maskCtx.globalCompositeOperation = "source-in"; maskCtx.globalCompositeOperation = "source-in";
const ctx = this.ctx;
let patternTransform = null;
if (isPatternFill) {
patternTransform = getAdjustmentTransformation(
ctx.mozCurrentTransform,
width,
height
);
}
maskCtx.fillStyle = isPatternFill maskCtx.fillStyle = isPatternFill
? fillColor.getPattern(maskCtx, this) ? fillColor.getPattern(maskCtx, this, false, patternTransform)
: fillColor; : fillColor;
maskCtx.fillRect(0, 0, width, height); maskCtx.fillRect(0, 0, width, height);
maskCtx.restore(); maskCtx.restore();
const ctx = this.ctx;
for (let i = 0, ii = positions.length; i < ii; i += 2) { for (let i = 0, ii = positions.length; i < ii; i += 2) {
ctx.save(); ctx.save();
ctx.transform( ctx.transform(
@ -2381,8 +2413,17 @@ const CanvasGraphics = (function CanvasGraphicsClosure() {
maskCtx.globalCompositeOperation = "source-in"; maskCtx.globalCompositeOperation = "source-in";
let patternTransform = null;
if (isPatternFill) {
patternTransform = getAdjustmentTransformation(
ctx.mozCurrentTransform,
width,
height
);
}
maskCtx.fillStyle = isPatternFill maskCtx.fillStyle = isPatternFill
? fillColor.getPattern(maskCtx, this) ? fillColor.getPattern(maskCtx, this, false, patternTransform)
: fillColor; : fillColor;
maskCtx.fillRect(0, 0, width, height); maskCtx.fillRect(0, 0, width, height);

View File

@ -72,11 +72,11 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
this._matrix = IR[8]; this._matrix = IR[8];
} }
getPattern(ctx, owner, shadingFill) { getPattern(ctx, owner, shadingFill = false, patternTransform = null) {
const tmpCanvas = owner.cachedCanvases.getCanvas( const tmpCanvas = owner.cachedCanvases.getCanvas(
"pattern", "pattern",
ctx.canvas.width, owner.ctx.canvas.width,
ctx.canvas.height, owner.ctx.canvas.height,
true true
); );
@ -121,7 +121,11 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
tmpCtx.fill(); tmpCtx.fill();
const pattern = ctx.createPattern(tmpCanvas.canvas, "repeat"); const pattern = ctx.createPattern(tmpCanvas.canvas, "repeat");
pattern.setTransform(createMatrix(ctx.mozCurrentTransformInverse)); if (patternTransform) {
pattern.setTransform(patternTransform);
} else {
pattern.setTransform(createMatrix(ctx.mozCurrentTransformInverse));
}
return pattern; return pattern;
} }
} }
@ -376,7 +380,7 @@ class MeshShadingPattern extends BaseShadingPattern {
}; };
} }
getPattern(ctx, owner, shadingFill) { getPattern(ctx, owner, shadingFill = false, patternTransform = null) {
applyBoundingBox(ctx, this._bbox); applyBoundingBox(ctx, this._bbox);
let scale; let scale;
if (shadingFill) { if (shadingFill) {
@ -599,7 +603,7 @@ class TilingPattern {
} }
} }
getPattern(ctx, owner, shadingFill) { getPattern(ctx, owner, shadingFill = false, patternTransform = null) {
ctx = this.ctx; ctx = this.ctx;
// PDF spec 8.7.2 NOTE 1: pattern's matrix is relative to initial matrix. // PDF spec 8.7.2 NOTE 1: pattern's matrix is relative to initial matrix.
let matrix = ctx.mozCurrentTransformInverse; let matrix = ctx.mozCurrentTransformInverse;
@ -627,4 +631,4 @@ class TilingPattern {
} }
} }
export { getShadingPattern, TilingPattern }; export { createMatrix, getShadingPattern, TilingPattern };

View File

@ -406,6 +406,7 @@
!issue13193.pdf !issue13193.pdf
!annotation-underline-without-appearance.pdf !annotation-underline-without-appearance.pdf
!issue269_2.pdf !issue269_2.pdf
!issue13372.pdf
!annotation-strikeout.pdf !annotation-strikeout.pdf
!annotation-strikeout-without-appearance.pdf !annotation-strikeout-without-appearance.pdf
!annotation-squiggly.pdf !annotation-squiggly.pdf

BIN
test/pdfs/issue13372.pdf Normal file

Binary file not shown.

View File

@ -1566,6 +1566,12 @@
"rounds": 1, "rounds": 1,
"type": "eq" "type": "eq"
}, },
{ "id": "issue13372",
"file": "pdfs/issue13372.pdf",
"md5": "0bc5329623fd554174c5e7653f904e28",
"rounds": 1,
"type": "eq"
},
{ "id": "simpletype3font-text", { "id": "simpletype3font-text",
"file": "pdfs/simpletype3font.pdf", "file": "pdfs/simpletype3font.pdf",
"md5": "b374c7543920840c61999e9e86939f99", "md5": "b374c7543920840c61999e9e86939f99",