Update to allow setting of globalCompositeOperation when

html <canvas> is used to process multiple tiledImages to blend
is a specific way.
(special handling,
   when compositeOperation is 'source-over' and opacity is 1,
   useSketch is false, otherwise useSketch is true
)
Valid values are 'source-atop', 'source-in', 'source-out',
  'destination-over', 'destination-atop', 'destination-in',
  'destination-out', 'lighter', 'copy' or 'xor'
http://www.w3schools.com/tags/canvas_globalcompositeoperation.asp
This commit is contained in:
Mei-Hui Su 2016-01-06 07:58:36 -08:00
parent 5fa2220fd7
commit ea833a780c
5 changed files with 35 additions and 5 deletions

View File

@ -373,13 +373,14 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{
* @param {Float} opacity The opacity of the blending. * @param {Float} opacity The opacity of the blending.
* @returns {undefined} * @returns {undefined}
*/ */
blendSketch: function(opacity) { blendSketch: function(opacity, compositeOperation) {
if (!this.useCanvas || !this.sketchCanvas) { if (!this.useCanvas || !this.sketchCanvas) {
return; return;
} }
this.context.save(); this.context.save();
this.context.globalAlpha = opacity; this.context.globalAlpha = opacity;
this.context.globalCompositeOperation = compositeOperation;
this.context.drawImage(this.sketchCanvas, 0, 0); this.context.drawImage(this.sketchCanvas, 0, 0);
this.context.restore(); this.context.restore();
}, },

View File

@ -206,6 +206,11 @@
* @property {Number} [opacity=1] * @property {Number} [opacity=1]
* Default opacity of the tiled images (1=opaque, 0=transparent) * Default opacity of the tiled images (1=opaque, 0=transparent)
* *
* @property {String} [compositeOperation='source-over']
* Valid values are 'source-atop', 'source-in', 'source-out',
* 'destination-over', 'destination-atop', 'destination-in',
* 'destination-out', 'lighter', 'copy' or 'xor'.<br>
*
* @property {String|CanvasGradient|CanvasPattern|Function} [placeholderFillStyle=null] * @property {String|CanvasGradient|CanvasPattern|Function} [placeholderFillStyle=null]
* Draws a colored rectangle behind the tile if it is not loaded yet. * Draws a colored rectangle behind the tile if it is not loaded yet.
* You can pass a CSS color value like "#FF8800". * You can pass a CSS color value like "#FF8800".
@ -1044,6 +1049,7 @@ if (typeof define === 'function' && define.amd) {
// APPEARANCE // APPEARANCE
opacity: 1, opacity: 1,
compositeOperation: 'source-over',
placeholderFillStyle: null, placeholderFillStyle: null,
//REFERENCE STRIP SETTINGS //REFERENCE STRIP SETTINGS

View File

@ -268,6 +268,7 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{
context.save(); context.save();
context.globalAlpha = this.opacity; context.globalAlpha = this.opacity;
context.globalCompositeOperation = this.compositeOperation;
//if we are supposed to be rendering fully opaque rectangle, //if we are supposed to be rendering fully opaque rectangle,
//ie its done fading or fading is turned off, and if we are drawing //ie its done fading or fading is turned off, and if we are drawing

View File

@ -65,6 +65,7 @@
* @param {Boolean} [options.alwaysBlend] - See {@link OpenSeadragon.Options}. * @param {Boolean} [options.alwaysBlend] - See {@link OpenSeadragon.Options}.
* @param {Number} [options.minPixelRatio] - See {@link OpenSeadragon.Options}. * @param {Number} [options.minPixelRatio] - See {@link OpenSeadragon.Options}.
* @param {Number} [options.opacity=1] - Opacity the tiled image should be drawn at. * @param {Number} [options.opacity=1] - Opacity the tiled image should be drawn at.
* @param {String} [options.compositeOperation='source-over'] - How a tiled source image are drawn onto an existing image.
* @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}. * @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}.
* @param {String|CanvasGradient|CanvasPattern|Function} [options.placeholderFillStyle] - See {@link OpenSeadragon.Options}. * @param {String|CanvasGradient|CanvasPattern|Function} [options.placeholderFillStyle] - See {@link OpenSeadragon.Options}.
* @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}. * @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}.
@ -131,7 +132,6 @@ $.TiledImage = function( options ) {
_midDraw: false, // Is the tiledImage currently updating the viewport? _midDraw: false, // Is the tiledImage currently updating the viewport?
_needsDraw: true, // Does the tiledImage need to update the viewport again? _needsDraw: true, // Does the tiledImage need to update the viewport again?
_hasOpaqueTile: false, // Do we have even one fully opaque tile? _hasOpaqueTile: false, // Do we have even one fully opaque tile?
//configurable settings //configurable settings
springStiffness: $.DEFAULT_SETTINGS.springStiffness, springStiffness: $.DEFAULT_SETTINGS.springStiffness,
animationTime: $.DEFAULT_SETTINGS.animationTime, animationTime: $.DEFAULT_SETTINGS.animationTime,
@ -145,7 +145,8 @@ $.TiledImage = function( options ) {
debugMode: $.DEFAULT_SETTINGS.debugMode, debugMode: $.DEFAULT_SETTINGS.debugMode,
crossOriginPolicy: $.DEFAULT_SETTINGS.crossOriginPolicy, crossOriginPolicy: $.DEFAULT_SETTINGS.crossOriginPolicy,
placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle, placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle,
opacity: $.DEFAULT_SETTINGS.opacity opacity: $.DEFAULT_SETTINGS.opacity,
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation
}, options ); }, options );
@ -583,6 +584,21 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
this._needsDraw = true; this._needsDraw = true;
}, },
/**
* @returns {String} The TiledImage's current compositeOperation.
*/
getCompositeOperation: function() {
return this.compositeOperation;
},
/**
* @param {String} compositeOperation the tiled image should be drawn with this globalCompositeOperation.
*/
setCompositeOperation: function(compositeOperation) {
this.compositeOperation = compositeOperation;
this._needsDraw = true;
},
// private // private
_setScale: function(scale, immediately) { _setScale: function(scale, immediately) {
var sameTarget = (this._scaleSpring.target.value === scale); var sameTarget = (this._scaleSpring.target.value === scale);
@ -1301,7 +1317,8 @@ function drawTiles( tiledImage, lastDrawn ) {
drawDebugInfo( tiledImage, lastDrawn ); drawDebugInfo( tiledImage, lastDrawn );
return; return;
} }
var useSketch = tiledImage.opacity < 1; var useSketch = (tiledImage.compositeOperation == 'source-over') ? (tiledImage.opacity < 1):true;
if ( useSketch ) { if ( useSketch ) {
tiledImage._drawer._clear( true ); tiledImage._drawer._clear( true );
} }
@ -1360,7 +1377,7 @@ function drawTiles( tiledImage, lastDrawn ) {
} }
if ( useSketch ) { if ( useSketch ) {
tiledImage._drawer.blendSketch( tiledImage.opacity ); tiledImage._drawer.blendSketch( tiledImage.opacity, tiledImage.compositeOperation );
} }
drawDebugInfo( tiledImage, lastDrawn ); drawDebugInfo( tiledImage, lastDrawn );
} }

View File

@ -1207,6 +1207,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
* (portions of the image outside of this area will not be visible). Only works on * (portions of the image outside of this area will not be visible). Only works on
* browsers that support the HTML5 canvas. * browsers that support the HTML5 canvas.
* @param {Number} [options.opacity] Opacity the tiled image should be drawn at by default. * @param {Number} [options.opacity] Opacity the tiled image should be drawn at by default.
* @param {String} [options.compositeOperation] How a tiled source image are drawn onto an existing image.
* @param {Function} [options.success] A function that gets called when the image is * @param {Function} [options.success] A function that gets called when the image is
* successfully added. It's passed the event object which contains a single property: * successfully added. It's passed the event object which contains a single property:
* "item", the resulting TiledImage. * "item", the resulting TiledImage.
@ -1239,6 +1240,9 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
if (options.opacity === undefined) { if (options.opacity === undefined) {
options.opacity = this.opacity; options.opacity = this.opacity;
} }
if (options.compositeOperation === undefined) {
options.compositeOperation = this.compositeOperation;
}
var myQueueItem = { var myQueueItem = {
options: options options: options
@ -1335,6 +1339,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
clip: queueItem.options.clip, clip: queueItem.options.clip,
placeholderFillStyle: queueItem.options.placeholderFillStyle, placeholderFillStyle: queueItem.options.placeholderFillStyle,
opacity: queueItem.options.opacity, opacity: queueItem.options.opacity,
compositeOperation: queueItem.options.compositeOperation,
springStiffness: _this.springStiffness, springStiffness: _this.springStiffness,
animationTime: _this.animationTime, animationTime: _this.animationTime,
minZoomImageRatio: _this.minZoomImageRatio, minZoomImageRatio: _this.minZoomImageRatio,