summaryrefslogtreecommitdiff
path: root/misc/openlayers/lib/OpenLayers/Renderer
diff options
context:
space:
mode:
authorChris Schlaeger <chris@linux.com>2015-10-17 21:36:38 +0200
committerChris Schlaeger <chris@linux.com>2015-10-17 21:36:38 +0200
commite30f267181d990947e67909de4809fa941698c85 (patch)
tree46e9f94c2b3699ed378963b420b8a8d361286ea1 /misc/openlayers/lib/OpenLayers/Renderer
parente763ceb183f389fcd314a4a6a712d87c9d4cdb32 (diff)
downloadpostrunner-e30f267181d990947e67909de4809fa941698c85.zip
Upgrading openlayers to 3.x
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Renderer')
-rw-r--r--misc/openlayers/lib/OpenLayers/Renderer/Canvas.js906
-rw-r--r--misc/openlayers/lib/OpenLayers/Renderer/Elements.js1053
-rw-r--r--misc/openlayers/lib/OpenLayers/Renderer/SVG.js1012
-rw-r--r--misc/openlayers/lib/OpenLayers/Renderer/VML.js985
4 files changed, 0 insertions, 3956 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;
diff --git a/misc/openlayers/lib/OpenLayers/Renderer/Elements.js b/misc/openlayers/lib/OpenLayers/Renderer/Elements.js
deleted file mode 100644
index 18a0d79..0000000
--- a/misc/openlayers/lib/OpenLayers/Renderer/Elements.js
+++ /dev/null
@@ -1,1053 +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.ElementsIndexer
- * This class takes care of figuring out which order elements should be
- * placed in the DOM based on given indexing methods.
- */
-OpenLayers.ElementsIndexer = OpenLayers.Class({
-
- /**
- * Property: maxZIndex
- * {Integer} This is the largest-most z-index value for a node
- * contained within the indexer.
- */
- maxZIndex: null,
-
- /**
- * Property: order
- * {Array<String>} This is an array of node id's stored in the
- * order that they should show up on screen. Id's higher up in the
- * array (higher array index) represent nodes with higher z-indeces.
- */
- order: null,
-
- /**
- * Property: indices
- * {Object} This is a hash that maps node ids to their z-index value
- * stored in the indexer. This is done to make finding a nodes z-index
- * value O(1).
- */
- indices: null,
-
- /**
- * Property: compare
- * {Function} This is the function used to determine placement of
- * of a new node within the indexer. If null, this defaults to to
- * the Z_ORDER_DRAWING_ORDER comparison method.
- */
- compare: null,
-
- /**
- * APIMethod: initialize
- * Create a new indexer with
- *
- * Parameters:
- * yOrdering - {Boolean} Whether to use y-ordering.
- */
- initialize: function(yOrdering) {
-
- this.compare = yOrdering ?
- OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER :
- OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER;
-
- this.clear();
- },
-
- /**
- * APIMethod: insert
- * Insert a new node into the indexer. In order to find the correct
- * positioning for the node to be inserted, this method uses a binary
- * search. This makes inserting O(log(n)).
- *
- * Parameters:
- * newNode - {DOMElement} The new node to be inserted.
- *
- * Returns
- * {DOMElement} the node before which we should insert our newNode, or
- * null if newNode can just be appended.
- */
- insert: function(newNode) {
- // If the node is known to the indexer, remove it so we can
- // recalculate where it should go.
- if (this.exists(newNode)) {
- this.remove(newNode);
- }
-
- var nodeId = newNode.id;
-
- this.determineZIndex(newNode);
-
- var leftIndex = -1;
- var rightIndex = this.order.length;
- var middle;
-
- while (rightIndex - leftIndex > 1) {
- middle = parseInt((leftIndex + rightIndex) / 2);
-
- var placement = this.compare(this, newNode,
- OpenLayers.Util.getElement(this.order[middle]));
-
- if (placement > 0) {
- leftIndex = middle;
- } else {
- rightIndex = middle;
- }
- }
-
- this.order.splice(rightIndex, 0, nodeId);
- this.indices[nodeId] = this.getZIndex(newNode);
-
- // If the new node should be before another in the index
- // order, return the node before which we have to insert the new one;
- // else, return null to indicate that the new node can be appended.
- return this.getNextElement(rightIndex);
- },
-
- /**
- * APIMethod: remove
- *
- * Parameters:
- * node - {DOMElement} The node to be removed.
- */
- remove: function(node) {
- var nodeId = node.id;
- var arrayIndex = OpenLayers.Util.indexOf(this.order, nodeId);
- if (arrayIndex >= 0) {
- // Remove it from the order array, as well as deleting the node
- // from the indeces hash.
- this.order.splice(arrayIndex, 1);
- delete this.indices[nodeId];
-
- // Reset the maxium z-index based on the last item in the
- // order array.
- if (this.order.length > 0) {
- var lastId = this.order[this.order.length - 1];
- this.maxZIndex = this.indices[lastId];
- } else {
- this.maxZIndex = 0;
- }
- }
- },
-
- /**
- * APIMethod: clear
- */
- clear: function() {
- this.order = [];
- this.indices = {};
- this.maxZIndex = 0;
- },
-
- /**
- * APIMethod: exists
- *
- * Parameters:
- * node - {DOMElement} The node to test for existence.
- *
- * Returns:
- * {Boolean} Whether or not the node exists in the indexer?
- */
- exists: function(node) {
- return (this.indices[node.id] != null);
- },
-
- /**
- * APIMethod: getZIndex
- * Get the z-index value for the current node from the node data itself.
- *
- * Parameters:
- * node - {DOMElement} The node whose z-index to get.
- *
- * Returns:
- * {Integer} The z-index value for the specified node (from the node
- * data itself).
- */
- getZIndex: function(node) {
- return node._style.graphicZIndex;
- },
-
- /**
- * Method: determineZIndex
- * Determine the z-index for the current node if there isn't one,
- * and set the maximum value if we've found a new maximum.
- *
- * Parameters:
- * node - {DOMElement}
- */
- determineZIndex: function(node) {
- var zIndex = node._style.graphicZIndex;
-
- // Everything must have a zIndex. If none is specified,
- // this means the user *must* (hint: assumption) want this
- // node to succomb to drawing order. To enforce drawing order
- // over all indexing methods, we'll create a new z-index that's
- // greater than any currently in the indexer.
- if (zIndex == null) {
- zIndex = this.maxZIndex;
- node._style.graphicZIndex = zIndex;
- } else if (zIndex > this.maxZIndex) {
- this.maxZIndex = zIndex;
- }
- },
-
- /**
- * APIMethod: getNextElement
- * Get the next element in the order stack.
- *
- * Parameters:
- * index - {Integer} The index of the current node in this.order.
- *
- * Returns:
- * {DOMElement} the node following the index passed in, or
- * null.
- */
- getNextElement: function(index) {
- var nextIndex = index + 1;
- if (nextIndex < this.order.length) {
- var nextElement = OpenLayers.Util.getElement(this.order[nextIndex]);
- if (nextElement == undefined) {
- nextElement = this.getNextElement(nextIndex);
- }
- return nextElement;
- } else {
- return null;
- }
- },
-
- CLASS_NAME: "OpenLayers.ElementsIndexer"
-});
-
-/**
- * Namespace: OpenLayers.ElementsIndexer.IndexingMethods
- * These are the compare methods for figuring out where a new node should be
- * placed within the indexer. These methods are very similar to general
- * sorting methods in that they return -1, 0, and 1 to specify the
- * direction in which new nodes fall in the ordering.
- */
-OpenLayers.ElementsIndexer.IndexingMethods = {
-
- /**
- * Method: Z_ORDER
- * This compare method is used by other comparison methods.
- * It can be used individually for ordering, but is not recommended,
- * because it doesn't subscribe to drawing order.
- *
- * Parameters:
- * indexer - {<OpenLayers.ElementsIndexer>}
- * newNode - {DOMElement}
- * nextNode - {DOMElement}
- *
- * Returns:
- * {Integer}
- */
- Z_ORDER: function(indexer, newNode, nextNode) {
- var newZIndex = indexer.getZIndex(newNode);
-
- var returnVal = 0;
- if (nextNode) {
- var nextZIndex = indexer.getZIndex(nextNode);
- returnVal = newZIndex - nextZIndex;
- }
-
- return returnVal;
- },
-
- /**
- * APIMethod: Z_ORDER_DRAWING_ORDER
- * This method orders nodes by their z-index, but does so in a way
- * that, if there are other nodes with the same z-index, the newest
- * drawn will be the front most within that z-index. This is the
- * default indexing method.
- *
- * Parameters:
- * indexer - {<OpenLayers.ElementsIndexer>}
- * newNode - {DOMElement}
- * nextNode - {DOMElement}
- *
- * Returns:
- * {Integer}
- */
- Z_ORDER_DRAWING_ORDER: function(indexer, newNode, nextNode) {
- var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(
- indexer,
- newNode,
- nextNode
- );
-
- // Make Z_ORDER subscribe to drawing order by pushing it above
- // all of the other nodes with the same z-index.
- if (nextNode && returnVal == 0) {
- returnVal = 1;
- }
-
- return returnVal;
- },
-
- /**
- * APIMethod: Z_ORDER_Y_ORDER
- * This one should really be called Z_ORDER_Y_ORDER_DRAWING_ORDER, as it
- * best describes which ordering methods have precedence (though, the
- * name would be too long). This method orders nodes by their z-index,
- * but does so in a way that, if there are other nodes with the same
- * z-index, the nodes with the lower y position will be "closer" than
- * those with a higher y position. If two nodes have the exact same y
- * position, however, then this method will revert to using drawing
- * order to decide placement.
- *
- * Parameters:
- * indexer - {<OpenLayers.ElementsIndexer>}
- * newNode - {DOMElement}
- * nextNode - {DOMElement}
- *
- * Returns:
- * {Integer}
- */
- Z_ORDER_Y_ORDER: function(indexer, newNode, nextNode) {
- var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(
- indexer,
- newNode,
- nextNode
- );
-
- if (nextNode && returnVal === 0) {
- var result = nextNode._boundsBottom - newNode._boundsBottom;
- returnVal = (result === 0) ? 1 : result;
- }
-
- return returnVal;
- }
-};
-
-/**
- * Class: OpenLayers.Renderer.Elements
- * This is another virtual class in that it should never be instantiated by
- * itself as a Renderer. It exists because there is *tons* of shared
- * functionality between different vector libraries which use nodes/elements
- * as a base for rendering vectors.
- *
- * The highlevel bits of code that are implemented here are the adding and
- * removing of geometries, which is essentially the same for any
- * element-based renderer. The details of creating each node and drawing the
- * paths are of course different, but the machinery is the same.
- *
- * Inherits:
- * - <OpenLayers.Renderer>
- */
-OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
-
- /**
- * Property: rendererRoot
- * {DOMElement}
- */
- rendererRoot: null,
-
- /**
- * Property: root
- * {DOMElement}
- */
- root: null,
-
- /**
- * Property: vectorRoot
- * {DOMElement}
- */
- vectorRoot: null,
-
- /**
- * Property: textRoot
- * {DOMElement}
- */
- textRoot: null,
-
- /**
- * Property: xmlns
- * {String}
- */
- xmlns: null,
-
- /**
- * Property: xOffset
- * {Number} Offset to apply to the renderer viewport translation in x
- * direction. If the renderer extent's center is on the right of the
- * dateline (i.e. exceeds the world bounds), we shift the viewport to the
- * left by one world width. This avoids that features disappear from the
- * map viewport. Because our dateline handling logic in other places
- * ensures that extents crossing the dateline always have a center
- * exceeding the world bounds on the left, we need this offset to make sure
- * that the same is true for the renderer extent in pixel space as well.
- */
- xOffset: 0,
-
- /**
- * Property: rightOfDateLine
- * {Boolean} Keeps track of the location of the map extent relative to the
- * date line. The <setExtent> method compares this value (which is the one
- * from the previous <setExtent> call) with the current position of the map
- * extent relative to the date line and updates the xOffset when the extent
- * has moved from one side of the date line to the other.
- */
-
- /**
- * Property: Indexer
- * {<OpenLayers.ElementIndexer>} An instance of OpenLayers.ElementsIndexer
- * created upon initialization if the zIndexing or yOrdering options
- * passed to this renderer's constructor are set to true.
- */
- indexer: null,
-
- /**
- * Constant: BACKGROUND_ID_SUFFIX
- * {String}
- */
- BACKGROUND_ID_SUFFIX: "_background",
-
- /**
- * Constant: LABEL_ID_SUFFIX
- * {String}
- */
- LABEL_ID_SUFFIX: "_label",
-
- /**
- * Constant: LABEL_OUTLINE_SUFFIX
- * {String}
- */
- LABEL_OUTLINE_SUFFIX: "_outline",
-
- /**
- * Constructor: OpenLayers.Renderer.Elements
- *
- * Parameters:
- * containerID - {String}
- * options - {Object} options for this renderer.
- *
- * Supported options are:
- * yOrdering - {Boolean} Whether to use y-ordering
- * zIndexing - {Boolean} Whether to use z-indexing. Will be ignored
- * if yOrdering is set to true.
- */
- initialize: function(containerID, options) {
- OpenLayers.Renderer.prototype.initialize.apply(this, arguments);
-
- this.rendererRoot = this.createRenderRoot();
- this.root = this.createRoot("_root");
- this.vectorRoot = this.createRoot("_vroot");
- this.textRoot = this.createRoot("_troot");
-
- this.root.appendChild(this.vectorRoot);
- this.root.appendChild(this.textRoot);
-
- this.rendererRoot.appendChild(this.root);
- this.container.appendChild(this.rendererRoot);
-
- if(options && (options.zIndexing || options.yOrdering)) {
- this.indexer = new OpenLayers.ElementsIndexer(options.yOrdering);
- }
- },
-
- /**
- * Method: destroy
- */
- destroy: function() {
-
- this.clear();
-
- this.rendererRoot = null;
- this.root = null;
- this.xmlns = null;
-
- OpenLayers.Renderer.prototype.destroy.apply(this, arguments);
- },
-
- /**
- * Method: clear
- * Remove all the elements from the root
- */
- clear: function() {
- var child;
- var root = this.vectorRoot;
- if (root) {
- while (child = root.firstChild) {
- root.removeChild(child);
- }
- }
- root = this.textRoot;
- if (root) {
- while (child = root.firstChild) {
- root.removeChild(child);
- }
- }
- if (this.indexer) {
- this.indexer.clear();
- }
- },
-
- /**
- * 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(extent, resolutionChanged) {
- var coordSysUnchanged = OpenLayers.Renderer.prototype.setExtent.apply(this, arguments);
- var resolution = this.getResolution();
- if (this.map.baseLayer && this.map.baseLayer.wrapDateLine) {
- var rightOfDateLine,
- ratio = extent.getWidth() / this.map.getExtent().getWidth(),
- extent = extent.scale(1 / ratio),
- world = this.map.getMaxExtent();
- if (world.right > extent.left && world.right < extent.right) {
- rightOfDateLine = true;
- } else if (world.left > extent.left && world.left < extent.right) {
- rightOfDateLine = false;
- }
- if (rightOfDateLine !== this.rightOfDateLine || resolutionChanged) {
- coordSysUnchanged = false;
- this.xOffset = rightOfDateLine === true ?
- world.getWidth() / resolution : 0;
- }
- this.rightOfDateLine = rightOfDateLine;
- }
- return coordSysUnchanged;
- },
-
- /**
- * Method: getNodeType
- * This function is in charge of asking the specific renderer which type
- * of node to create for the given geometry and style. All geometries
- * in an Elements-based renderer consist of one node and some
- * attributes. We have the nodeFactory() function which creates a node
- * for us, but it takes a 'type' as input, and that is precisely what
- * this function tells us.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- *
- * Returns:
- * {String} The corresponding node type for the specified geometry
- */
- getNodeType: function(geometry, style) { },
-
- /**
- * Method: drawGeometry
- * Draw the geometry, creating new nodes, setting paths, setting style,
- * setting featureId on the node. This method should only be called
- * by the renderer itself.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- *
- * Returns:
- * {Boolean} true if the geometry has been drawn completely; null if
- * incomplete; false otherwise
- */
- drawGeometry: function(geometry, style, featureId) {
- var className = geometry.CLASS_NAME;
- var rendered = true;
- if ((className == "OpenLayers.Geometry.Collection") ||
- (className == "OpenLayers.Geometry.MultiPoint") ||
- (className == "OpenLayers.Geometry.MultiLineString") ||
- (className == "OpenLayers.Geometry.MultiPolygon")) {
- for (var i = 0, len=geometry.components.length; i<len; i++) {
- rendered = this.drawGeometry(
- geometry.components[i], style, featureId) && rendered;
- }
- return rendered;
- }
-
- rendered = false;
- var removeBackground = false;
- if (style.display != "none") {
- if (style.backgroundGraphic) {
- this.redrawBackgroundNode(geometry.id, geometry, style,
- featureId);
- } else {
- removeBackground = true;
- }
- rendered = this.redrawNode(geometry.id, geometry, style,
- featureId);
- }
- if (rendered == false) {
- var node = document.getElementById(geometry.id);
- if (node) {
- if (node._style.backgroundGraphic) {
- removeBackground = true;
- }
- node.parentNode.removeChild(node);
- }
- }
- if (removeBackground) {
- var node = document.getElementById(
- geometry.id + this.BACKGROUND_ID_SUFFIX);
- if (node) {
- node.parentNode.removeChild(node);
- }
- }
- return rendered;
- },
-
- /**
- * Method: redrawNode
- *
- * Parameters:
- * id - {String}
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- *
- * Returns:
- * {Boolean} true if the complete geometry could be drawn, null if parts of
- * the geometry could not be drawn, false otherwise
- */
- redrawNode: function(id, geometry, style, featureId) {
- style = this.applyDefaultSymbolizer(style);
- // Get the node if it's already on the map.
- var node = this.nodeFactory(id, this.getNodeType(geometry, style));
-
- // Set the data for the node, then draw it.
- node._featureId = featureId;
- node._boundsBottom = geometry.getBounds().bottom;
- node._geometryClass = geometry.CLASS_NAME;
- node._style = style;
-
- var drawResult = this.drawGeometryNode(node, geometry, style);
- if(drawResult === false) {
- return false;
- }
-
- node = drawResult.node;
-
- // Insert the node into the indexer so it can show us where to
- // place it. Note that this operation is O(log(n)). If there's a
- // performance problem (when dragging, for instance) this is
- // likely where it would be.
- if (this.indexer) {
- var insert = this.indexer.insert(node);
- if (insert) {
- this.vectorRoot.insertBefore(node, insert);
- } else {
- this.vectorRoot.appendChild(node);
- }
- } else {
- // if there's no indexer, simply append the node to root,
- // but only if the node is a new one
- if (node.parentNode !== this.vectorRoot){
- this.vectorRoot.appendChild(node);
- }
- }
-
- this.postDraw(node);
-
- return drawResult.complete;
- },
-
- /**
- * Method: redrawBackgroundNode
- * Redraws the node using special 'background' style properties. Basically
- * just calls redrawNode(), but instead of directly using the
- * 'externalGraphic', 'graphicXOffset', 'graphicYOffset', and
- * 'graphicZIndex' properties directly from the specified 'style'
- * parameter, we create a new style object and set those properties
- * from the corresponding 'background'-prefixed properties from
- * specified 'style' parameter.
- *
- * Parameters:
- * id - {String}
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- *
- * Returns:
- * {Boolean} true if the complete geometry could be drawn, null if parts of
- * the geometry could not be drawn, false otherwise
- */
- redrawBackgroundNode: function(id, geometry, style, featureId) {
- var backgroundStyle = OpenLayers.Util.extend({}, style);
-
- // Set regular style attributes to apply to the background styles.
- backgroundStyle.externalGraphic = backgroundStyle.backgroundGraphic;
- backgroundStyle.graphicXOffset = backgroundStyle.backgroundXOffset;
- backgroundStyle.graphicYOffset = backgroundStyle.backgroundYOffset;
- backgroundStyle.graphicZIndex = backgroundStyle.backgroundGraphicZIndex;
- backgroundStyle.graphicWidth = backgroundStyle.backgroundWidth || backgroundStyle.graphicWidth;
- backgroundStyle.graphicHeight = backgroundStyle.backgroundHeight || backgroundStyle.graphicHeight;
-
- // Erase background styles.
- backgroundStyle.backgroundGraphic = null;
- backgroundStyle.backgroundXOffset = null;
- backgroundStyle.backgroundYOffset = null;
- backgroundStyle.backgroundGraphicZIndex = null;
-
- return this.redrawNode(
- id + this.BACKGROUND_ID_SUFFIX,
- geometry,
- backgroundStyle,
- null
- );
- },
-
- /**
- * Method: drawGeometryNode
- * Given a node, draw a geometry on the specified layer.
- * node and geometry are required arguments, style is optional.
- * This method is only called by the render itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- *
- * Returns:
- * {Object} a hash with properties "node" (the drawn node) and "complete"
- * (null if parts of the geometry could not be drawn, false if nothing
- * could be drawn)
- */
- drawGeometryNode: function(node, geometry, style) {
- style = style || node._style;
-
- var options = {
- 'isFilled': style.fill === undefined ?
- true :
- style.fill,
- 'isStroked': style.stroke === undefined ?
- !!style.strokeWidth :
- style.stroke
- };
- var drawn;
- switch (geometry.CLASS_NAME) {
- case "OpenLayers.Geometry.Point":
- if(style.graphic === false) {
- options.isFilled = false;
- options.isStroked = false;
- }
- drawn = this.drawPoint(node, geometry);
- break;
- case "OpenLayers.Geometry.LineString":
- options.isFilled = false;
- drawn = this.drawLineString(node, geometry);
- break;
- case "OpenLayers.Geometry.LinearRing":
- drawn = this.drawLinearRing(node, geometry);
- break;
- case "OpenLayers.Geometry.Polygon":
- drawn = this.drawPolygon(node, geometry);
- break;
- case "OpenLayers.Geometry.Rectangle":
- drawn = this.drawRectangle(node, geometry);
- break;
- default:
- break;
- }
-
- node._options = options;
-
- //set style
- //TBD simplify this
- if (drawn != false) {
- return {
- node: this.setStyle(node, style, options, geometry),
- complete: drawn
- };
- } else {
- return false;
- }
- },
-
- /**
- * Method: postDraw
- * Things that have do be done after the geometry node is appended
- * to its parent node. To be overridden by subclasses.
- *
- * Parameters:
- * node - {DOMElement}
- */
- postDraw: function(node) {},
-
- /**
- * Method: drawPoint
- * Virtual function for drawing Point Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the point
- */
- drawPoint: function(node, geometry) {},
-
- /**
- * Method: drawLineString
- * Virtual function for drawing LineString Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or null if the renderer could not draw all components of
- * the linestring, or false if nothing could be drawn
- */
- drawLineString: function(node, geometry) {},
-
- /**
- * Method: drawLinearRing
- * Virtual function for drawing LinearRing Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or null if the renderer could not draw all components
- * of the linear ring, or false if nothing could be drawn
- */
- drawLinearRing: function(node, geometry) {},
-
- /**
- * Method: drawPolygon
- * Virtual function for drawing Polygon Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or null if the renderer could not draw all components
- * of the polygon, or false if nothing could be drawn
- */
- drawPolygon: function(node, geometry) {},
-
- /**
- * Method: drawRectangle
- * Virtual function for drawing Rectangle Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the rectangle
- */
- drawRectangle: function(node, geometry) {},
-
- /**
- * Method: drawCircle
- * Virtual function for drawing Circle Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the circle
- */
- drawCircle: function(node, geometry) {},
-
- /**
- * Method: removeText
- * Removes a label
- *
- * Parameters:
- * featureId - {String}
- */
- removeText: function(featureId) {
- var label = document.getElementById(featureId + this.LABEL_ID_SUFFIX);
- if (label) {
- this.textRoot.removeChild(label);
- }
- var outline = document.getElementById(featureId + this.LABEL_OUTLINE_SUFFIX);
- if (outline) {
- this.textRoot.removeChild(outline);
- }
- },
-
- /**
- * Method: getFeatureIdFromEvent
- *
- * Parameters:
- * evt - {Object} An <OpenLayers.Event> object
- *
- * Returns:
- * {String} A feature id or undefined.
- */
- getFeatureIdFromEvent: function(evt) {
- var target = evt.target;
- var useElement = target && target.correspondingUseElement;
- var node = useElement ? useElement : (target || evt.srcElement);
- return node._featureId;
- },
-
- /**
- * Method: eraseGeometry
- * Erase a geometry from the renderer. In the case of a multi-geometry,
- * we cycle through and recurse on ourselves. Otherwise, we look for a
- * node with the geometry.id, destroy its geometry, and remove it from
- * the DOM.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * featureId - {String}
- */
- eraseGeometry: function(geometry, featureId) {
- if ((geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") ||
- (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiLineString") ||
- (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon") ||
- (geometry.CLASS_NAME == "OpenLayers.Geometry.Collection")) {
- for (var i=0, len=geometry.components.length; i<len; i++) {
- this.eraseGeometry(geometry.components[i], featureId);
- }
- } else {
- var element = OpenLayers.Util.getElement(geometry.id);
- if (element && element.parentNode) {
- if (element.geometry) {
- element.geometry.destroy();
- element.geometry = null;
- }
- element.parentNode.removeChild(element);
-
- if (this.indexer) {
- this.indexer.remove(element);
- }
-
- if (element._style.backgroundGraphic) {
- var backgroundId = geometry.id + this.BACKGROUND_ID_SUFFIX;
- var bElem = OpenLayers.Util.getElement(backgroundId);
- if (bElem && bElem.parentNode) {
- // No need to destroy the geometry since the element and the background
- // node share the same geometry.
- bElem.parentNode.removeChild(bElem);
- }
- }
- }
- }
- },
-
- /**
- * Method: nodeFactory
- * Create new node of the specified type, with the (optional) specified id.
- *
- * If node already exists with same ID and a different type, we remove it
- * and then call ourselves again to recreate it.
- *
- * Parameters:
- * id - {String}
- * type - {String} type Kind of node to draw.
- *
- * Returns:
- * {DOMElement} A new node of the given type and id.
- */
- nodeFactory: function(id, type) {
- var node = OpenLayers.Util.getElement(id);
- if (node) {
- if (!this.nodeTypeCompare(node, type)) {
- node.parentNode.removeChild(node);
- node = this.nodeFactory(id, type);
- }
- } else {
- node = this.createNode(type, id);
- }
- return node;
- },
-
- /**
- * Method: nodeTypeCompare
- *
- * Parameters:
- * node - {DOMElement}
- * type - {String} Kind of node
- *
- * Returns:
- * {Boolean} Whether or not the specified node is of the specified type
- * This function must be overridden by subclasses.
- */
- nodeTypeCompare: function(node, type) {},
-
- /**
- * Method: createNode
- *
- * Parameters:
- * type - {String} Kind of node to draw.
- * id - {String} Id for node.
- *
- * Returns:
- * {DOMElement} A new node of the given type and id.
- * This function must be overridden by subclasses.
- */
- createNode: function(type, id) {},
-
- /**
- * Method: moveRoot
- * moves this renderer's root to a different renderer.
- *
- * Parameters:
- * renderer - {<OpenLayers.Renderer>} target renderer for the moved root
- */
- moveRoot: function(renderer) {
- var root = this.root;
- if(renderer.root.parentNode == this.rendererRoot) {
- root = renderer.root;
- }
- root.parentNode.removeChild(root);
- renderer.rendererRoot.appendChild(root);
- },
-
- /**
- * Method: getRenderLayerId
- * Gets the layer that this renderer's output appears on. If moveRoot was
- * used, this will be different from the id of the layer containing the
- * features rendered by this renderer.
- *
- * Returns:
- * {String} the id of the output layer.
- */
- getRenderLayerId: function() {
- return this.root.parentNode.parentNode.id;
- },
-
- /**
- * Method: isComplexSymbol
- * Determines if a symbol cannot be rendered using drawCircle
- *
- * Parameters:
- * graphicName - {String}
- *
- * Returns
- * {Boolean} true if the symbol is complex, false if not
- */
- isComplexSymbol: function(graphicName) {
- return (graphicName != "circle") && !!graphicName;
- },
-
- CLASS_NAME: "OpenLayers.Renderer.Elements"
-});
-
diff --git a/misc/openlayers/lib/OpenLayers/Renderer/SVG.js b/misc/openlayers/lib/OpenLayers/Renderer/SVG.js
deleted file mode 100644
index 263aac0..0000000
--- a/misc/openlayers/lib/OpenLayers/Renderer/SVG.js
+++ /dev/null
@@ -1,1012 +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/Elements.js
- */
-
-/**
- * Class: OpenLayers.Renderer.SVG
- *
- * Inherits:
- * - <OpenLayers.Renderer.Elements>
- */
-OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
-
- /**
- * Property: xmlns
- * {String}
- */
- xmlns: "http://www.w3.org/2000/svg",
-
- /**
- * Property: xlinkns
- * {String}
- */
- xlinkns: "http://www.w3.org/1999/xlink",
-
- /**
- * Constant: MAX_PIXEL
- * {Integer} Firefox has a limitation where values larger or smaller than
- * about 15000 in an SVG document lock the browser up. This
- * works around it.
- */
- MAX_PIXEL: 15000,
-
- /**
- * Property: translationParameters
- * {Object} Hash with "x" and "y" properties
- */
- translationParameters: null,
-
- /**
- * Property: symbolMetrics
- * {Object} Cache for symbol metrics according to their svg coordinate
- * space. This is an object keyed by the symbol's id, and values are
- * an array of [width, centerX, centerY].
- */
- symbolMetrics: null,
-
- /**
- * Constructor: OpenLayers.Renderer.SVG
- *
- * Parameters:
- * containerID - {String}
- */
- initialize: function(containerID) {
- if (!this.supported()) {
- return;
- }
- OpenLayers.Renderer.Elements.prototype.initialize.apply(this,
- arguments);
- this.translationParameters = {x: 0, y: 0};
-
- this.symbolMetrics = {};
- },
-
- /**
- * APIMethod: supported
- *
- * Returns:
- * {Boolean} Whether or not the browser supports the SVG renderer
- */
- supported: function() {
- var svgFeature = "http://www.w3.org/TR/SVG11/feature#";
- return (document.implementation &&
- (document.implementation.hasFeature("org.w3c.svg", "1.0") ||
- document.implementation.hasFeature(svgFeature + "SVG", "1.1") ||
- document.implementation.hasFeature(svgFeature + "BasicStructure", "1.1") ));
- },
-
- /**
- * Method: inValidRange
- * See #669 for more information
- *
- * Parameters:
- * x - {Integer}
- * y - {Integer}
- * xyOnly - {Boolean} whether or not to just check for x and y, which means
- * to not take the current translation parameters into account if true.
- *
- * Returns:
- * {Boolean} Whether or not the 'x' and 'y' coordinates are in the
- * valid range.
- */
- inValidRange: function(x, y, xyOnly) {
- var left = x + (xyOnly ? 0 : this.translationParameters.x);
- var top = y + (xyOnly ? 0 : this.translationParameters.y);
- return (left >= -this.MAX_PIXEL && left <= this.MAX_PIXEL &&
- top >= -this.MAX_PIXEL && top <= this.MAX_PIXEL);
- },
-
- /**
- * Method: setExtent
- *
- * 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(extent, resolutionChanged) {
- var coordSysUnchanged = OpenLayers.Renderer.Elements.prototype.setExtent.apply(this, arguments);
-
- var resolution = this.getResolution(),
- left = -extent.left / resolution,
- top = extent.top / resolution;
-
- // If the resolution has changed, start over changing the corner, because
- // the features will redraw.
- if (resolutionChanged) {
- this.left = left;
- this.top = top;
- // Set the viewbox
- var extentString = "0 0 " + this.size.w + " " + this.size.h;
-
- this.rendererRoot.setAttributeNS(null, "viewBox", extentString);
- this.translate(this.xOffset, 0);
- return true;
- } else {
- var inRange = this.translate(left - this.left + this.xOffset, top - this.top);
- if (!inRange) {
- // recenter the coordinate system
- this.setExtent(extent, true);
- }
- return coordSysUnchanged && inRange;
- }
- },
-
- /**
- * Method: translate
- * Transforms the SVG coordinate system
- *
- * Parameters:
- * x - {Float}
- * y - {Float}
- *
- * Returns:
- * {Boolean} true if the translation parameters are in the valid coordinates
- * range, false otherwise.
- */
- translate: function(x, y) {
- if (!this.inValidRange(x, y, true)) {
- return false;
- } else {
- var transformString = "";
- if (x || y) {
- transformString = "translate(" + x + "," + y + ")";
- }
- this.root.setAttributeNS(null, "transform", transformString);
- this.translationParameters = {x: x, y: y};
- return true;
- }
- },
-
- /**
- * Method: setSize
- * Sets the size of the drawing surface.
- *
- * Parameters:
- * size - {<OpenLayers.Size>} The size of the drawing surface
- */
- setSize: function(size) {
- OpenLayers.Renderer.prototype.setSize.apply(this, arguments);
-
- this.rendererRoot.setAttributeNS(null, "width", this.size.w);
- this.rendererRoot.setAttributeNS(null, "height", this.size.h);
- },
-
- /**
- * Method: getNodeType
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- *
- * Returns:
- * {String} The corresponding node type for the specified geometry
- */
- getNodeType: function(geometry, style) {
- var nodeType = null;
- switch (geometry.CLASS_NAME) {
- case "OpenLayers.Geometry.Point":
- if (style.externalGraphic) {
- nodeType = "image";
- } else if (this.isComplexSymbol(style.graphicName)) {
- nodeType = "svg";
- } else {
- nodeType = "circle";
- }
- break;
- case "OpenLayers.Geometry.Rectangle":
- nodeType = "rect";
- break;
- case "OpenLayers.Geometry.LineString":
- nodeType = "polyline";
- break;
- case "OpenLayers.Geometry.LinearRing":
- nodeType = "polygon";
- break;
- case "OpenLayers.Geometry.Polygon":
- case "OpenLayers.Geometry.Curve":
- nodeType = "path";
- break;
- default:
- break;
- }
- return nodeType;
- },
-
- /**
- * Method: setStyle
- * Use to set all the style attributes to a SVG node.
- *
- * Takes care to adjust stroke width and point radius to be
- * resolution-relative
- *
- * Parameters:
- * node - {SVGDomElement} An SVG element to decorate
- * style - {Object}
- * options - {Object} Currently supported options include
- * 'isFilled' {Boolean} and
- * 'isStroked' {Boolean}
- */
- setStyle: function(node, style, options) {
- style = style || node._style;
- options = options || node._options;
-
- var title = style.title || style.graphicTitle;
- if (title) {
- node.setAttributeNS(null, "title", title);
- //Standards-conformant SVG
- // Prevent duplicate nodes. See issue https://github.com/openlayers/openlayers/issues/92
- var titleNode = node.getElementsByTagName("title");
- if (titleNode.length > 0) {
- titleNode[0].firstChild.textContent = title;
- } else {
- var label = this.nodeFactory(null, "title");
- label.textContent = title;
- node.appendChild(label);
- }
- }
-
- var r = parseFloat(node.getAttributeNS(null, "r"));
- var widthFactor = 1;
- var pos;
- if (node._geometryClass == "OpenLayers.Geometry.Point" && r) {
- node.style.visibility = "";
- if (style.graphic === false) {
- node.style.visibility = "hidden";
- } else if (style.externalGraphic) {
- pos = this.getPosition(node);
- if (style.graphicWidth && style.graphicHeight) {
- node.setAttributeNS(null, "preserveAspectRatio", "none");
- }
- 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;
-
- node.setAttributeNS(null, "x", (pos.x + xOffset).toFixed());
- node.setAttributeNS(null, "y", (pos.y + yOffset).toFixed());
- node.setAttributeNS(null, "width", width);
- node.setAttributeNS(null, "height", height);
- node.setAttributeNS(this.xlinkns, "xlink:href", style.externalGraphic);
- node.setAttributeNS(null, "style", "opacity: "+opacity);
- node.onclick = OpenLayers.Event.preventDefault;
- } else if (this.isComplexSymbol(style.graphicName)) {
- // the symbol viewBox is three times as large as the symbol
- var offset = style.pointRadius * 3;
- var size = offset * 2;
- var src = this.importSymbol(style.graphicName);
- pos = this.getPosition(node);
- widthFactor = this.symbolMetrics[src.id][0] * 3 / size;
-
- // remove the node from the dom before we modify it. This
- // prevents various rendering issues in Safari and FF
- var parent = node.parentNode;
- var nextSibling = node.nextSibling;
- if(parent) {
- parent.removeChild(node);
- }
-
- // The more appropriate way to implement this would be use/defs,
- // but due to various issues in several browsers, it is safer to
- // copy the symbols instead of referencing them.
- // See e.g. ticket http://trac.osgeo.org/openlayers/ticket/2985
- // and this email thread
- // http://osgeo-org.1803224.n2.nabble.com/Select-Control-Ctrl-click-on-Feature-with-a-graphicName-opens-new-browser-window-tc5846039.html
- node.firstChild && node.removeChild(node.firstChild);
- node.appendChild(src.firstChild.cloneNode(true));
- node.setAttributeNS(null, "viewBox", src.getAttributeNS(null, "viewBox"));
-
- node.setAttributeNS(null, "width", size);
- node.setAttributeNS(null, "height", size);
- node.setAttributeNS(null, "x", pos.x - offset);
- node.setAttributeNS(null, "y", pos.y - offset);
-
- // now that the node has all its new properties, insert it
- // back into the dom where it was
- if(nextSibling) {
- parent.insertBefore(node, nextSibling);
- } else if(parent) {
- parent.appendChild(node);
- }
- } else {
- node.setAttributeNS(null, "r", style.pointRadius);
- }
-
- var rotation = style.rotation;
-
- if ((rotation !== undefined || node._rotation !== undefined) && pos) {
- node._rotation = rotation;
- rotation |= 0;
- if (node.nodeName !== "svg") {
- node.setAttributeNS(null, "transform",
- "rotate(" + rotation + " " + pos.x + " " +
- pos.y + ")");
- } else {
- var metrics = this.symbolMetrics[src.id];
- node.firstChild.setAttributeNS(null, "transform", "rotate("
- + rotation + " "
- + metrics[1] + " "
- + metrics[2] + ")");
- }
- }
- }
-
- if (options.isFilled) {
- node.setAttributeNS(null, "fill", style.fillColor);
- node.setAttributeNS(null, "fill-opacity", style.fillOpacity);
- } else {
- node.setAttributeNS(null, "fill", "none");
- }
-
- if (options.isStroked) {
- node.setAttributeNS(null, "stroke", style.strokeColor);
- node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity);
- node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor);
- node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap || "round");
- // Hard-coded linejoin for now, to make it look the same as in VML.
- // There is no strokeLinejoin property yet for symbolizers.
- node.setAttributeNS(null, "stroke-linejoin", "round");
- style.strokeDashstyle && node.setAttributeNS(null,
- "stroke-dasharray", this.dashStyle(style, widthFactor));
- } else {
- node.setAttributeNS(null, "stroke", "none");
- }
-
- if (style.pointerEvents) {
- node.setAttributeNS(null, "pointer-events", style.pointerEvents);
- }
-
- if (style.cursor != null) {
- node.setAttributeNS(null, "cursor", style.cursor);
- }
-
- return node;
- },
-
- /**
- * Method: dashStyle
- *
- * Parameters:
- * style - {Object}
- * widthFactor - {Number}
- *
- * Returns:
- * {String} A SVG compliant 'stroke-dasharray' value
- */
- dashStyle: function(style, widthFactor) {
- var w = style.strokeWidth * widthFactor;
- var str = style.strokeDashstyle;
- switch (str) {
- case 'solid':
- return 'none';
- case 'dot':
- return [1, 4 * w].join();
- case 'dash':
- return [4 * w, 4 * w].join();
- case 'dashdot':
- return [4 * w, 4 * w, 1, 4 * w].join();
- case 'longdash':
- return [8 * w, 4 * w].join();
- case 'longdashdot':
- return [8 * w, 4 * w, 1, 4 * w].join();
- default:
- return OpenLayers.String.trim(str).replace(/\s+/g, ",");
- }
- },
-
- /**
- * Method: createNode
- *
- * Parameters:
- * type - {String} Kind of node to draw
- * id - {String} Id for node
- *
- * Returns:
- * {DOMElement} A new node of the given type and id
- */
- createNode: function(type, id) {
- var node = document.createElementNS(this.xmlns, type);
- if (id) {
- node.setAttributeNS(null, "id", id);
- }
- return node;
- },
-
- /**
- * Method: nodeTypeCompare
- *
- * Parameters:
- * node - {SVGDomElement} An SVG element
- * type - {String} Kind of node
- *
- * Returns:
- * {Boolean} Whether or not the specified node is of the specified type
- */
- nodeTypeCompare: function(node, type) {
- return (type == node.nodeName);
- },
-
- /**
- * Method: createRenderRoot
- *
- * Returns:
- * {DOMElement} The specific render engine's root element
- */
- createRenderRoot: function() {
- var svg = this.nodeFactory(this.container.id + "_svgRoot", "svg");
- svg.style.display = "block";
- return svg;
- },
-
- /**
- * Method: createRoot
- *
- * Parameters:
- * suffix - {String} suffix to append to the id
- *
- * Returns:
- * {DOMElement}
- */
- createRoot: function(suffix) {
- return this.nodeFactory(this.container.id + suffix, "g");
- },
-
- /**
- * Method: createDefs
- *
- * Returns:
- * {DOMElement} The element to which we'll add the symbol definitions
- */
- createDefs: function() {
- var defs = this.nodeFactory(this.container.id + "_defs", "defs");
- this.rendererRoot.appendChild(defs);
- return defs;
- },
-
- /**************************************
- * *
- * GEOMETRY DRAWING FUNCTIONS *
- * *
- **************************************/
-
- /**
- * Method: drawPoint
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the point
- */
- drawPoint: function(node, geometry) {
- return this.drawCircle(node, geometry, 1);
- },
-
- /**
- * Method: drawCircle
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- * radius - {Float}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the circle
- */
- drawCircle: function(node, geometry, radius) {
- var resolution = this.getResolution();
- var x = ((geometry.x - this.featureDx) / resolution + this.left);
- var y = (this.top - geometry.y / resolution);
-
- if (this.inValidRange(x, y)) {
- node.setAttributeNS(null, "cx", x);
- node.setAttributeNS(null, "cy", y);
- node.setAttributeNS(null, "r", radius);
- return node;
- } else {
- return false;
- }
-
- },
-
- /**
- * Method: drawLineString
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or null if the renderer could not draw all components of
- * the linestring, or false if nothing could be drawn
- */
- drawLineString: function(node, geometry) {
- var componentsResult = this.getComponentsString(geometry.components);
- if (componentsResult.path) {
- node.setAttributeNS(null, "points", componentsResult.path);
- return (componentsResult.complete ? node : null);
- } else {
- return false;
- }
- },
-
- /**
- * Method: drawLinearRing
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or null if the renderer could not draw all components
- * of the linear ring, or false if nothing could be drawn
- */
- drawLinearRing: function(node, geometry) {
- var componentsResult = this.getComponentsString(geometry.components);
- if (componentsResult.path) {
- node.setAttributeNS(null, "points", componentsResult.path);
- return (componentsResult.complete ? node : null);
- } else {
- return false;
- }
- },
-
- /**
- * Method: drawPolygon
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or null if the renderer could not draw all components
- * of the polygon, or false if nothing could be drawn
- */
- drawPolygon: function(node, geometry) {
- var d = "";
- var draw = true;
- var complete = true;
- var linearRingResult, path;
- for (var j=0, len=geometry.components.length; j<len; j++) {
- d += " M";
- linearRingResult = this.getComponentsString(
- geometry.components[j].components, " ");
- path = linearRingResult.path;
- if (path) {
- d += " " + path;
- complete = linearRingResult.complete && complete;
- } else {
- draw = false;
- }
- }
- d += " z";
- if (draw) {
- node.setAttributeNS(null, "d", d);
- node.setAttributeNS(null, "fill-rule", "evenodd");
- return complete ? node : null;
- } else {
- return false;
- }
- },
-
- /**
- * Method: drawRectangle
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the rectangle
- */
- drawRectangle: function(node, geometry) {
- var resolution = this.getResolution();
- var x = ((geometry.x - this.featureDx) / resolution + this.left);
- var y = (this.top - geometry.y / resolution);
-
- if (this.inValidRange(x, y)) {
- node.setAttributeNS(null, "x", x);
- node.setAttributeNS(null, "y", y);
- node.setAttributeNS(null, "width", geometry.width / resolution);
- node.setAttributeNS(null, "height", geometry.height / resolution);
- return node;
- } else {
- return false;
- }
- },
-
- /**
- * Method: drawText
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * featureId - {String}
- * style -
- * location - {<OpenLayers.Geometry.Point>}
- */
- drawText: function(featureId, style, location) {
- var drawOutline = (!!style.labelOutlineWidth);
- // First draw text in halo color and size and overlay the
- // normal text afterwards
- if (drawOutline) {
- var outlineStyle = OpenLayers.Util.extend({}, style);
- outlineStyle.fontColor = outlineStyle.labelOutlineColor;
- outlineStyle.fontStrokeColor = outlineStyle.labelOutlineColor;
- outlineStyle.fontStrokeWidth = style.labelOutlineWidth;
- if (style.labelOutlineOpacity) {
- outlineStyle.fontOpacity = style.labelOutlineOpacity;
- }
- delete outlineStyle.labelOutlineWidth;
- this.drawText(featureId, outlineStyle, location);
- }
-
- var resolution = this.getResolution();
-
- var x = ((location.x - this.featureDx) / resolution + this.left);
- var y = (location.y / resolution - this.top);
-
- var suffix = (drawOutline)?this.LABEL_OUTLINE_SUFFIX:this.LABEL_ID_SUFFIX;
- var label = this.nodeFactory(featureId + suffix, "text");
-
- label.setAttributeNS(null, "x", x);
- label.setAttributeNS(null, "y", -y);
-
- if (style.fontColor) {
- label.setAttributeNS(null, "fill", style.fontColor);
- }
- if (style.fontStrokeColor) {
- label.setAttributeNS(null, "stroke", style.fontStrokeColor);
- }
- if (style.fontStrokeWidth) {
- label.setAttributeNS(null, "stroke-width", style.fontStrokeWidth);
- }
- if (style.fontOpacity) {
- label.setAttributeNS(null, "opacity", style.fontOpacity);
- }
- if (style.fontFamily) {
- label.setAttributeNS(null, "font-family", style.fontFamily);
- }
- if (style.fontSize) {
- label.setAttributeNS(null, "font-size", style.fontSize);
- }
- if (style.fontWeight) {
- label.setAttributeNS(null, "font-weight", style.fontWeight);
- }
- if (style.fontStyle) {
- label.setAttributeNS(null, "font-style", style.fontStyle);
- }
- if (style.labelSelect === true) {
- label.setAttributeNS(null, "pointer-events", "visible");
- label._featureId = featureId;
- } else {
- label.setAttributeNS(null, "pointer-events", "none");
- }
- var align = style.labelAlign || OpenLayers.Renderer.defaultSymbolizer.labelAlign;
- label.setAttributeNS(null, "text-anchor",
- OpenLayers.Renderer.SVG.LABEL_ALIGN[align[0]] || "middle");
-
- if (OpenLayers.IS_GECKO === true) {
- label.setAttributeNS(null, "dominant-baseline",
- OpenLayers.Renderer.SVG.LABEL_ALIGN[align[1]] || "central");
- }
-
- var labelRows = style.label.split('\n');
- var numRows = labelRows.length;
- while (label.childNodes.length > numRows) {
- label.removeChild(label.lastChild);
- }
- for (var i = 0; i < numRows; i++) {
- var tspan = this.nodeFactory(featureId + suffix + "_tspan_" + i, "tspan");
- if (style.labelSelect === true) {
- tspan._featureId = featureId;
- tspan._geometry = location;
- tspan._geometryClass = location.CLASS_NAME;
- }
- if (OpenLayers.IS_GECKO === false) {
- tspan.setAttributeNS(null, "baseline-shift",
- OpenLayers.Renderer.SVG.LABEL_VSHIFT[align[1]] || "-35%");
- }
- tspan.setAttribute("x", x);
- if (i == 0) {
- var vfactor = OpenLayers.Renderer.SVG.LABEL_VFACTOR[align[1]];
- if (vfactor == null) {
- vfactor = -.5;
- }
- tspan.setAttribute("dy", (vfactor*(numRows-1)) + "em");
- } else {
- tspan.setAttribute("dy", "1em");
- }
- tspan.textContent = (labelRows[i] === '') ? ' ' : labelRows[i];
- if (!tspan.parentNode) {
- label.appendChild(tspan);
- }
- }
-
- if (!label.parentNode) {
- this.textRoot.appendChild(label);
- }
- },
-
- /**
- * Method: getComponentString
- *
- * Parameters:
- * components - {Array(<OpenLayers.Geometry.Point>)} Array of points
- * separator - {String} character between coordinate pairs. Defaults to ","
- *
- * Returns:
- * {Object} hash with properties "path" (the string created from the
- * components and "complete" (false if the renderer was unable to
- * draw all components)
- */
- getComponentsString: function(components, separator) {
- var renderCmp = [];
- var complete = true;
- var len = components.length;
- var strings = [];
- var str, component;
- for(var i=0; i<len; i++) {
- component = components[i];
- renderCmp.push(component);
- str = this.getShortString(component);
- if (str) {
- strings.push(str);
- } else {
- // The current component is outside the valid range. Let's
- // see if the previous or next component is inside the range.
- // If so, add the coordinate of the intersection with the
- // valid range bounds.
- if (i > 0) {
- if (this.getShortString(components[i - 1])) {
- strings.push(this.clipLine(components[i],
- components[i-1]));
- }
- }
- if (i < len - 1) {
- if (this.getShortString(components[i + 1])) {
- strings.push(this.clipLine(components[i],
- components[i+1]));
- }
- }
- complete = false;
- }
- }
-
- return {
- path: strings.join(separator || ","),
- complete: complete
- };
- },
-
- /**
- * Method: clipLine
- * Given two points (one inside the valid range, and one outside),
- * clips the line betweeen the two points so that the new points are both
- * inside the valid range.
- *
- * Parameters:
- * badComponent - {<OpenLayers.Geometry.Point>} original geometry of the
- * invalid point
- * goodComponent - {<OpenLayers.Geometry.Point>} original geometry of the
- * valid point
- * Returns
- * {String} the SVG coordinate pair of the clipped point (like
- * getShortString), or an empty string if both passed componets are at
- * the same point.
- */
- clipLine: function(badComponent, goodComponent) {
- if (goodComponent.equals(badComponent)) {
- return "";
- }
- var resolution = this.getResolution();
- var maxX = this.MAX_PIXEL - this.translationParameters.x;
- var maxY = this.MAX_PIXEL - this.translationParameters.y;
- var x1 = (goodComponent.x - this.featureDx) / resolution + this.left;
- var y1 = this.top - goodComponent.y / resolution;
- var x2 = (badComponent.x - this.featureDx) / resolution + this.left;
- var y2 = this.top - badComponent.y / resolution;
- var k;
- if (x2 < -maxX || x2 > maxX) {
- k = (y2 - y1) / (x2 - x1);
- x2 = x2 < 0 ? -maxX : maxX;
- y2 = y1 + (x2 - x1) * k;
- }
- if (y2 < -maxY || y2 > maxY) {
- k = (x2 - x1) / (y2 - y1);
- y2 = y2 < 0 ? -maxY : maxY;
- x2 = x1 + (y2 - y1) * k;
- }
- return x2 + "," + y2;
- },
-
- /**
- * Method: getShortString
- *
- * Parameters:
- * point - {<OpenLayers.Geometry.Point>}
- *
- * Returns:
- * {String} or false if point is outside the valid range
- */
- getShortString: function(point) {
- var resolution = this.getResolution();
- var x = ((point.x - this.featureDx) / resolution + this.left);
- var y = (this.top - point.y / resolution);
-
- if (this.inValidRange(x, y)) {
- return x + "," + y;
- } else {
- return false;
- }
- },
-
- /**
- * Method: getPosition
- * Finds the position of an svg node.
- *
- * Parameters:
- * node - {DOMElement}
- *
- * Returns:
- * {Object} hash with x and y properties, representing the coordinates
- * within the svg coordinate system
- */
- getPosition: function(node) {
- return({
- x: parseFloat(node.getAttributeNS(null, "cx")),
- y: parseFloat(node.getAttributeNS(null, "cy"))
- });
- },
-
- /**
- * Method: importSymbol
- * add a new symbol definition from the rendererer's symbol hash
- *
- * Parameters:
- * graphicName - {String} name of the symbol to import
- *
- * Returns:
- * {DOMElement} - the imported symbol
- */
- importSymbol: function (graphicName) {
- if (!this.defs) {
- // create svg defs tag
- this.defs = this.createDefs();
- }
- var id = this.container.id + "-" + graphicName;
-
- // check if symbol already exists in the defs
- var existing = document.getElementById(id);
- if (existing != null) {
- return existing;
- }
-
- var symbol = OpenLayers.Renderer.symbol[graphicName];
- if (!symbol) {
- throw new Error(graphicName + ' is not a valid symbol name');
- }
-
- var symbolNode = this.nodeFactory(id, "symbol");
- var node = this.nodeFactory(null, "polygon");
- symbolNode.appendChild(node);
- var symbolExtent = new OpenLayers.Bounds(
- Number.MAX_VALUE, Number.MAX_VALUE, 0, 0);
-
- var points = [];
- var x,y;
- for (var i=0; i<symbol.length; i=i+2) {
- x = symbol[i];
- y = symbol[i+1];
- symbolExtent.left = Math.min(symbolExtent.left, x);
- symbolExtent.bottom = Math.min(symbolExtent.bottom, y);
- symbolExtent.right = Math.max(symbolExtent.right, x);
- symbolExtent.top = Math.max(symbolExtent.top, y);
- points.push(x, ",", y);
- }
-
- node.setAttributeNS(null, "points", points.join(" "));
-
- var width = symbolExtent.getWidth();
- var height = symbolExtent.getHeight();
- // create a viewBox three times as large as the symbol itself,
- // to allow for strokeWidth being displayed correctly at the corners.
- var viewBox = [symbolExtent.left - width,
- symbolExtent.bottom - height, width * 3, height * 3];
- symbolNode.setAttributeNS(null, "viewBox", viewBox.join(" "));
- this.symbolMetrics[id] = [
- Math.max(width, height),
- symbolExtent.getCenterLonLat().lon,
- symbolExtent.getCenterLonLat().lat
- ];
-
- this.defs.appendChild(symbolNode);
- return symbolNode;
- },
-
- /**
- * Method: getFeatureIdFromEvent
- *
- * Parameters:
- * evt - {Object} An <OpenLayers.Event> object
- *
- * Returns:
- * {String} A feature id or undefined.
- */
- getFeatureIdFromEvent: function(evt) {
- var featureId = OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this, arguments);
- if(!featureId) {
- var target = evt.target;
- featureId = target.parentNode && target != this.rendererRoot ?
- target.parentNode._featureId : undefined;
- }
- return featureId;
- },
-
- CLASS_NAME: "OpenLayers.Renderer.SVG"
-});
-
-/**
- * Constant: OpenLayers.Renderer.SVG.LABEL_ALIGN
- * {Object}
- */
-OpenLayers.Renderer.SVG.LABEL_ALIGN = {
- "l": "start",
- "r": "end",
- "b": "bottom",
- "t": "hanging"
-};
-
-/**
- * Constant: OpenLayers.Renderer.SVG.LABEL_VSHIFT
- * {Object}
- */
-OpenLayers.Renderer.SVG.LABEL_VSHIFT = {
- // according to
- // http://www.w3.org/Graphics/SVG/Test/20061213/htmlObjectHarness/full-text-align-02-b.html
- // a baseline-shift of -70% shifts the text exactly from the
- // bottom to the top of the baseline, so -35% moves the text to
- // the center of the baseline.
- "t": "-70%",
- "b": "0"
-};
-
-/**
- * Constant: OpenLayers.Renderer.SVG.LABEL_VFACTOR
- * {Object}
- */
-OpenLayers.Renderer.SVG.LABEL_VFACTOR = {
- "t": 0,
- "b": -1
-};
-
-/**
- * Function: OpenLayers.Renderer.SVG.preventDefault
- * *Deprecated*. Use <OpenLayers.Event.preventDefault> method instead.
- * Used to prevent default events (especially opening images in a new tab on
- * ctrl-click) from being executed for externalGraphic symbols
- */
-OpenLayers.Renderer.SVG.preventDefault = function(e) {
- OpenLayers.Event.preventDefault(e);
-};
diff --git a/misc/openlayers/lib/OpenLayers/Renderer/VML.js b/misc/openlayers/lib/OpenLayers/Renderer/VML.js
deleted file mode 100644
index 8f6374b..0000000
--- a/misc/openlayers/lib/OpenLayers/Renderer/VML.js
+++ /dev/null
@@ -1,985 +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/Elements.js
- */
-
-/**
- * Class: OpenLayers.Renderer.VML
- * Render vector features in browsers with VML capability. Construct a new
- * VML renderer with the <OpenLayers.Renderer.VML> constructor.
- *
- * Note that for all calculations in this class, we use (num | 0) to truncate a
- * float value to an integer. This is done because it seems that VML doesn't
- * support float values.
- *
- * Inherits from:
- * - <OpenLayers.Renderer.Elements>
- */
-OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
-
- /**
- * Property: xmlns
- * {String} XML Namespace URN
- */
- xmlns: "urn:schemas-microsoft-com:vml",
-
- /**
- * Property: symbolCache
- * {DOMElement} node holding symbols. This hash is keyed by symbol name,
- * and each value is a hash with a "path" and an "extent" property.
- */
- symbolCache: {},
-
- /**
- * Property: offset
- * {Object} Hash with "x" and "y" properties
- */
- offset: null,
-
- /**
- * Constructor: OpenLayers.Renderer.VML
- * Create a new VML renderer.
- *
- * Parameters:
- * containerID - {String} The id for the element that contains the renderer
- */
- initialize: function(containerID) {
- if (!this.supported()) {
- return;
- }
- if (!document.namespaces.olv) {
- document.namespaces.add("olv", this.xmlns);
- var style = document.createStyleSheet();
- var shapes = ['shape','rect', 'oval', 'fill', 'stroke', 'imagedata', 'group','textbox'];
- for (var i = 0, len = shapes.length; i < len; i++) {
-
- style.addRule('olv\\:' + shapes[i], "behavior: url(#default#VML); " +
- "position: absolute; display: inline-block;");
- }
- }
-
- OpenLayers.Renderer.Elements.prototype.initialize.apply(this,
- arguments);
- },
-
- /**
- * APIMethod: supported
- * Determine whether a browser supports this renderer.
- *
- * Returns:
- * {Boolean} The browser supports the VML renderer
- */
- supported: function() {
- return !!(document.namespaces);
- },
-
- /**
- * Method: setExtent
- * Set the renderer's extent
- *
- * 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.
- */
- setExtent: function(extent, resolutionChanged) {
- var coordSysUnchanged = OpenLayers.Renderer.Elements.prototype.setExtent.apply(this, arguments);
- var resolution = this.getResolution();
-
- var left = (extent.left/resolution) | 0;
- var top = (extent.top/resolution - this.size.h) | 0;
- if (resolutionChanged || !this.offset) {
- this.offset = {x: left, y: top};
- left = 0;
- top = 0;
- } else {
- left = left - this.offset.x;
- top = top - this.offset.y;
- }
-
-
- var org = (left - this.xOffset) + " " + top;
- this.root.coordorigin = org;
- var roots = [this.root, this.vectorRoot, this.textRoot];
- var root;
- for(var i=0, len=roots.length; i<len; ++i) {
- root = roots[i];
-
- var size = this.size.w + " " + this.size.h;
- root.coordsize = size;
-
- }
- // flip the VML display Y axis upside down so it
- // matches the display Y axis of the map
- this.root.style.flip = "y";
-
- return coordSysUnchanged;
- },
-
-
- /**
- * Method: setSize
- * Set the size of the drawing surface
- *
- * Parameters:
- * size - {<OpenLayers.Size>} the size of the drawing surface
- */
- setSize: function(size) {
- OpenLayers.Renderer.prototype.setSize.apply(this, arguments);
-
- // setting width and height on all roots to avoid flicker which we
- // would get with 100% width and height on child roots
- var roots = [
- this.rendererRoot,
- this.root,
- this.vectorRoot,
- this.textRoot
- ];
- var w = this.size.w + "px";
- var h = this.size.h + "px";
- var root;
- for(var i=0, len=roots.length; i<len; ++i) {
- root = roots[i];
- root.style.width = w;
- root.style.height = h;
- }
- },
-
- /**
- * Method: getNodeType
- * Get the node type for a geometry and style
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- *
- * Returns:
- * {String} The corresponding node type for the specified geometry
- */
- getNodeType: function(geometry, style) {
- var nodeType = null;
- switch (geometry.CLASS_NAME) {
- case "OpenLayers.Geometry.Point":
- if (style.externalGraphic) {
- nodeType = "olv:rect";
- } else if (this.isComplexSymbol(style.graphicName)) {
- nodeType = "olv:shape";
- } else {
- nodeType = "olv:oval";
- }
- break;
- case "OpenLayers.Geometry.Rectangle":
- nodeType = "olv:rect";
- break;
- case "OpenLayers.Geometry.LineString":
- case "OpenLayers.Geometry.LinearRing":
- case "OpenLayers.Geometry.Polygon":
- case "OpenLayers.Geometry.Curve":
- nodeType = "olv:shape";
- break;
- default:
- break;
- }
- return nodeType;
- },
-
- /**
- * Method: setStyle
- * Use to set all the style attributes to a VML node.
- *
- * Parameters:
- * node - {DOMElement} An VML element to decorate
- * style - {Object}
- * options - {Object} Currently supported options include
- * 'isFilled' {Boolean} and
- * 'isStroked' {Boolean}
- * geometry - {<OpenLayers.Geometry>}
- */
- setStyle: function(node, style, options, geometry) {
- style = style || node._style;
- options = options || node._options;
- var fillColor = style.fillColor;
-
- var title = style.title || style.graphicTitle;
- if (title) {
- node.title = title;
- }
-
- if (node._geometryClass === "OpenLayers.Geometry.Point") {
- if (style.externalGraphic) {
- options.isFilled = true;
- 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 resolution = this.getResolution();
- var xOffset = (style.graphicXOffset != undefined) ?
- style.graphicXOffset : -(0.5 * width);
- var yOffset = (style.graphicYOffset != undefined) ?
- style.graphicYOffset : -(0.5 * height);
-
- node.style.left = ((((geometry.x - this.featureDx)/resolution - this.offset.x)+xOffset) | 0) + "px";
- node.style.top = (((geometry.y/resolution - this.offset.y)-(yOffset+height)) | 0) + "px";
- node.style.width = width + "px";
- node.style.height = height + "px";
- node.style.flip = "y";
-
- // modify fillColor and options for stroke styling below
- fillColor = "none";
- options.isStroked = false;
- } else if (this.isComplexSymbol(style.graphicName)) {
- var cache = this.importSymbol(style.graphicName);
- node.path = cache.path;
- node.coordorigin = cache.left + "," + cache.bottom;
- var size = cache.size;
- node.coordsize = size + "," + size;
- this.drawCircle(node, geometry, style.pointRadius);
- node.style.flip = "y";
- } else {
- this.drawCircle(node, geometry, style.pointRadius);
- }
- }
-
- // fill
- if (options.isFilled) {
- node.fillcolor = fillColor;
- } else {
- node.filled = "false";
- }
- var fills = node.getElementsByTagName("fill");
- var fill = (fills.length == 0) ? null : fills[0];
- if (!options.isFilled) {
- if (fill) {
- node.removeChild(fill);
- }
- } else {
- if (!fill) {
- fill = this.createNode('olv:fill', node.id + "_fill");
- }
- fill.opacity = style.fillOpacity;
-
- if (node._geometryClass === "OpenLayers.Geometry.Point" &&
- style.externalGraphic) {
-
- // override fillOpacity
- if (style.graphicOpacity) {
- fill.opacity = style.graphicOpacity;
- }
-
- fill.src = style.externalGraphic;
- fill.type = "frame";
-
- if (!(style.graphicWidth && style.graphicHeight)) {
- fill.aspect = "atmost";
- }
- }
- if (fill.parentNode != node) {
- node.appendChild(fill);
- }
- }
-
- // additional rendering for rotated graphics or symbols
- var rotation = style.rotation;
- if ((rotation !== undefined || node._rotation !== undefined)) {
- node._rotation = rotation;
- if (style.externalGraphic) {
- this.graphicRotate(node, xOffset, yOffset, style);
- // make the fill fully transparent, because we now have
- // the graphic as imagedata element. We cannot just remove
- // the fill, because this is part of the hack described
- // in graphicRotate
- fill.opacity = 0;
- } else if(node._geometryClass === "OpenLayers.Geometry.Point") {
- node.style.rotation = rotation || 0;
- }
- }
-
- // stroke
- var strokes = node.getElementsByTagName("stroke");
- var stroke = (strokes.length == 0) ? null : strokes[0];
- if (!options.isStroked) {
- node.stroked = false;
- if (stroke) {
- stroke.on = false;
- }
- } else {
- if (!stroke) {
- stroke = this.createNode('olv:stroke', node.id + "_stroke");
- node.appendChild(stroke);
- }
- stroke.on = true;
- stroke.color = style.strokeColor;
- stroke.weight = style.strokeWidth + "px";
- stroke.opacity = style.strokeOpacity;
- stroke.endcap = style.strokeLinecap == 'butt' ? 'flat' :
- (style.strokeLinecap || 'round');
- if (style.strokeDashstyle) {
- stroke.dashstyle = this.dashStyle(style);
- }
- }
-
- if (style.cursor != "inherit" && style.cursor != null) {
- node.style.cursor = style.cursor;
- }
- return node;
- },
-
- /**
- * Method: graphicRotate
- * If a point is to be styled with externalGraphic and rotation, VML fills
- * cannot be used to display the graphic, because rotation of graphic
- * fills is not supported by the VML implementation of Internet Explorer.
- * This method creates a olv:imagedata element inside the VML node,
- * DXImageTransform.Matrix and BasicImage filters for rotation and
- * opacity, and a 3-step hack to remove rendering artefacts from the
- * graphic and preserve the ability of graphics to trigger events.
- * Finally, OpenLayers methods are used to determine the correct
- * insertion point of the rotated image, because DXImageTransform.Matrix
- * does the rotation without the ability to specify a rotation center
- * point.
- *
- * Parameters:
- * node - {DOMElement}
- * xOffset - {Number} rotation center relative to image, x coordinate
- * yOffset - {Number} rotation center relative to image, y coordinate
- * style - {Object}
- */
- graphicRotate: function(node, xOffset, yOffset, style) {
- var style = style || node._style;
- var rotation = style.rotation || 0;
-
- var aspectRatio, size;
- if (!(style.graphicWidth && style.graphicHeight)) {
- // load the image to determine its size
- var img = new Image();
- img.onreadystatechange = OpenLayers.Function.bind(function() {
- if(img.readyState == "complete" ||
- img.readyState == "interactive") {
- aspectRatio = img.width / img.height;
- size = Math.max(style.pointRadius * 2,
- style.graphicWidth || 0,
- style.graphicHeight || 0);
- xOffset = xOffset * aspectRatio;
- style.graphicWidth = size * aspectRatio;
- style.graphicHeight = size;
- this.graphicRotate(node, xOffset, yOffset, style);
- }
- }, this);
- img.src = style.externalGraphic;
-
- // will be called again by the onreadystate handler
- return;
- } else {
- size = Math.max(style.graphicWidth, style.graphicHeight);
- aspectRatio = style.graphicWidth / style.graphicHeight;
- }
-
- var width = Math.round(style.graphicWidth || size * aspectRatio);
- var height = Math.round(style.graphicHeight || size);
- node.style.width = width + "px";
- node.style.height = height + "px";
-
- // Three steps are required to remove artefacts for images with
- // transparent backgrounds (resulting from using DXImageTransform
- // filters on svg objects), while preserving awareness for browser
- // events on images:
- // - Use the fill as usual (like for unrotated images) to handle
- // events
- // - specify an imagedata element with the same src as the fill
- // - style the imagedata element with an AlphaImageLoader filter
- // with empty src
- var image = document.getElementById(node.id + "_image");
- if (!image) {
- image = this.createNode("olv:imagedata", node.id + "_image");
- node.appendChild(image);
- }
- image.style.width = width + "px";
- image.style.height = height + "px";
- image.src = style.externalGraphic;
- image.style.filter =
- "progid:DXImageTransform.Microsoft.AlphaImageLoader(" +
- "src='', sizingMethod='scale')";
-
- var rot = rotation * Math.PI / 180;
- var sintheta = Math.sin(rot);
- var costheta = Math.cos(rot);
-
- // do the rotation on the image
- var filter =
- "progid:DXImageTransform.Microsoft.Matrix(M11=" + costheta +
- ",M12=" + (-sintheta) + ",M21=" + sintheta + ",M22=" + costheta +
- ",SizingMethod='auto expand')\n";
-
- // set the opacity (needed for the imagedata)
- var opacity = style.graphicOpacity || style.fillOpacity;
- if (opacity && opacity != 1) {
- filter +=
- "progid:DXImageTransform.Microsoft.BasicImage(opacity=" +
- opacity+")\n";
- }
- node.style.filter = filter;
-
- // do the rotation again on a box, so we know the insertion point
- var centerPoint = new OpenLayers.Geometry.Point(-xOffset, -yOffset);
- var imgBox = new OpenLayers.Bounds(0, 0, width, height).toGeometry();
- imgBox.rotate(style.rotation, centerPoint);
- var imgBounds = imgBox.getBounds();
-
- node.style.left = Math.round(
- parseInt(node.style.left) + imgBounds.left) + "px";
- node.style.top = Math.round(
- parseInt(node.style.top) - imgBounds.bottom) + "px";
- },
-
- /**
- * Method: postDraw
- * Does some node postprocessing to work around browser issues:
- * - Some versions of Internet Explorer seem to be unable to set fillcolor
- * and strokecolor to "none" correctly before the fill node is appended
- * to a visible vml node. This method takes care of that and sets
- * fillcolor and strokecolor again if needed.
- * - In some cases, a node won't become visible after being drawn. Setting
- * style.visibility to "visible" works around that.
- *
- * Parameters:
- * node - {DOMElement}
- */
- postDraw: function(node) {
- node.style.visibility = "visible";
- var fillColor = node._style.fillColor;
- var strokeColor = node._style.strokeColor;
- if (fillColor == "none" &&
- node.fillcolor != fillColor) {
- node.fillcolor = fillColor;
- }
- if (strokeColor == "none" &&
- node.strokecolor != strokeColor) {
- node.strokecolor = strokeColor;
- }
- },
-
-
- /**
- * Method: setNodeDimension
- * Get the geometry's bounds, convert it to our vml coordinate system,
- * then set the node's position, size, and local coordinate system.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- */
- setNodeDimension: function(node, geometry) {
-
- var bbox = geometry.getBounds();
- if(bbox) {
- var resolution = this.getResolution();
-
- var scaledBox =
- new OpenLayers.Bounds(((bbox.left - this.featureDx)/resolution - this.offset.x) | 0,
- (bbox.bottom/resolution - this.offset.y) | 0,
- ((bbox.right - this.featureDx)/resolution - this.offset.x) | 0,
- (bbox.top/resolution - this.offset.y) | 0);
-
- // Set the internal coordinate system to draw the path
- node.style.left = scaledBox.left + "px";
- node.style.top = scaledBox.top + "px";
- node.style.width = scaledBox.getWidth() + "px";
- node.style.height = scaledBox.getHeight() + "px";
-
- node.coordorigin = scaledBox.left + " " + scaledBox.top;
- node.coordsize = scaledBox.getWidth()+ " " + scaledBox.getHeight();
- }
- },
-
- /**
- * Method: dashStyle
- *
- * Parameters:
- * style - {Object}
- *
- * Returns:
- * {String} A VML compliant 'stroke-dasharray' value
- */
- dashStyle: function(style) {
- var dash = style.strokeDashstyle;
- switch (dash) {
- case 'solid':
- case 'dot':
- case 'dash':
- case 'dashdot':
- case 'longdash':
- case 'longdashdot':
- return dash;
- default:
- // very basic guessing of dash style patterns
- var parts = dash.split(/[ ,]/);
- if (parts.length == 2) {
- if (1*parts[0] >= 2*parts[1]) {
- return "longdash";
- }
- return (parts[0] == 1 || parts[1] == 1) ? "dot" : "dash";
- } else if (parts.length == 4) {
- return (1*parts[0] >= 2*parts[1]) ? "longdashdot" :
- "dashdot";
- }
- return "solid";
- }
- },
-
- /**
- * Method: createNode
- * Create a new node
- *
- * Parameters:
- * type - {String} Kind of node to draw
- * id - {String} Id for node
- *
- * Returns:
- * {DOMElement} A new node of the given type and id
- */
- createNode: function(type, id) {
- var node = document.createElement(type);
- if (id) {
- node.id = id;
- }
-
- // IE hack to make elements unselectable, to prevent 'blue flash'
- // while dragging vectors; #1410
- node.unselectable = 'on';
- node.onselectstart = OpenLayers.Function.False;
-
- return node;
- },
-
- /**
- * Method: nodeTypeCompare
- * Determine whether a node is of a given type
- *
- * Parameters:
- * node - {DOMElement} An VML element
- * type - {String} Kind of node
- *
- * Returns:
- * {Boolean} Whether or not the specified node is of the specified type
- */
- nodeTypeCompare: function(node, type) {
-
- //split type
- var subType = type;
- var splitIndex = subType.indexOf(":");
- if (splitIndex != -1) {
- subType = subType.substr(splitIndex+1);
- }
-
- //split nodeName
- var nodeName = node.nodeName;
- splitIndex = nodeName.indexOf(":");
- if (splitIndex != -1) {
- nodeName = nodeName.substr(splitIndex+1);
- }
-
- return (subType == nodeName);
- },
-
- /**
- * Method: createRenderRoot
- * Create the renderer root
- *
- * Returns:
- * {DOMElement} The specific render engine's root element
- */
- createRenderRoot: function() {
- return this.nodeFactory(this.container.id + "_vmlRoot", "div");
- },
-
- /**
- * Method: createRoot
- * Create the main root element
- *
- * Parameters:
- * suffix - {String} suffix to append to the id
- *
- * Returns:
- * {DOMElement}
- */
- createRoot: function(suffix) {
- return this.nodeFactory(this.container.id + suffix, "olv:group");
- },
-
- /**************************************
- * *
- * GEOMETRY DRAWING FUNCTIONS *
- * *
- **************************************/
-
- /**
- * Method: drawPoint
- * Render a point
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the point could not be drawn
- */
- drawPoint: function(node, geometry) {
- return this.drawCircle(node, geometry, 1);
- },
-
- /**
- * Method: drawCircle
- * Render a circle.
- * Size and Center a circle given geometry (x,y center) and radius
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- * radius - {float}
- *
- * Returns:
- * {DOMElement} or false if the circle could not ne drawn
- */
- drawCircle: function(node, geometry, radius) {
- if(!isNaN(geometry.x)&& !isNaN(geometry.y)) {
- var resolution = this.getResolution();
-
- node.style.left = ((((geometry.x - this.featureDx) /resolution - this.offset.x) | 0) - radius) + "px";
- node.style.top = (((geometry.y /resolution - this.offset.y) | 0) - radius) + "px";
-
- var diameter = radius * 2;
-
- node.style.width = diameter + "px";
- node.style.height = diameter + "px";
- return node;
- }
- return false;
- },
-
-
- /**
- * Method: drawLineString
- * Render a linestring.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement}
- */
- drawLineString: function(node, geometry) {
- return this.drawLine(node, geometry, false);
- },
-
- /**
- * Method: drawLinearRing
- * Render a linearring
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement}
- */
- drawLinearRing: function(node, geometry) {
- return this.drawLine(node, geometry, true);
- },
-
- /**
- * Method: DrawLine
- * Render a line.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- * closeLine - {Boolean} Close the line? (make it a ring?)
- *
- * Returns:
- * {DOMElement}
- */
- drawLine: function(node, geometry, closeLine) {
-
- this.setNodeDimension(node, geometry);
-
- var resolution = this.getResolution();
- var numComponents = geometry.components.length;
- var parts = new Array(numComponents);
-
- var comp, x, y;
- for (var i = 0; i < numComponents; i++) {
- comp = geometry.components[i];
- x = ((comp.x - this.featureDx)/resolution - this.offset.x) | 0;
- y = (comp.y/resolution - this.offset.y) | 0;
- parts[i] = " " + x + "," + y + " l ";
- }
- var end = (closeLine) ? " x e" : " e";
- node.path = "m" + parts.join("") + end;
- return node;
- },
-
- /**
- * Method: drawPolygon
- * Render a polygon
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement}
- */
- drawPolygon: function(node, geometry) {
- this.setNodeDimension(node, geometry);
-
- var resolution = this.getResolution();
-
- var path = [];
- var j, jj, points, area, first, second, i, ii, comp, pathComp, x, y;
- for (j=0, jj=geometry.components.length; j<jj; j++) {
- path.push("m");
- points = geometry.components[j].components;
- // we only close paths of interior rings with area
- area = (j === 0);
- first = null;
- second = null;
- for (i=0, ii=points.length; i<ii; i++) {
- comp = points[i];
- x = ((comp.x - this.featureDx) / resolution - this.offset.x) | 0;
- y = (comp.y / resolution - this.offset.y) | 0;
- pathComp = " " + x + "," + y;
- path.push(pathComp);
- if (i==0) {
- path.push(" l");
- }
- if (!area) {
- // IE improperly renders sub-paths that have no area.
- // Instead of checking the area of every ring, we confirm
- // the ring has at least three distinct points. This does
- // not catch all non-zero area cases, but it greatly improves
- // interior ring digitizing and is a minor performance hit
- // when rendering rings with many points.
- if (!first) {
- first = pathComp;
- } else if (first != pathComp) {
- if (!second) {
- second = pathComp;
- } else if (second != pathComp) {
- // stop looking
- area = true;
- }
- }
- }
- }
- path.push(area ? " x " : " ");
- }
- path.push("e");
- node.path = path.join("");
- return node;
- },
-
- /**
- * Method: drawRectangle
- * Render a rectangle
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement}
- */
- drawRectangle: function(node, geometry) {
- var resolution = this.getResolution();
-
- node.style.left = (((geometry.x - this.featureDx)/resolution - this.offset.x) | 0) + "px";
- node.style.top = ((geometry.y/resolution - this.offset.y) | 0) + "px";
- node.style.width = ((geometry.width/resolution) | 0) + "px";
- node.style.height = ((geometry.height/resolution) | 0) + "px";
-
- return node;
- },
-
- /**
- * Method: drawText
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * featureId - {String}
- * style -
- * location - {<OpenLayers.Geometry.Point>}
- */
- drawText: function(featureId, style, location) {
- var label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, "olv:rect");
- var textbox = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_textbox", "olv:textbox");
-
- var resolution = this.getResolution();
- label.style.left = (((location.x - this.featureDx)/resolution - this.offset.x) | 0) + "px";
- label.style.top = ((location.y/resolution - this.offset.y) | 0) + "px";
- label.style.flip = "y";
-
- textbox.innerText = style.label;
-
- if (style.cursor != "inherit" && style.cursor != null) {
- textbox.style.cursor = style.cursor;
- }
- if (style.fontColor) {
- textbox.style.color = style.fontColor;
- }
- if (style.fontOpacity) {
- textbox.style.filter = 'alpha(opacity=' + (style.fontOpacity * 100) + ')';
- }
- if (style.fontFamily) {
- textbox.style.fontFamily = style.fontFamily;
- }
- if (style.fontSize) {
- textbox.style.fontSize = style.fontSize;
- }
- if (style.fontWeight) {
- textbox.style.fontWeight = style.fontWeight;
- }
- if (style.fontStyle) {
- textbox.style.fontStyle = style.fontStyle;
- }
- if(style.labelSelect === true) {
- label._featureId = featureId;
- textbox._featureId = featureId;
- textbox._geometry = location;
- textbox._geometryClass = location.CLASS_NAME;
- }
- textbox.style.whiteSpace = "nowrap";
- // fun with IE: IE7 in standards compliant mode does not display any
- // text with a left inset of 0. So we set this to 1px and subtract one
- // pixel later when we set label.style.left
- textbox.inset = "1px,0px,0px,0px";
-
- if(!label.parentNode) {
- label.appendChild(textbox);
- this.textRoot.appendChild(label);
- }
-
- var align = style.labelAlign || "cm";
- if (align.length == 1) {
- align += "m";
- }
- var xshift = textbox.clientWidth *
- (OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(0,1)]);
- var yshift = textbox.clientHeight *
- (OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(1,1)]);
- label.style.left = parseInt(label.style.left)-xshift-1+"px";
- label.style.top = parseInt(label.style.top)+yshift+"px";
-
- },
-
- /**
- * Method: moveRoot
- * moves this renderer's root to a different renderer.
- *
- * Parameters:
- * renderer - {<OpenLayers.Renderer>} target renderer for the moved root
- * root - {DOMElement} optional root node. To be used when this renderer
- * holds roots from multiple layers to tell this method which one to
- * detach
- *
- * Returns:
- * {Boolean} true if successful, false otherwise
- */
- moveRoot: function(renderer) {
- var layer = this.map.getLayer(renderer.container.id);
- if(layer instanceof OpenLayers.Layer.Vector.RootContainer) {
- layer = this.map.getLayer(this.container.id);
- }
- layer && layer.renderer.clear();
- OpenLayers.Renderer.Elements.prototype.moveRoot.apply(this, arguments);
- layer && layer.redraw();
- },
-
- /**
- * Method: importSymbol
- * add a new symbol definition from the rendererer's symbol hash
- *
- * Parameters:
- * graphicName - {String} name of the symbol to import
- *
- * Returns:
- * {Object} - hash of {DOMElement} "symbol" and {Number} "size"
- */
- importSymbol: function (graphicName) {
- var id = this.container.id + "-" + graphicName;
-
- // check if symbol already exists in the cache
- var cache = this.symbolCache[id];
- if (cache) {
- return cache;
- }
-
- var symbol = OpenLayers.Renderer.symbol[graphicName];
- if (!symbol) {
- throw new Error(graphicName + ' is not a valid symbol name');
- }
-
- var symbolExtent = new OpenLayers.Bounds(
- Number.MAX_VALUE, Number.MAX_VALUE, 0, 0);
-
- var pathitems = ["m"];
- for (var i=0; i<symbol.length; i=i+2) {
- var x = symbol[i];
- var y = symbol[i+1];
- symbolExtent.left = Math.min(symbolExtent.left, x);
- symbolExtent.bottom = Math.min(symbolExtent.bottom, y);
- symbolExtent.right = Math.max(symbolExtent.right, x);
- symbolExtent.top = Math.max(symbolExtent.top, y);
-
- pathitems.push(x);
- pathitems.push(y);
- if (i == 0) {
- pathitems.push("l");
- }
- }
- pathitems.push("x e");
- var path = pathitems.join(" ");
-
- var diff = (symbolExtent.getWidth() - symbolExtent.getHeight()) / 2;
- if(diff > 0) {
- symbolExtent.bottom = symbolExtent.bottom - diff;
- symbolExtent.top = symbolExtent.top + diff;
- } else {
- symbolExtent.left = symbolExtent.left + diff;
- symbolExtent.right = symbolExtent.right - diff;
- }
-
- cache = {
- path: path,
- size: symbolExtent.getWidth(), // equals getHeight() now
- left: symbolExtent.left,
- bottom: symbolExtent.bottom
- };
- this.symbolCache[id] = cache;
-
- return cache;
- },
-
- CLASS_NAME: "OpenLayers.Renderer.VML"
-});
-
-/**
- * Constant: OpenLayers.Renderer.VML.LABEL_SHIFT
- * {Object}
- */
-OpenLayers.Renderer.VML.LABEL_SHIFT = {
- "l": 0,
- "c": .5,
- "r": 1,
- "t": 0,
- "m": .5,
- "b": 1
-};