diff --git a/examples/render-geometry.html b/examples/render-geometry.html
new file mode 100644
index 0000000000..0c0af68691
--- /dev/null
+++ b/examples/render-geometry.html
@@ -0,0 +1,9 @@
+---
+layout: example.html
+title: Render geometries to a canvas
+shortdesc: Example of rendering geometries to an arbitrary canvas.
+docs: >
+ This example shows how to render geometries to an arbitrary canvas.
+tags: "render, geometry, canvas"
+---
+
diff --git a/examples/render-geometry.js b/examples/render-geometry.js
new file mode 100644
index 0000000000..7682fbf47e
--- /dev/null
+++ b/examples/render-geometry.js
@@ -0,0 +1,25 @@
+goog.require('ol.geom.LineString');
+goog.require('ol.geom.Point');
+goog.require('ol.geom.Polygon');
+goog.require('ol.render');
+goog.require('ol.style.Circle');
+goog.require('ol.style.Fill');
+goog.require('ol.style.Stroke');
+
+
+var canvas = document.getElementById('canvas');
+var render = ol.render.toContext(canvas.getContext('2d'), {size: [100, 100]});
+
+var fill = new ol.style.Fill({ color: 'blue' });
+var stroke = new ol.style.Stroke({ color: 'black' });
+render.setFillStrokeStyle(fill, stroke);
+render.setImageStyle(new ol.style.Circle({
+ radius: 10,
+ fill: fill,
+ stroke: stroke
+}));
+
+render.drawLineStringGeometry(new ol.geom.LineString([[10, 10], [90, 90]]));
+render.drawPolygonGeometry(
+ new ol.geom.Polygon([[[2, 2], [98, 2], [2, 98], [2, 2]]]));
+render.drawPointGeometry(new ol.geom.Point([88, 88]));
diff --git a/externs/olx.js b/externs/olx.js
index 5ae51dc0f7..7b0ae01895 100644
--- a/externs/olx.js
+++ b/externs/olx.js
@@ -3796,6 +3796,40 @@ olx.layer.VectorTileOptions.prototype.updateWhileInteracting;
olx.layer.VectorTileOptions.prototype.visible;
+/**
+ * Namespace.
+ * @type {Object}
+ */
+olx.render;
+
+
+/**
+ * @typedef {{size: (ol.Size|undefined),
+ * pixelRatio: (number|undefined)}}
+ * @api
+ */
+olx.render.ToContextOptions;
+
+
+/**
+ * Desired size of the canvas in css pixels. When provided, both canvas and css
+ * size will be set according to the `pixelRatio`. If not provided, the current
+ * canvas and css sizes will not be altered.
+ * @type {ol.Size|undefined}
+ * @api
+ */
+olx.render.ToContextOptions.prototype.size;
+
+
+/**
+ * Pixel ratio (canvas pixel to css pixel ratio) for the canvas. Default
+ * is the detected device pixel ratio.
+ * @type {ol.Size|undefined}
+ * @api
+ */
+olx.render.ToContextOptions.prototype.pixelRatio;
+
+
/**
* Namespace.
* @type {Object}
diff --git a/src/ol/render.js b/src/ol/render.js
new file mode 100644
index 0000000000..3686dc178f
--- /dev/null
+++ b/src/ol/render.js
@@ -0,0 +1,43 @@
+goog.provide('ol.render');
+
+goog.require('goog.vec.Mat4');
+goog.require('ol.render.canvas.Immediate');
+goog.require('ol.vec.Mat4');
+
+
+/**
+ * Binds a Canvas Immediate API to a canvas context, to allow drawing geometries
+ * to the context's canvas.
+ * ```js
+ * var canvas = document.createElement('canvas');
+ * var render = ol.render.toContext(canvas.getContext('2d'),
+ * { size: [100, 100] });
+ * render.setFillStrokeStyle(new ol.style.Fill({ color: blue }));
+ * render.drawPolygonGeometry(
+ * new ol.geom.Polygon([[[0, 0], [100, 100], [100, 0], [0, 0]]]));
+ * ```
+ * Note that {@link ol.render.canvas.Immediate#drawAsync} and
+ * {@link ol.render.canvas.Immediate#drawFeature} cannot be used.
+ *
+ * @param {CanvasRenderingContext2D} context Canvas context.
+ * @param {olx.render.ToContextOptions=} opt_options Options.
+ * @return {ol.render.canvas.Immediate} Canvas Immediate.
+ * @api
+ */
+ol.render.toContext = function(context, opt_options) {
+ var canvas = context.canvas;
+ var options = opt_options ? opt_options : {};
+ var pixelRatio = options.pixelRatio || ol.has.DEVICE_PIXEL_RATIO;
+ var size = options.size;
+ if (size) {
+ canvas.width = size[0] * pixelRatio;
+ canvas.height = size[1] * pixelRatio;
+ canvas.style.width = size[0] + 'px';
+ canvas.style.height = size[1] + 'px';
+ }
+ var extent = [0, 0, canvas.width, canvas.height];
+ var transform = ol.vec.Mat4.makeTransform2D(goog.vec.Mat4.createNumber(),
+ 0, 0, pixelRatio, pixelRatio, 0, 0, 0);
+ return new ol.render.canvas.Immediate(context, pixelRatio, extent, transform,
+ 0);
+};
diff --git a/src/ol/render/canvas/canvasimmediate.js b/src/ol/render/canvas/canvasimmediate.js
index 2821b2c8fe..9d0a156e55 100644
--- a/src/ol/render/canvas/canvasimmediate.js
+++ b/src/ol/render/canvas/canvasimmediate.js
@@ -429,11 +429,10 @@ ol.render.canvas.Immediate.prototype.drawAsync = function(zIndex, callback) {
* the current fill and stroke styles.
*
* @param {ol.geom.Circle} circleGeometry Circle geometry.
- * @param {ol.Feature} feature Feature,
* @api
*/
ol.render.canvas.Immediate.prototype.drawCircleGeometry =
- function(circleGeometry, feature) {
+ function(circleGeometry) {
if (!ol.extent.intersects(this.extent_, circleGeometry.getExtent())) {
return;
}
@@ -528,11 +527,10 @@ ol.render.canvas.Immediate.prototype.drawGeometryCollectionGeometry =
* the current style.
*
* @param {ol.geom.Point|ol.render.Feature} pointGeometry Point geometry.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
* @api
*/
ol.render.canvas.Immediate.prototype.drawPointGeometry =
- function(pointGeometry, feature) {
+ function(pointGeometry) {
var flatCoordinates = pointGeometry.getFlatCoordinates();
var stride = pointGeometry.getStride();
if (this.image_) {
@@ -550,11 +548,10 @@ ol.render.canvas.Immediate.prototype.drawPointGeometry =
*
* @param {ol.geom.MultiPoint|ol.render.Feature} multiPointGeometry MultiPoint
* geometry.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
* @api
*/
ol.render.canvas.Immediate.prototype.drawMultiPointGeometry =
- function(multiPointGeometry, feature) {
+ function(multiPointGeometry) {
var flatCoordinates = multiPointGeometry.getFlatCoordinates();
var stride = multiPointGeometry.getStride();
if (this.image_) {
@@ -572,11 +569,10 @@ ol.render.canvas.Immediate.prototype.drawMultiPointGeometry =
*
* @param {ol.geom.LineString|ol.render.Feature} lineStringGeometry Line
* string geometry.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
* @api
*/
ol.render.canvas.Immediate.prototype.drawLineStringGeometry =
- function(lineStringGeometry, feature) {
+ function(lineStringGeometry) {
if (!ol.extent.intersects(this.extent_, lineStringGeometry.getExtent())) {
return;
}
@@ -602,11 +598,10 @@ ol.render.canvas.Immediate.prototype.drawLineStringGeometry =
*
* @param {ol.geom.MultiLineString|ol.render.Feature} multiLineStringGeometry
* MultiLineString geometry.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
* @api
*/
ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry =
- function(multiLineStringGeometry, feature) {
+ function(multiLineStringGeometry) {
var geometryExtent = multiLineStringGeometry.getExtent();
if (!ol.extent.intersects(this.extent_, geometryExtent)) {
return;
@@ -639,11 +634,10 @@ ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry =
*
* @param {ol.geom.Polygon|ol.render.Feature} polygonGeometry Polygon
* geometry.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
* @api
*/
ol.render.canvas.Immediate.prototype.drawPolygonGeometry =
- function(polygonGeometry, feature) {
+ function(polygonGeometry) {
if (!ol.extent.intersects(this.extent_, polygonGeometry.getExtent())) {
return;
}
@@ -676,11 +670,10 @@ ol.render.canvas.Immediate.prototype.drawPolygonGeometry =
* Render MultiPolygon geometry into the canvas. Rendering is immediate and
* uses the current style.
* @param {ol.geom.MultiPolygon} multiPolygonGeometry MultiPolygon geometry.
- * @param {ol.Feature} feature Feature.
* @api
*/
ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry =
- function(multiPolygonGeometry, feature) {
+ function(multiPolygonGeometry) {
if (!ol.extent.intersects(this.extent_, multiPolygonGeometry.getExtent())) {
return;
}
diff --git a/test/spec/ol/render.test.js b/test/spec/ol/render.test.js
new file mode 100644
index 0000000000..662ad0fb4c
--- /dev/null
+++ b/test/spec/ol/render.test.js
@@ -0,0 +1,37 @@
+goog.provide('ol.test.render');
+
+describe('ol.render', function() {
+
+ describe('toContext', function() {
+
+ it('creates an ol.render.canvas.Immediate and sets defaults', function() {
+ var canvas = document.createElement('canvas');
+ var render = ol.render.toContext(canvas.getContext('2d'));
+ expect(render).to.be.a(ol.render.canvas.Immediate);
+ expect(render.pixelRatio_).to.be(ol.has.DEVICE_PIXEL_RATIO);
+ });
+
+ it('sets size and pixel ratio from options', function() {
+ var canvas = document.createElement('canvas');
+ var pixelRatio = 1.5;
+ var size = [100, 50];
+ var render = ol.render.toContext(canvas.getContext('2d'),
+ {pixelRatio: pixelRatio, size: size});
+ expect(render.pixelRatio_).to.be(pixelRatio);
+ expect(render.extent_).to.eql(
+ [0, 0, size[0] * pixelRatio, size[1] * pixelRatio]);
+ expect(canvas.style.width).to.be(size[0] + 'px');
+ expect(canvas.style.height).to.be(size[1] + 'px');
+ var transform = ol.vec.Mat4.makeTransform2D(goog.vec.Mat4.createNumber(),
+ 0, 0, pixelRatio, pixelRatio, 0, 0, 0);
+ expect(ol.vec.Mat4.equals2D(render.transform_, transform)).to.be.ok();
+ });
+ });
+
+});
+
+
+goog.require('goog.vec.Mat4');
+goog.require('ol.render');
+goog.require('ol.render.canvas.Immediate');
+goog.require('ol.vec.Mat4');