Merge pull request #7176 from yurydelendik/smask-resume
Allow SMask be resumed after restore() and better transform after SMask
This commit is contained in:
commit
be6754a1a0
@ -432,7 +432,8 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
|
|||||||
this.fillAlpha = 1;
|
this.fillAlpha = 1;
|
||||||
this.strokeAlpha = 1;
|
this.strokeAlpha = 1;
|
||||||
this.lineWidth = 1;
|
this.lineWidth = 1;
|
||||||
this.activeSMask = null; // nonclonable field (see the save method below)
|
this.activeSMask = null;
|
||||||
|
this.resumeSMaskCtx = null; // nonclonable field (see the save method below)
|
||||||
|
|
||||||
this.old = old;
|
this.old = old;
|
||||||
}
|
}
|
||||||
@ -869,6 +870,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
endDrawing: function CanvasGraphics_endDrawing() {
|
endDrawing: function CanvasGraphics_endDrawing() {
|
||||||
|
// Finishing all opened operations such as SMask group painting.
|
||||||
|
if (this.current.activeSMask !== null) {
|
||||||
|
this.endSMaskGroup();
|
||||||
|
}
|
||||||
|
|
||||||
this.ctx.restore();
|
this.ctx.restore();
|
||||||
|
|
||||||
if (this.transparentCanvas) {
|
if (this.transparentCanvas) {
|
||||||
@ -977,8 +983,17 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
break;
|
break;
|
||||||
case 'SMask':
|
case 'SMask':
|
||||||
if (this.current.activeSMask) {
|
if (this.current.activeSMask) {
|
||||||
|
// If SMask is currrenly used, it needs to be suspended or
|
||||||
|
// finished. Suspend only makes sense when at least one save()
|
||||||
|
// was performed and state needs to be reverted on restore().
|
||||||
|
if (this.stateStack.length > 0 &&
|
||||||
|
(this.stateStack[this.stateStack.length - 1].activeSMask ===
|
||||||
|
this.current.activeSMask)) {
|
||||||
|
this.suspendSMaskGroup();
|
||||||
|
} else {
|
||||||
this.endSMaskGroup();
|
this.endSMaskGroup();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
this.current.activeSMask = value ? this.tempSMask : null;
|
this.current.activeSMask = value ? this.tempSMask : null;
|
||||||
if (this.current.activeSMask) {
|
if (this.current.activeSMask) {
|
||||||
this.beginSMaskGroup();
|
this.beginSMaskGroup();
|
||||||
@ -1006,6 +1021,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
groupCtx.translate(-activeSMask.offsetX, -activeSMask.offsetY);
|
groupCtx.translate(-activeSMask.offsetX, -activeSMask.offsetY);
|
||||||
groupCtx.transform.apply(groupCtx, currentTransform);
|
groupCtx.transform.apply(groupCtx, currentTransform);
|
||||||
|
|
||||||
|
activeSMask.startTransformInverse = groupCtx.mozCurrentTransformInverse;
|
||||||
|
|
||||||
copyCtxState(currentCtx, groupCtx);
|
copyCtxState(currentCtx, groupCtx);
|
||||||
this.ctx = groupCtx;
|
this.ctx = groupCtx;
|
||||||
this.setGState([
|
this.setGState([
|
||||||
@ -1016,6 +1033,43 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
this.groupStack.push(currentCtx);
|
this.groupStack.push(currentCtx);
|
||||||
this.groupLevel++;
|
this.groupLevel++;
|
||||||
},
|
},
|
||||||
|
suspendSMaskGroup: function CanvasGraphics_endSMaskGroup() {
|
||||||
|
// Similar to endSMaskGroup, the intermediate canvas has to be composed
|
||||||
|
// and future ctx state restored.
|
||||||
|
var groupCtx = this.ctx;
|
||||||
|
this.groupLevel--;
|
||||||
|
this.ctx = this.groupStack.pop();
|
||||||
|
|
||||||
|
composeSMask(this.ctx, this.current.activeSMask, groupCtx);
|
||||||
|
this.ctx.restore();
|
||||||
|
this.ctx.save(); // save is needed since SMask will be resumed.
|
||||||
|
copyCtxState(groupCtx, this.ctx);
|
||||||
|
|
||||||
|
// Saving state for resuming.
|
||||||
|
this.current.resumeSMaskCtx = groupCtx;
|
||||||
|
// Transform was changed in the SMask canvas, reflecting this change on
|
||||||
|
// this.ctx.
|
||||||
|
var deltaTransform = Util.transform(
|
||||||
|
this.current.activeSMask.startTransformInverse,
|
||||||
|
groupCtx.mozCurrentTransform);
|
||||||
|
this.ctx.transform.apply(this.ctx, deltaTransform);
|
||||||
|
|
||||||
|
// SMask was composed, the results at the groupCtx can be cleared.
|
||||||
|
groupCtx.save();
|
||||||
|
groupCtx.setTransform(1, 0, 0, 1, 0, 0);
|
||||||
|
groupCtx.clearRect(0, 0, groupCtx.canvas.width, groupCtx.canvas.height);
|
||||||
|
groupCtx.restore();
|
||||||
|
},
|
||||||
|
resumeSMaskGroup: function CanvasGraphics_endSMaskGroup() {
|
||||||
|
// Resuming state saved by suspendSMaskGroup. We don't need to restore
|
||||||
|
// any groupCtx state since restore() command (the only caller) will do
|
||||||
|
// that for us. See also beginSMaskGroup.
|
||||||
|
var groupCtx = this.current.resumeSMaskCtx;
|
||||||
|
var currentCtx = this.ctx;
|
||||||
|
this.ctx = groupCtx;
|
||||||
|
this.groupStack.push(currentCtx);
|
||||||
|
this.groupLevel++;
|
||||||
|
},
|
||||||
endSMaskGroup: function CanvasGraphics_endSMaskGroup() {
|
endSMaskGroup: function CanvasGraphics_endSMaskGroup() {
|
||||||
var groupCtx = this.ctx;
|
var groupCtx = this.ctx;
|
||||||
this.groupLevel--;
|
this.groupLevel--;
|
||||||
@ -1024,20 +1078,34 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
composeSMask(this.ctx, this.current.activeSMask, groupCtx);
|
composeSMask(this.ctx, this.current.activeSMask, groupCtx);
|
||||||
this.ctx.restore();
|
this.ctx.restore();
|
||||||
copyCtxState(groupCtx, this.ctx);
|
copyCtxState(groupCtx, this.ctx);
|
||||||
|
// Transform was changed in the SMask canvas, reflecting this change on
|
||||||
|
// this.ctx.
|
||||||
|
var deltaTransform = Util.transform(
|
||||||
|
this.current.activeSMask.startTransformInverse,
|
||||||
|
groupCtx.mozCurrentTransform);
|
||||||
|
this.ctx.transform.apply(this.ctx, deltaTransform);
|
||||||
},
|
},
|
||||||
save: function CanvasGraphics_save() {
|
save: function CanvasGraphics_save() {
|
||||||
this.ctx.save();
|
this.ctx.save();
|
||||||
var old = this.current;
|
var old = this.current;
|
||||||
this.stateStack.push(old);
|
this.stateStack.push(old);
|
||||||
this.current = old.clone();
|
this.current = old.clone();
|
||||||
this.current.activeSMask = null;
|
this.current.resumeSMaskCtx = null;
|
||||||
},
|
},
|
||||||
restore: function CanvasGraphics_restore() {
|
restore: function CanvasGraphics_restore() {
|
||||||
if (this.stateStack.length !== 0) {
|
// SMask was suspended, we just need to resume it.
|
||||||
if (this.current.activeSMask !== null) {
|
if (this.current.resumeSMaskCtx) {
|
||||||
|
this.resumeSMaskGroup();
|
||||||
|
}
|
||||||
|
// SMask has to be finished once there is no states that are using the
|
||||||
|
// same SMask.
|
||||||
|
if (this.current.activeSMask !== null && (this.stateStack.length === 0 ||
|
||||||
|
this.stateStack[this.stateStack.length - 1].activeSMask !==
|
||||||
|
this.current.activeSMask)) {
|
||||||
this.endSMaskGroup();
|
this.endSMaskGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.stateStack.length !== 0) {
|
||||||
this.current = this.stateStack.pop();
|
this.current = this.stateStack.pop();
|
||||||
this.ctx.restore();
|
this.ctx.restore();
|
||||||
|
|
||||||
@ -1825,7 +1893,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
scaleY: scaleY,
|
scaleY: scaleY,
|
||||||
subtype: group.smask.subtype,
|
subtype: group.smask.subtype,
|
||||||
backdrop: group.smask.backdrop,
|
backdrop: group.smask.backdrop,
|
||||||
transferMap: group.smask.transferMap || null
|
transferMap: group.smask.transferMap || null,
|
||||||
|
startTransformInverse: null, // used during suspend operation
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Setup the current ctx so when the group is popped we draw it at the
|
// Setup the current ctx so when the group is popped we draw it at the
|
||||||
@ -1845,6 +1914,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
]);
|
]);
|
||||||
this.groupStack.push(currentCtx);
|
this.groupStack.push(currentCtx);
|
||||||
this.groupLevel++;
|
this.groupLevel++;
|
||||||
|
|
||||||
|
// Reseting mask state, masks will be applied on restore of the group.
|
||||||
|
this.current.activeSMask = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
endGroup: function CanvasGraphics_endGroup(group) {
|
endGroup: function CanvasGraphics_endGroup(group) {
|
||||||
|
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -215,6 +215,7 @@
|
|||||||
!issue6069.pdf
|
!issue6069.pdf
|
||||||
!issue6106.pdf
|
!issue6106.pdf
|
||||||
!issue6296.pdf
|
!issue6296.pdf
|
||||||
|
!bug852992_reduced.pdf
|
||||||
!issue6298.pdf
|
!issue6298.pdf
|
||||||
!issue6889.pdf
|
!issue6889.pdf
|
||||||
!bug1001080.pdf
|
!bug1001080.pdf
|
||||||
|
1
test/pdfs/bug1199237.pdf.link
Normal file
1
test/pdfs/bug1199237.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://bugzilla.mozilla.org/attachment.cgi?id=8653724
|
BIN
test/pdfs/bug852992_reduced.pdf
Normal file
BIN
test/pdfs/bug852992_reduced.pdf
Normal file
Binary file not shown.
1
test/pdfs/issue6165.pdf.link
Normal file
1
test/pdfs/issue6165.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://web.archive.org/web/20160405054842/http://www.sec.gov/investor/pubs/sec-guide-to-proxy-brochures.pdf
|
@ -1503,6 +1503,33 @@
|
|||||||
"link": true,
|
"link": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "bug852992",
|
||||||
|
"file": "pdfs/bug852992_reduced.pdf",
|
||||||
|
"md5": "c11439fe3b7f8bc39d89dcff58c50a0c",
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bug1199237",
|
||||||
|
"file": "pdfs/bug1199237.pdf",
|
||||||
|
"md5": "e9a63d3207ccc65a4955d5723546e962",
|
||||||
|
"rounds": 1,
|
||||||
|
"firstPage": 1,
|
||||||
|
"lastPage": 1,
|
||||||
|
"link": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "issue6165",
|
||||||
|
"file": "pdfs/issue6165.pdf",
|
||||||
|
"md5": "84ebde43b9121aa2ef8026388a4f4244",
|
||||||
|
"rounds": 1,
|
||||||
|
"firstPage": 1,
|
||||||
|
"lastPage": 1,
|
||||||
|
"link": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "issue6019-text",
|
"id": "issue6019-text",
|
||||||
"file": "pdfs/issue6019.pdf",
|
"file": "pdfs/issue6019.pdf",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user