diff options
author | Chris Schlaeger <chris@linux.com> | 2015-10-17 21:36:38 +0200 |
---|---|---|
committer | Chris Schlaeger <chris@linux.com> | 2015-10-17 21:36:38 +0200 |
commit | e30f267181d990947e67909de4809fa941698c85 (patch) | |
tree | 46e9f94c2b3699ed378963b420b8a8d361286ea1 /misc/openlayers/lib/OpenLayers/Renderer | |
parent | e763ceb183f389fcd314a4a6a712d87c9d4cdb32 (diff) | |
download | postrunner-e30f267181d990947e67909de4809fa941698c85.zip |
Upgrading openlayers to 3.x
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Renderer')
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Renderer/Canvas.js | 906 | ||||
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Renderer/Elements.js | 1053 | ||||
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Renderer/SVG.js | 1012 | ||||
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Renderer/VML.js | 985 |
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 -}; |