Merge pull request #1417 from twpayne/vector-api-image-rotate-and-scale

[vector-api] Image rotate and scale
This commit is contained in:
Tom Payne
2013-12-19 07:41:54 -08:00
6 changed files with 139 additions and 37 deletions

View File

@@ -735,6 +735,7 @@
* @typedef {Object} olx.style.IconOptions
* @property {ol.Pixel|undefined} anchor Anchor.
* @property {null|string|undefined} crossOrigin crossOrigin setting for image.
* @property {number|undefined} scale Scale.
* @property {number|undefined} rotation Rotation.
* @property {ol.Size|undefined} size Icon size in pixel.
* @property {string} src Image source URI.

View File

@@ -5,11 +5,13 @@
goog.provide('ol.render.canvas.Immediate');
goog.require('goog.asserts');
goog.require('goog.vec.Mat4');
goog.require('ol.color');
goog.require('ol.extent');
goog.require('ol.render.IRender');
goog.require('ol.render.canvas');
goog.require('ol.style.Text');
goog.require('ol.vec.Mat4');
@@ -60,11 +62,13 @@ ol.render.canvas.Immediate = function(context, pixelRatio, extent, transform) {
* fillStyle: (string|undefined),
* strokeStyle: (string|undefined),
* lineWidth: (number|undefined),
* image: (HTMLCanvasElement|HTMLVideoElement|Image),
* anchorX: (number|undefined),
* anchorY: (number|undefined),
* image: (HTMLCanvasElement|HTMLVideoElement|Image),
* height: (number|undefined),
* width: (number|undefined),
* scale: number,
* rotation: number,
* lineCap: (string|undefined),
* lineDash: Array.<number>,
* lineJoin: (string|undefined),
@@ -83,10 +87,12 @@ ol.render.canvas.Immediate = function(context, pixelRatio, extent, transform) {
fillStyle: undefined,
strokeStyle: undefined,
lineWidth: undefined,
image: null,
anchorX: undefined,
anchorY: undefined,
image: null,
height: undefined,
rotation: 0,
scale: 1,
width: undefined,
lineCap: undefined,
lineDash: null,
@@ -102,6 +108,12 @@ ol.render.canvas.Immediate = function(context, pixelRatio, extent, transform) {
*/
this.pixelCoordinates_ = [];
/**
* @private
* @type {!goog.vec.Mat4.Number}
*/
this.tmpLocalTransform_ = goog.vec.Mat4.createNumber();
};
@@ -122,6 +134,7 @@ ol.render.canvas.Immediate.prototype.drawImages_ = function(geometry) {
goog.asserts.assert(goog.isDef(state.width));
var pixelCoordinates = ol.geom.transformSimpleGeometry2D(
geometry, this.transform_, this.pixelCoordinates_);
var localTransform = this.tmpLocalTransform_;
var i, ii;
for (i = 0, ii = pixelCoordinates.length; i < ii; i += 2) {
var x = pixelCoordinates[i] - state.anchorX;
@@ -130,8 +143,22 @@ ol.render.canvas.Immediate.prototype.drawImages_ = function(geometry) {
x = (x + 0.5) | 0;
y = (y + 0.5) | 0;
}
if (state.scale != 1 || state.rotation !== 0) {
ol.vec.Mat4.makeTransform2D(localTransform,
x, y, state.scale, state.scale, state.rotation, -x, -y);
context.setTransform(
goog.vec.Mat4.getElement(localTransform, 0, 0),
goog.vec.Mat4.getElement(localTransform, 1, 0),
goog.vec.Mat4.getElement(localTransform, 0, 1),
goog.vec.Mat4.getElement(localTransform, 1, 1),
goog.vec.Mat4.getElement(localTransform, 0, 3),
goog.vec.Mat4.getElement(localTransform, 1, 3));
}
context.drawImage(state.image, x, y, state.width, state.height);
}
if (state.scale != 1 || state.rotation !== 0) {
context.setTransform(1, 0, 0, 1, 0, 0);
}
};
@@ -469,12 +496,14 @@ ol.render.canvas.Immediate.prototype.setImageStyle = function(imageStyle) {
var image = imageStyle.getImage(1);
goog.asserts.assert(!goog.isNull(image));
var state = this.state_;
state.image = image;
state.anchorX = anchor[0];
state.anchorY = anchor[1];
state.image = image;
state.width = size[0];
state.height = size[1];
state.rotation = imageStyle.getRotation();
state.scale = imageStyle.getScale();
state.snapToPixel = imageStyle.getSnapToPixel();
state.width = size[0];
}
};

View File

@@ -109,6 +109,12 @@ ol.render.canvas.Replay = function(pixelRatio, tolerance) {
*/
this.extent_ = ol.extent.createEmpty();
/**
* @private
* @type {!goog.vec.Mat4.Number}
*/
this.tmpLocalTransform_ = goog.vec.Mat4.createNumber();
};
@@ -180,6 +186,7 @@ ol.render.canvas.Replay.prototype.replay_ =
var ii = instructions.length; // end of instructions
var d; // data index
var dd; // end of per-instruction data
var localTransform = this.tmpLocalTransform_;
while (i < ii) {
var instruction = instructions[i];
var type = /** @type {ol.render.canvas.Instruction} */ (instruction[0]);
@@ -202,13 +209,16 @@ ol.render.canvas.Replay.prototype.replay_ =
d = /** @type {number} */ (instruction[1]);
goog.asserts.assert(goog.isNumber(instruction[2]));
dd = /** @type {number} */ (instruction[2]);
var anchorX = /** @type {number} */ (instruction[3]);
var anchorY = /** @type {number} */ (instruction[4]);
var width = /** @type {number} */ (instruction[5]);
var height = /** @type {number} */ (instruction[6]);
var image = /** @type {HTMLCanvasElement|HTMLVideoElement|Image} */
(instruction[7]);
var snapToPixel = /** @type {boolean|undefined} */ (instruction[8]);
(instruction[3]);
// Remaining arguments in DRAW_IMAGE are in alphabetical order
var anchorX = /** @type {number} */ (instruction[4]);
var anchorY = /** @type {number} */ (instruction[5]);
var height = /** @type {number} */ (instruction[6]);
var rotation = /** @type {number} */ (instruction[7]);
var scale = /** @type {number} */ (instruction[8]);
var snapToPixel = /** @type {boolean|undefined} */ (instruction[9]);
var width = /** @type {number} */ (instruction[10]);
for (; d < dd; d += 2) {
var x = pixelCoordinates[d] - anchorX;
var y = pixelCoordinates[d + 1] - anchorY;
@@ -216,7 +226,21 @@ ol.render.canvas.Replay.prototype.replay_ =
x = (x + 0.5) | 0;
y = (y + 0.5) | 0;
}
if (scale != 1 || rotation !== 0) {
ol.vec.Mat4.makeTransform2D(
localTransform, x, y, scale, scale, rotation, -x, -y);
context.setTransform(
goog.vec.Mat4.getElement(localTransform, 0, 0),
goog.vec.Mat4.getElement(localTransform, 1, 0),
goog.vec.Mat4.getElement(localTransform, 0, 1),
goog.vec.Mat4.getElement(localTransform, 1, 1),
goog.vec.Mat4.getElement(localTransform, 0, 3),
goog.vec.Mat4.getElement(localTransform, 1, 3));
}
context.drawImage(image, x, y, width, height);
if (scale != 1 || rotation !== 0) {
context.setTransform(1, 0, 0, 1, 0, 0);
}
}
++i;
} else if (type == ol.render.canvas.Instruction.END_GEOMETRY) {
@@ -454,18 +478,6 @@ ol.render.canvas.ImageReplay = function(pixelRatio, tolerance) {
goog.base(this, pixelRatio, tolerance);
/**
* @private
* @type {number|undefined}
*/
this.anchorX_ = undefined;
/**
* @private
* @type {number|undefined}
*/
this.anchorY_ = undefined;
/**
* @private
* @type {HTMLCanvasElement|HTMLVideoElement|Image}
@@ -478,6 +490,18 @@ ol.render.canvas.ImageReplay = function(pixelRatio, tolerance) {
*/
this.image_ = null;
/**
* @private
* @type {number|undefined}
*/
this.anchorX_ = undefined;
/**
* @private
* @type {number|undefined}
*/
this.anchorY_ = undefined;
/**
* @private
* @type {number|undefined}
@@ -488,7 +512,13 @@ ol.render.canvas.ImageReplay = function(pixelRatio, tolerance) {
* @private
* @type {number|undefined}
*/
this.width_ = undefined;
this.rotation_ = undefined;
/**
* @private
* @type {number|undefined}
*/
this.scale_ = undefined;
/**
* @private
@@ -496,6 +526,12 @@ ol.render.canvas.ImageReplay = function(pixelRatio, tolerance) {
*/
this.snapToPixel_ = undefined;
/**
* @private
* @type {number|undefined}
*/
this.width_ = undefined;
};
goog.inherits(ol.render.canvas.ImageReplay, ol.render.canvas.Replay);
@@ -526,6 +562,8 @@ ol.render.canvas.ImageReplay.prototype.drawPointGeometry =
goog.asserts.assert(goog.isDef(this.anchorX_));
goog.asserts.assert(goog.isDef(this.anchorY_));
goog.asserts.assert(goog.isDef(this.height_));
goog.asserts.assert(goog.isDef(this.rotation_));
goog.asserts.assert(goog.isDef(this.scale_));
goog.asserts.assert(goog.isDef(this.width_));
ol.extent.extend(this.extent_, pointGeometry.getExtent());
this.beginGeometry(pointGeometry);
@@ -535,14 +573,17 @@ ol.render.canvas.ImageReplay.prototype.drawPointGeometry =
var myEnd = this.drawCoordinates_(
flatCoordinates, 0, flatCoordinates.length, stride);
this.instructions.push([
ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
this.anchorX_, this.anchorY_, this.width_, this.height_,
this.image_, this.snapToPixel_
ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_, this.anchorY_, this.height_, this.rotation_, this.scale_,
this.snapToPixel_, this.width_
]);
this.hitDetectionInstructions.push([
ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
this.anchorX_, this.anchorY_, this.width_, this.height_,
this.hitDetectionImage_, this.snapToPixel_
this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_, this.anchorY_, this.height_, this.rotation_, this.scale_,
this.snapToPixel_, this.width_
]);
this.endGeometry(pointGeometry, data);
};
@@ -559,6 +600,8 @@ ol.render.canvas.ImageReplay.prototype.drawMultiPointGeometry =
goog.asserts.assert(goog.isDef(this.anchorX_));
goog.asserts.assert(goog.isDef(this.anchorY_));
goog.asserts.assert(goog.isDef(this.height_));
goog.asserts.assert(goog.isDef(this.rotation_));
goog.asserts.assert(goog.isDef(this.scale_));
goog.asserts.assert(goog.isDef(this.width_));
ol.extent.extend(this.extent_, multiPointGeometry.getExtent());
this.beginGeometry(multiPointGeometry);
@@ -568,14 +611,17 @@ ol.render.canvas.ImageReplay.prototype.drawMultiPointGeometry =
var myEnd = this.drawCoordinates_(
flatCoordinates, 0, flatCoordinates.length, stride);
this.instructions.push([
ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
this.anchorX_, this.anchorY_, this.width_, this.height_,
this.image_, this.snapToPixel_
ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_, this.anchorY_, this.height_, this.rotation_, this.scale_,
this.snapToPixel_, this.width_
]);
this.hitDetectionInstructions.push([
ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
this.anchorX_, this.anchorY_, this.width_, this.height_,
this.hitDetectionImage_, this.snapToPixel_
this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_, this.anchorY_, this.height_, this.rotation_, this.scale_,
this.snapToPixel_, this.width_
]);
this.endGeometry(multiPointGeometry, data);
};
@@ -592,8 +638,10 @@ ol.render.canvas.ImageReplay.prototype.finish = function() {
this.hitDetectionImage_ = null;
this.image_ = null;
this.height_ = undefined;
this.width_ = undefined;
this.scale_ = undefined;
this.rotation_ = undefined;
this.snapToPixel_ = undefined;
this.width_ = undefined;
};
@@ -615,9 +663,11 @@ ol.render.canvas.ImageReplay.prototype.setImageStyle = function(imageStyle) {
this.anchorY_ = anchor[1];
this.hitDetectionImage_ = hitDetectionImage;
this.image_ = image;
this.width_ = size[0];
this.height_ = size[1];
this.rotation_ = imageStyle.getRotation();
this.scale_ = imageStyle.getScale();
this.snapToPixel_ = imageStyle.getSnapToPixel();
this.width_ = size[0];
};

View File

@@ -52,6 +52,7 @@ ol.style.Circle = function(opt_options) {
anchor: [size / 2, size / 2],
imageState: ol.style.ImageState.LOADED,
rotation: 0,
scale: 1,
size: [size, size],
snapToPixel: undefined,
subtractViewRotation: false

View File

@@ -83,10 +83,16 @@ ol.style.Icon = function(opt_options) {
*/
var rotation = goog.isDef(options.rotation) ? options.rotation : 0;
/**
* @type {number}
*/
var scale = goog.isDef(options.scale) ? options.scale : 1;
goog.base(this, {
anchor: anchor,
imageState: ol.style.ImageState.IDLE,
rotation: rotation,
scale: scale,
size: size,
snapToPixel: undefined,
subtractViewRotation: false

View File

@@ -22,6 +22,7 @@ ol.style.ImageState = {
* @typedef {{anchor: ol.Pixel,
* imageState: ol.style.ImageState,
* rotation: number,
* scale: number,
* size: ol.Size,
* snapToPixel: (boolean|undefined),
* subtractViewRotation: boolean}}
@@ -53,10 +54,16 @@ ol.style.Image = function(options) {
/**
* @private
* @type {number|undefined}
* @type {number}
*/
this.rotation_ = options.rotation;
/**
* @private
* @type {number}
*/
this.scale_ = options.scale;
/**
* @protected
* @type {ol.Size}
@@ -104,13 +111,21 @@ ol.style.Image.prototype.getImageState = function() {
/**
* @return {number|undefined} Rotation.
* @return {number} Rotation.
*/
ol.style.Image.prototype.getRotation = function() {
return this.rotation_;
};
/**
* @return {number} Scale.
*/
ol.style.Image.prototype.getScale = function() {
return this.scale_;
};
/**
* @return {ol.Size} Size.
*/