summaryrefslogtreecommitdiff
path: root/misc/openlayers/lib/OpenLayers/Renderer/Canvas.js
diff options
context:
space:
mode:
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Renderer/Canvas.js')
-rw-r--r--misc/openlayers/lib/OpenLayers/Renderer/Canvas.js906
1 files changed, 0 insertions, 906 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Renderer/Canvas.js b/misc/openlayers/lib/OpenLayers/Renderer/Canvas.js
deleted file mode 100644
index 61a327c..0000000
--- a/misc/openlayers/lib/OpenLayers/Renderer/Canvas.js
+++ /dev/null
@@ -1,906 +0,0 @@
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/Renderer.js
- */
-
-/**
- * Class: OpenLayers.Renderer.Canvas
- * A renderer based on the 2D 'canvas' drawing element.
- *
- * Inherits:
- * - <OpenLayers.Renderer>
- */
-OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, {
-
- /**
- * APIProperty: hitDetection
- * {Boolean} Allow for hit detection of features. Default is true.
- */
- hitDetection: true,
-
- /**
- * Property: hitOverflow
- * {Number} The method for converting feature identifiers to color values
- * supports 16777215 sequential values. Two features cannot be
- * predictably detected if their identifiers differ by more than this
- * value. The hitOverflow allows for bigger numbers (but the
- * difference in values is still limited).
- */
- hitOverflow: 0,
-
- /**
- * Property: canvas
- * {Canvas} The canvas context object.
- */
- canvas: null,
-
- /**
- * Property: features
- * {Object} Internal object of feature/style pairs for use in redrawing the layer.
- */
- features: null,
-
- /**
- * Property: pendingRedraw
- * {Boolean} The renderer needs a redraw call to render features added while
- * the renderer was locked.
- */
- pendingRedraw: false,
-
- /**
- * Property: cachedSymbolBounds
- * {Object} Internal cache of calculated symbol extents.
- */
- cachedSymbolBounds: {},
-
- /**
- * Constructor: OpenLayers.Renderer.Canvas
- *
- * Parameters:
- * containerID - {<String>}
- * options - {Object} Optional properties to be set on the renderer.
- */
- initialize: function(containerID, options) {
- OpenLayers.Renderer.prototype.initialize.apply(this, arguments);
- this.root = document.createElement("canvas");
- this.container.appendChild(this.root);
- this.canvas = this.root.getContext("2d");
- this.features = {};
- if (this.hitDetection) {
- this.hitCanvas = document.createElement("canvas");
- this.hitContext = this.hitCanvas.getContext("2d");
- }
- },
-
- /**
- * Method: setExtent
- * Set the visible part of the layer.
- *
- * Parameters:
- * extent - {<OpenLayers.Bounds>}
- * resolutionChanged - {Boolean}
- *
- * Returns:
- * {Boolean} true to notify the layer that the new extent does not exceed
- * the coordinate range, and the features will not need to be redrawn.
- * False otherwise.
- */
- setExtent: function() {
- OpenLayers.Renderer.prototype.setExtent.apply(this, arguments);
- // always redraw features
- return false;
- },
-
- /**
- * Method: eraseGeometry
- * Erase a geometry from the renderer. Because the Canvas renderer has
- * 'memory' of the features that it has drawn, we have to remove the
- * feature so it doesn't redraw.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * featureId - {String}
- */
- eraseGeometry: function(geometry, featureId) {
- this.eraseFeatures(this.features[featureId][0]);
- },
-
- /**
- * APIMethod: supported
- *
- * Returns:
- * {Boolean} Whether or not the browser supports the renderer class
- */
- supported: function() {
- return OpenLayers.CANVAS_SUPPORTED;
- },
-
- /**
- * Method: setSize
- * Sets the size of the drawing surface.
- *
- * Once the size is updated, redraw the canvas.
- *
- * Parameters:
- * size - {<OpenLayers.Size>}
- */
- setSize: function(size) {
- this.size = size.clone();
- var root = this.root;
- root.style.width = size.w + "px";
- root.style.height = size.h + "px";
- root.width = size.w;
- root.height = size.h;
- this.resolution = null;
- if (this.hitDetection) {
- var hitCanvas = this.hitCanvas;
- hitCanvas.style.width = size.w + "px";
- hitCanvas.style.height = size.h + "px";
- hitCanvas.width = size.w;
- hitCanvas.height = size.h;
- }
- },
-
- /**
- * Method: drawFeature
- * Draw the feature. Stores the feature in the features list,
- * then redraws the layer.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- * style - {<Object>}
- *
- * Returns:
- * {Boolean} The feature has been drawn completely. If the feature has no
- * geometry, undefined will be returned. If the feature is not rendered
- * for other reasons, false will be returned.
- */
- drawFeature: function(feature, style) {
- var rendered;
- if (feature.geometry) {
- style = this.applyDefaultSymbolizer(style || feature.style);
- // don't render if display none or feature outside extent
- var bounds = feature.geometry.getBounds();
-
- var worldBounds;
- if (this.map.baseLayer && this.map.baseLayer.wrapDateLine) {
- worldBounds = this.map.getMaxExtent();
- }
-
- var intersects = bounds && bounds.intersectsBounds(this.extent, {worldBounds: worldBounds});
-
- rendered = (style.display !== "none") && !!bounds && intersects;
- if (rendered) {
- // keep track of what we have rendered for redraw
- this.features[feature.id] = [feature, style];
- }
- else {
- // remove from features tracked for redraw
- delete(this.features[feature.id]);
- }
- this.pendingRedraw = true;
- }
- if (this.pendingRedraw && !this.locked) {
- this.redraw();
- this.pendingRedraw = false;
- }
- return rendered;
- },
-
- /**
- * Method: drawGeometry
- * Used when looping (in redraw) over the features; draws
- * the canvas.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- */
- drawGeometry: function(geometry, style, featureId) {
- var className = geometry.CLASS_NAME;
- if ((className == "OpenLayers.Geometry.Collection") ||
- (className == "OpenLayers.Geometry.MultiPoint") ||
- (className == "OpenLayers.Geometry.MultiLineString") ||
- (className == "OpenLayers.Geometry.MultiPolygon")) {
- for (var i = 0; i < geometry.components.length; i++) {
- this.drawGeometry(geometry.components[i], style, featureId);
- }
- return;
- }
- switch (geometry.CLASS_NAME) {
- case "OpenLayers.Geometry.Point":
- this.drawPoint(geometry, style, featureId);
- break;
- case "OpenLayers.Geometry.LineString":
- this.drawLineString(geometry, style, featureId);
- break;
- case "OpenLayers.Geometry.LinearRing":
- this.drawLinearRing(geometry, style, featureId);
- break;
- case "OpenLayers.Geometry.Polygon":
- this.drawPolygon(geometry, style, featureId);
- break;
- default:
- break;
- }
- },
-
- /**
- * Method: drawExternalGraphic
- * Called to draw External graphics.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- */
- drawExternalGraphic: function(geometry, style, featureId) {
- var img = new Image();
-
- var title = style.title || style.graphicTitle;
- if (title) {
- img.title = title;
- }
-
- var width = style.graphicWidth || style.graphicHeight;
- var height = style.graphicHeight || style.graphicWidth;
- width = width ? width : style.pointRadius * 2;
- height = height ? height : style.pointRadius * 2;
- var xOffset = (style.graphicXOffset != undefined) ?
- style.graphicXOffset : -(0.5 * width);
- var yOffset = (style.graphicYOffset != undefined) ?
- style.graphicYOffset : -(0.5 * height);
-
- var opacity = style.graphicOpacity || style.fillOpacity;
-
- var onLoad = function() {
- if(!this.features[featureId]) {
- return;
- }
- var pt = this.getLocalXY(geometry);
- var p0 = pt[0];
- var p1 = pt[1];
- if(!isNaN(p0) && !isNaN(p1)) {
- var x = (p0 + xOffset) | 0;
- var y = (p1 + yOffset) | 0;
- var canvas = this.canvas;
- canvas.globalAlpha = opacity;
- var factor = OpenLayers.Renderer.Canvas.drawImageScaleFactor ||
- (OpenLayers.Renderer.Canvas.drawImageScaleFactor =
- /android 2.1/.test(navigator.userAgent.toLowerCase()) ?
- // 320 is the screen width of the G1 phone, for
- // which drawImage works out of the box.
- 320 / window.screen.width : 1
- );
- canvas.drawImage(
- img, x*factor, y*factor, width*factor, height*factor
- );
- if (this.hitDetection) {
- this.setHitContextStyle("fill", featureId);
- this.hitContext.fillRect(x, y, width, height);
- }
- }
- };
-
- img.onload = OpenLayers.Function.bind(onLoad, this);
- img.src = style.externalGraphic;
- },
-
- /**
- * Method: drawNamedSymbol
- * Called to draw Well Known Graphic Symbol Name.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- */
- drawNamedSymbol: function(geometry, style, featureId) {
- var x, y, cx, cy, i, symbolBounds, scaling, angle;
- var unscaledStrokeWidth;
- var deg2rad = Math.PI / 180.0;
-
- var symbol = OpenLayers.Renderer.symbol[style.graphicName];
-
- if (!symbol) {
- throw new Error(style.graphicName + ' is not a valid symbol name');
- }
-
- if (!symbol.length || symbol.length < 2) return;
-
- var pt = this.getLocalXY(geometry);
- var p0 = pt[0];
- var p1 = pt[1];
-
- if (isNaN(p0) || isNaN(p1)) return;
-
- // Use rounded line caps
- this.canvas.lineCap = "round";
- this.canvas.lineJoin = "round";
-
- if (this.hitDetection) {
- this.hitContext.lineCap = "round";
- this.hitContext.lineJoin = "round";
- }
-
- // Scale and rotate symbols, using precalculated bounds whenever possible.
- if (style.graphicName in this.cachedSymbolBounds) {
- symbolBounds = this.cachedSymbolBounds[style.graphicName];
- } else {
- symbolBounds = new OpenLayers.Bounds();
- for(i = 0; i < symbol.length; i+=2) {
- symbolBounds.extend(new OpenLayers.LonLat(symbol[i], symbol[i+1]));
- }
- this.cachedSymbolBounds[style.graphicName] = symbolBounds;
- }
-
- // Push symbol scaling, translation and rotation onto the transformation stack in reverse order.
- // Don't forget to apply all canvas transformations to the hitContext canvas as well(!)
- this.canvas.save();
- if (this.hitDetection) { this.hitContext.save(); }
-
- // Step 3: place symbol at the desired location
- this.canvas.translate(p0,p1);
- if (this.hitDetection) { this.hitContext.translate(p0,p1); }
-
- // Step 2a. rotate the symbol if necessary
- angle = deg2rad * style.rotation; // will be NaN when style.rotation is undefined.
- if (!isNaN(angle)) {
- this.canvas.rotate(angle);
- if (this.hitDetection) { this.hitContext.rotate(angle); }
- }
-
- // // Step 2: scale symbol such that pointRadius equals half the maximum symbol dimension.
- scaling = 2.0 * style.pointRadius / Math.max(symbolBounds.getWidth(), symbolBounds.getHeight());
- this.canvas.scale(scaling,scaling);
- if (this.hitDetection) { this.hitContext.scale(scaling,scaling); }
-
- // Step 1: center the symbol at the origin
- cx = symbolBounds.getCenterLonLat().lon;
- cy = symbolBounds.getCenterLonLat().lat;
- this.canvas.translate(-cx,-cy);
- if (this.hitDetection) { this.hitContext.translate(-cx,-cy); }
-
- // Don't forget to scale stroke widths, because they are affected by canvas scale transformations as well(!)
- // Alternative: scale symbol coordinates manually, so stroke width scaling is not needed anymore.
- unscaledStrokeWidth = style.strokeWidth;
- style.strokeWidth = unscaledStrokeWidth / scaling;
-
- if (style.fill !== false) {
- this.setCanvasStyle("fill", style);
- this.canvas.beginPath();
- for (i=0; i<symbol.length; i=i+2) {
- x = symbol[i];
- y = symbol[i+1];
- if (i == 0) this.canvas.moveTo(x,y);
- this.canvas.lineTo(x,y);
- }
- this.canvas.closePath();
- this.canvas.fill();
-
- if (this.hitDetection) {
- this.setHitContextStyle("fill", featureId, style);
- this.hitContext.beginPath();
- for (i=0; i<symbol.length; i=i+2) {
- x = symbol[i];
- y = symbol[i+1];
- if (i == 0) this.canvas.moveTo(x,y);
- this.hitContext.lineTo(x,y);
- }
- this.hitContext.closePath();
- this.hitContext.fill();
- }
- }
-
- if (style.stroke !== false) {
- this.setCanvasStyle("stroke", style);
- this.canvas.beginPath();
- for (i=0; i<symbol.length; i=i+2) {
- x = symbol[i];
- y = symbol[i+1];
- if (i == 0) this.canvas.moveTo(x,y);
- this.canvas.lineTo(x,y);
- }
- this.canvas.closePath();
- this.canvas.stroke();
-
-
- if (this.hitDetection) {
- this.setHitContextStyle("stroke", featureId, style, scaling);
- this.hitContext.beginPath();
- for (i=0; i<symbol.length; i=i+2) {
- x = symbol[i];
- y = symbol[i+1];
- if (i == 0) this.hitContext.moveTo(x,y);
- this.hitContext.lineTo(x,y);
- }
- this.hitContext.closePath();
- this.hitContext.stroke();
- }
-
- }
-
- style.strokeWidth = unscaledStrokeWidth;
- this.canvas.restore();
- if (this.hitDetection) { this.hitContext.restore(); }
- this.setCanvasStyle("reset");
- },
-
- /**
- * Method: setCanvasStyle
- * Prepare the canvas for drawing by setting various global settings.
- *
- * Parameters:
- * type - {String} one of 'stroke', 'fill', or 'reset'
- * style - {Object} Symbolizer hash
- */
- setCanvasStyle: function(type, style) {
- if (type === "fill") {
- this.canvas.globalAlpha = style['fillOpacity'];
- this.canvas.fillStyle = style['fillColor'];
- } else if (type === "stroke") {
- this.canvas.globalAlpha = style['strokeOpacity'];
- this.canvas.strokeStyle = style['strokeColor'];
- this.canvas.lineWidth = style['strokeWidth'];
- } else {
- this.canvas.globalAlpha = 0;
- this.canvas.lineWidth = 1;
- }
- },
-
- /**
- * Method: featureIdToHex
- * Convert a feature ID string into an RGB hex string.
- *
- * Parameters:
- * featureId - {String} Feature id
- *
- * Returns:
- * {String} RGB hex string.
- */
- featureIdToHex: function(featureId) {
- var id = Number(featureId.split("_").pop()) + 1; // zero for no feature
- if (id >= 16777216) {
- this.hitOverflow = id - 16777215;
- id = id % 16777216 + 1;
- }
- var hex = "000000" + id.toString(16);
- var len = hex.length;
- hex = "#" + hex.substring(len-6, len);
- return hex;
- },
-
- /**
- * Method: setHitContextStyle
- * Prepare the hit canvas for drawing by setting various global settings.
- *
- * Parameters:
- * type - {String} one of 'stroke', 'fill', or 'reset'
- * featureId - {String} The feature id.
- * symbolizer - {<OpenLayers.Symbolizer>} The symbolizer.
- */
- setHitContextStyle: function(type, featureId, symbolizer, strokeScaling) {
- var hex = this.featureIdToHex(featureId);
- if (type == "fill") {
- this.hitContext.globalAlpha = 1.0;
- this.hitContext.fillStyle = hex;
- } else if (type == "stroke") {
- this.hitContext.globalAlpha = 1.0;
- this.hitContext.strokeStyle = hex;
- // bump up stroke width to deal with antialiasing. If strokeScaling is defined, we're rendering a symbol
- // on a transformed canvas, so the antialias width bump has to scale as well.
- if (typeof strokeScaling === "undefined") {
- this.hitContext.lineWidth = symbolizer.strokeWidth + 2;
- } else {
- if (!isNaN(strokeScaling)) { this.hitContext.lineWidth = symbolizer.strokeWidth + 2.0 / strokeScaling; }
- }
- } else {
- this.hitContext.globalAlpha = 0;
- this.hitContext.lineWidth = 1;
- }
- },
-
- /**
- * Method: drawPoint
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- */
- drawPoint: function(geometry, style, featureId) {
- if(style.graphic !== false) {
- if(style.externalGraphic) {
- this.drawExternalGraphic(geometry, style, featureId);
- } else if (style.graphicName && (style.graphicName != "circle")) {
- this.drawNamedSymbol(geometry, style, featureId);
- } else {
- var pt = this.getLocalXY(geometry);
- var p0 = pt[0];
- var p1 = pt[1];
- if(!isNaN(p0) && !isNaN(p1)) {
- var twoPi = Math.PI*2;
- var radius = style.pointRadius;
- if(style.fill !== false) {
- this.setCanvasStyle("fill", style);
- this.canvas.beginPath();
- this.canvas.arc(p0, p1, radius, 0, twoPi, true);
- this.canvas.fill();
- if (this.hitDetection) {
- this.setHitContextStyle("fill", featureId, style);
- this.hitContext.beginPath();
- this.hitContext.arc(p0, p1, radius, 0, twoPi, true);
- this.hitContext.fill();
- }
- }
-
- if(style.stroke !== false) {
- this.setCanvasStyle("stroke", style);
- this.canvas.beginPath();
- this.canvas.arc(p0, p1, radius, 0, twoPi, true);
- this.canvas.stroke();
- if (this.hitDetection) {
- this.setHitContextStyle("stroke", featureId, style);
- this.hitContext.beginPath();
- this.hitContext.arc(p0, p1, radius, 0, twoPi, true);
- this.hitContext.stroke();
- }
- this.setCanvasStyle("reset");
- }
- }
- }
- }
- },
-
- /**
- * Method: drawLineString
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- */
- drawLineString: function(geometry, style, featureId) {
- style = OpenLayers.Util.applyDefaults({fill: false}, style);
- this.drawLinearRing(geometry, style, featureId);
- },
-
- /**
- * Method: drawLinearRing
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- */
- drawLinearRing: function(geometry, style, featureId) {
- if (style.fill !== false) {
- this.setCanvasStyle("fill", style);
- this.renderPath(this.canvas, geometry, style, featureId, "fill");
- if (this.hitDetection) {
- this.setHitContextStyle("fill", featureId, style);
- this.renderPath(this.hitContext, geometry, style, featureId, "fill");
- }
- }
- if (style.stroke !== false) {
- this.setCanvasStyle("stroke", style);
- this.renderPath(this.canvas, geometry, style, featureId, "stroke");
- if (this.hitDetection) {
- this.setHitContextStyle("stroke", featureId, style);
- this.renderPath(this.hitContext, geometry, style, featureId, "stroke");
- }
- }
- this.setCanvasStyle("reset");
- },
-
- /**
- * Method: renderPath
- * Render a path with stroke and optional fill.
- */
- renderPath: function(context, geometry, style, featureId, type) {
- var components = geometry.components;
- var len = components.length;
- context.beginPath();
- var start = this.getLocalXY(components[0]);
- var x = start[0];
- var y = start[1];
- if (!isNaN(x) && !isNaN(y)) {
- context.moveTo(start[0], start[1]);
- for (var i=1; i<len; ++i) {
- var pt = this.getLocalXY(components[i]);
- context.lineTo(pt[0], pt[1]);
- }
- if (type === "fill") {
- context.fill();
- } else {
- context.stroke();
- }
- }
- },
-
- /**
- * Method: drawPolygon
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- */
- drawPolygon: function(geometry, style, featureId) {
- var components = geometry.components;
- var len = components.length;
- this.drawLinearRing(components[0], style, featureId);
- // erase inner rings
- for (var i=1; i<len; ++i) {
- /**
- * Note that this is overly agressive. Here we punch holes through
- * all previously rendered features on the same canvas. A better
- * solution for polygons with interior rings would be to draw the
- * polygon on a sketch canvas first. We could erase all holes
- * there and then copy the drawing to the layer canvas.
- * TODO: http://trac.osgeo.org/openlayers/ticket/3130
- */
- this.canvas.globalCompositeOperation = "destination-out";
- if (this.hitDetection) {
- this.hitContext.globalCompositeOperation = "destination-out";
- }
- this.drawLinearRing(
- components[i],
- OpenLayers.Util.applyDefaults({stroke: false, fillOpacity: 1.0}, style),
- featureId
- );
- this.canvas.globalCompositeOperation = "source-over";
- if (this.hitDetection) {
- this.hitContext.globalCompositeOperation = "source-over";
- }
- this.drawLinearRing(
- components[i],
- OpenLayers.Util.applyDefaults({fill: false}, style),
- featureId
- );
- }
- },
-
- /**
- * Method: drawText
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * location - {<OpenLayers.Point>}
- * style - {Object}
- */
- drawText: function(location, style) {
- var pt = this.getLocalXY(location);
-
- this.setCanvasStyle("reset");
- this.canvas.fillStyle = style.fontColor;
- this.canvas.globalAlpha = style.fontOpacity || 1.0;
- var fontStyle = [style.fontStyle ? style.fontStyle : "normal",
- "normal", // "font-variant" not supported
- style.fontWeight ? style.fontWeight : "normal",
- style.fontSize ? style.fontSize : "1em",
- style.fontFamily ? style.fontFamily : "sans-serif"].join(" ");
- var labelRows = style.label.split('\n');
- var numRows = labelRows.length;
- if (this.canvas.fillText) {
- // HTML5
- this.canvas.font = fontStyle;
- this.canvas.textAlign =
- OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]] ||
- "center";
- this.canvas.textBaseline =
- OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[1]] ||
- "middle";
- var vfactor =
- OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];
- if (vfactor == null) {
- vfactor = -.5;
- }
- var lineHeight =
- this.canvas.measureText('Mg').height ||
- this.canvas.measureText('xx').width;
- pt[1] += lineHeight*vfactor*(numRows-1);
- for (var i = 0; i < numRows; i++) {
- if (style.labelOutlineWidth) {
- this.canvas.save();
- this.canvas.globalAlpha = style.labelOutlineOpacity || style.fontOpacity || 1.0;
- this.canvas.strokeStyle = style.labelOutlineColor;
- this.canvas.lineWidth = style.labelOutlineWidth;
- this.canvas.strokeText(labelRows[i], pt[0], pt[1] + (lineHeight*i) + 1);
- this.canvas.restore();
- }
- this.canvas.fillText(labelRows[i], pt[0], pt[1] + (lineHeight*i));
- }
- } else if (this.canvas.mozDrawText) {
- // Mozilla pre-Gecko1.9.1 (<FF3.1)
- this.canvas.mozTextStyle = fontStyle;
- // No built-in text alignment, so we measure and adjust the position
- var hfactor =
- OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[0]];
- if (hfactor == null) {
- hfactor = -.5;
- }
- var vfactor =
- OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];
- if (vfactor == null) {
- vfactor = -.5;
- }
- var lineHeight = this.canvas.mozMeasureText('xx');
- pt[1] += lineHeight*(1 + (vfactor*numRows));
- for (var i = 0; i < numRows; i++) {
- var x = pt[0] + (hfactor*this.canvas.mozMeasureText(labelRows[i]));
- var y = pt[1] + (i*lineHeight);
- this.canvas.translate(x, y);
- this.canvas.mozDrawText(labelRows[i]);
- this.canvas.translate(-x, -y);
- }
- }
- this.setCanvasStyle("reset");
- },
-
- /**
- * Method: getLocalXY
- * transform geographic xy into pixel xy
- *
- * Parameters:
- * point - {<OpenLayers.Geometry.Point>}
- */
- getLocalXY: function(point) {
- var resolution = this.getResolution();
- var extent = this.extent;
- var x = ((point.x - this.featureDx) / resolution + (-extent.left / resolution));
- var y = ((extent.top / resolution) - point.y / resolution);
- return [x, y];
- },
-
- /**
- * Method: clear
- * Clear all vectors from the renderer.
- */
- clear: function() {
- var height = this.root.height;
- var width = this.root.width;
- this.canvas.clearRect(0, 0, width, height);
- this.features = {};
- if (this.hitDetection) {
- this.hitContext.clearRect(0, 0, width, height);
- }
- },
-
- /**
- * Method: getFeatureIdFromEvent
- * Returns a feature id from an event on the renderer.
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- *
- * Returns:
- * {<OpenLayers.Feature.Vector} A feature or undefined. This method returns a
- * feature instead of a feature id to avoid an unnecessary lookup on the
- * layer.
- */
- getFeatureIdFromEvent: function(evt) {
- var featureId, feature;
-
- if (this.hitDetection && this.root.style.display !== "none") {
- // this dragging check should go in the feature handler
- if (!this.map.dragging) {
- var xy = evt.xy;
- var x = xy.x | 0;
- var y = xy.y | 0;
- var data = this.hitContext.getImageData(x, y, 1, 1).data;
- if (data[3] === 255) { // antialiased
- var id = data[2] + (256 * (data[1] + (256 * data[0])));
- if (id) {
- featureId = "OpenLayers_Feature_Vector_" + (id - 1 + this.hitOverflow);
- try {
- feature = this.features[featureId][0];
- } catch(err) {
- // Because of antialiasing on the canvas, when the hit location is at a point where the edge of
- // one symbol intersects the interior of another symbol, a wrong hit color (and therefore id) results.
- // todo: set Antialiasing = 'off' on the hitContext as soon as browsers allow it.
- }
- }
- }
- }
- }
- return feature;
- },
-
- /**
- * Method: eraseFeatures
- * This is called by the layer to erase features; removes the feature from
- * the list, then redraws the layer.
- *
- * Parameters:
- * features - {Array(<OpenLayers.Feature.Vector>)}
- */
- eraseFeatures: function(features) {
- if(!(OpenLayers.Util.isArray(features))) {
- features = [features];
- }
- for(var i=0; i<features.length; ++i) {
- delete this.features[features[i].id];
- }
- this.redraw();
- },
-
- /**
- * Method: redraw
- * The real 'meat' of the function: any time things have changed,
- * redraw() can be called to loop over all the data and (you guessed
- * it) redraw it. Unlike Elements-based Renderers, we can't interact
- * with things once they're drawn, to remove them, for example, so
- * instead we have to just clear everything and draw from scratch.
- */
- redraw: function() {
- if (!this.locked) {
- var height = this.root.height;
- var width = this.root.width;
- this.canvas.clearRect(0, 0, width, height);
- if (this.hitDetection) {
- this.hitContext.clearRect(0, 0, width, height);
- }
- var labelMap = [];
- var feature, geometry, style;
- var worldBounds = (this.map.baseLayer && this.map.baseLayer.wrapDateLine) && this.map.getMaxExtent();
- for (var id in this.features) {
- if (!this.features.hasOwnProperty(id)) { continue; }
- feature = this.features[id][0];
- geometry = feature.geometry;
- this.calculateFeatureDx(geometry.getBounds(), worldBounds);
- style = this.features[id][1];
- this.drawGeometry(geometry, style, feature.id);
- if(style.label) {
- labelMap.push([feature, style]);
- }
- }
- var item;
- for (var i=0, len=labelMap.length; i<len; ++i) {
- item = labelMap[i];
- this.drawText(item[0].geometry.getCentroid(), item[1]);
- }
- }
- },
-
- CLASS_NAME: "OpenLayers.Renderer.Canvas"
-});
-
-/**
- * Constant: OpenLayers.Renderer.Canvas.LABEL_ALIGN
- * {Object}
- */
-OpenLayers.Renderer.Canvas.LABEL_ALIGN = {
- "l": "left",
- "r": "right",
- "t": "top",
- "b": "bottom"
-};
-
-/**
- * Constant: OpenLayers.Renderer.Canvas.LABEL_FACTOR
- * {Object}
- */
-OpenLayers.Renderer.Canvas.LABEL_FACTOR = {
- "l": 0,
- "r": -1,
- "t": 0,
- "b": -1
-};
-
-/**
- * Constant: OpenLayers.Renderer.Canvas.drawImageScaleFactor
- * {Number} Scale factor to apply to the canvas drawImage arguments. This
- * is always 1 except for Android 2.1 devices, to work around
- * http://code.google.com/p/android/issues/detail?id=5141.
- */
-OpenLayers.Renderer.Canvas.drawImageScaleFactor = null;