diff options
Diffstat (limited to 'src/js/util/mxImageExport.js')
-rw-r--r-- | src/js/util/mxImageExport.js | 1412 |
1 files changed, 0 insertions, 1412 deletions
diff --git a/src/js/util/mxImageExport.js b/src/js/util/mxImageExport.js deleted file mode 100644 index dcbcf9a..0000000 --- a/src/js/util/mxImageExport.js +++ /dev/null @@ -1,1412 +0,0 @@ -/** - * $Id: mxImageExport.js,v 1.47 2012-09-24 14:54:32 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxImageExport - * - * Creates a new image export instance to be used with an export canvas. Here - * is an example that uses this class to create an image via a backend using - * <mxXmlExportCanvas>. - * - * (code) - * var xmlDoc = mxUtils.createXmlDocument(); - * var root = xmlDoc.createElement('output'); - * xmlDoc.appendChild(root); - * - * var xmlCanvas = new mxXmlCanvas2D(root); - * var imgExport = new mxImageExport(); - * imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas); - * - * var bounds = graph.getGraphBounds(); - * var w = Math.ceil(bounds.x + bounds.width); - * var h = Math.ceil(bounds.y + bounds.height); - * - * var xml = mxUtils.getXml(root); - * new mxXmlRequest('export', 'format=png&w=' + w + - * '&h=' + h + '&bg=#F9F7ED&xml=' + encodeURIComponent(xml)) - * .simulate(document, '_blank'); - * (end) - * - * In order to export images for a graph whose container is not visible or not - * part of the DOM, the following workaround can be used to compute the size of - * the labels. - * - * (code) - * mxText.prototype.getTableSize = function(table) - * { - * var oldParent = table.parentNode; - * - * document.body.appendChild(table); - * var size = new mxRectangle(0, 0, table.offsetWidth, table.offsetHeight); - * oldParent.appendChild(table); - * - * return size; - * }; - * (end) - * - * Constructor: mxImageExport - * - * Constructs a new image export. - */ -function mxImageExport() -{ - this.initShapes(); - this.initMarkers(); -}; - -/** - * Variable: includeOverlays - * - * Specifies if overlays should be included in the export. Default is false. - */ -mxImageExport.prototype.includeOverlays = false; - -/** - * Variable: glassSize - * - * Reference to the thread while the animation is running. - */ -mxImageExport.prototype.glassSize = 0.4; - -/** - * Variable: shapes - * - * Holds implementations for the built-in shapes. - */ -mxImageExport.prototype.shapes = null; - -/** - * Variable: markers - * - * Holds implementations for the built-in markers. - */ -mxImageExport.prototype.markers = null; - -/** - * Function: drawState - * - * Draws the given state and all its descendants to the given canvas. - */ -mxImageExport.prototype.drawState = function(state, canvas) -{ - if (state != null) - { - if (state.shape != null) - { - var shape = (state.shape.stencil != null) ? - state.shape.stencil : - this.shapes[state.style[mxConstants.STYLE_SHAPE]]; - - if (shape == null) - { - // Checks if there is a custom shape - if (typeof(state.shape.redrawPath) == 'function') - { - shape = this.createShape(state, canvas); - } - // Uses a rectangle for all vertices where no shape can be found - else if (state.view.graph.getModel().isVertex(state.cell)) - { - shape = this.shapes['rectangle']; - } - } - - if (shape != null) - { - this.drawShape(state, canvas, shape); - - if (this.includeOverlays) - { - this.drawOverlays(state, canvas); - } - } - } - - var graph = state.view.graph; - var childCount = graph.model.getChildCount(state.cell); - - for (var i = 0; i < childCount; i++) - { - var childState = graph.view.getState(graph.model.getChildAt(state.cell, i)); - this.drawState(childState, canvas); - } - } -}; - -/** - * Function: createShape - * - * Creates a shape wrapper for the custom shape in the given cell state and - * links its output to the given canvas. - */ -mxImageExport.prototype.createShape = function(state, canvas) -{ - return { - drawShape: function(canvas, state, bounds, background) - { - var path = - { - translate: new mxPoint(bounds.x, bounds.y), - moveTo: function(x, y) - { - canvas.moveTo(this.translate.x + x, this.translate.y + y); - }, - lineTo: function(x, y) - { - canvas.lineTo(this.translate.x + x, this.translate.y + y); - }, - quadTo: function(x1, y1, x, y) - { - canvas.quadTo(this.translate.x + x1, this.translate.y + y1, this.translate.x + x, this.translate.y + y); - }, - curveTo: function(x1, y1, x2, y2, x, y) - { - canvas.curveTo(this.translate.x + x1, this.translate.y + y1, this.translate.x + x2, this.translate.y + y2, this.translate.x + x, this.translate.y + y); - }, - end: function() - { - // do nothing - }, - close: function() - { - canvas.close(); - } - }; - - if (!background) - { - canvas.fillAndStroke(); - } - - // LATER: Remove empty path if shape does not implement foreground, add shadow/clipping - canvas.begin(); - state.shape.redrawPath.call(state.shape, path, bounds.x, bounds.y, bounds.width, bounds.height, !background); - - if (!background) - { - canvas.fillAndStroke(); - } - - return true; - } - }; -}; - -/** - * Function: drawOverlays - * - * Draws the overlays for the given state. This is called if <includeOverlays> - * is true. - */ -mxImageExport.prototype.drawOverlays = function(state, canvas) -{ - if (state.overlays != null) - { - state.overlays.visit(function(id, shape) - { - var bounds = shape.bounds; - - if (bounds != null) - { - canvas.image(bounds.x, bounds.y, bounds.width, bounds.height, shape.image); - } - }); - } -}; - -/** - * Function: drawShape - * - * Draws the given state to the given canvas. - */ -mxImageExport.prototype.drawShape = function(state, canvas, shape) -{ - var rotation = mxUtils.getNumber(state.style, mxConstants.STYLE_ROTATION, 0); - var direction = mxUtils.getValue(state.style, mxConstants.STYLE_DIRECTION, null); - - // New styles for shape flipping the stencil - var flipH = state.style[mxConstants.STYLE_STENCIL_FLIPH]; - var flipV = state.style[mxConstants.STYLE_STENCIL_FLIPV]; - - if (flipH ? !flipV : flipV) - { - rotation *= -1; - } - - // Default direction is east (ignored if rotation exists) - if (direction != null) - { - if (direction == 'north') - { - rotation += 270; - } - else if (direction == 'west') - { - rotation += 180; - } - else if (direction == 'south') - { - rotation += 90; - } - } - - if (flipH && flipV) - { - rotation += 180; - flipH = false; - flipV = false; - } - - // Saves the global state for each cell - canvas.save(); - - // Adds rotation and horizontal/vertical flipping - // FIXME: Rotation and stencil flip only supported for stencil shapes - rotation = rotation % 360; - - if (rotation != 0 || flipH || flipV) - { - canvas.rotate(rotation, flipH, flipV, state.getCenterX(), state.getCenterY()); - } - - // Note: Overwritten in mxStencil.paintShape (can depend on aspect) - var scale = state.view.scale; - var sw = mxUtils.getNumber(state.style, mxConstants.STYLE_STROKEWIDTH, 1) * scale; - canvas.setStrokeWidth(sw); - - var sw2 = sw / 2; - var bg = this.getBackgroundBounds(state); - - // Stencils will rotate the bounds as required - if (state.shape.stencil == null && (direction == 'south' || direction == 'north')) - { - var dx = (bg.width - bg.height) / 2; - bg.x += dx; - bg.y += -dx; - var tmp = bg.width; - bg.width = bg.height; - bg.height = tmp; - } - - var bb = new mxRectangle(bg.x - sw2, bg.y - sw2, bg.width + sw, bg.height + sw); - var alpha = mxUtils.getValue(state.style, mxConstants.STYLE_OPACITY, 100) / 100; - - var shp = state.style[mxConstants.STYLE_SHAPE]; - var imageShape = shp == mxConstants.SHAPE_IMAGE; - var gradientColor = (imageShape) ? null : mxUtils.getValue(state.style, mxConstants.STYLE_GRADIENTCOLOR); - - // Converts colors with special keyword none to null - if (gradientColor == mxConstants.NONE) - { - gradientColor = null; - } - - var fcKey = (imageShape) ? mxConstants.STYLE_IMAGE_BACKGROUND : mxConstants.STYLE_FILLCOLOR; - var fillColor = mxUtils.getValue(state.style, fcKey, null); - - if (fillColor == mxConstants.NONE) - { - fillColor = null; - } - - var scKey = (imageShape) ? mxConstants.STYLE_IMAGE_BORDER : mxConstants.STYLE_STROKECOLOR; - var strokeColor = mxUtils.getValue(state.style, scKey, null); - - if (strokeColor == mxConstants.NONE) - { - strokeColor = null; - } - - var glass = (fillColor != null && (shp == mxConstants.SHAPE_LABEL || shp == mxConstants.SHAPE_RECTANGLE)); - - // Draws the shadow if the fillColor is not transparent - if (mxUtils.getValue(state.style, mxConstants.STYLE_SHADOW, false)) - { - this.drawShadow(canvas, state, shape, rotation, flipH, flipV, bg, alpha, fillColor != null); - } - - canvas.setAlpha(alpha); - - // Sets the dashed state - if (mxUtils.getValue(state.style, mxConstants.STYLE_DASHED, '0') == '1') - { - canvas.setDashed(true); - - // Supports custom dash patterns - var dash = state.style['dashPattern']; - - if (dash != null) - { - canvas.setDashPattern(dash); - } - } - - // Draws background and foreground - if (strokeColor != null || fillColor != null) - { - if (strokeColor != null) - { - canvas.setStrokeColor(strokeColor); - } - - if (fillColor != null) - { - if (gradientColor != null && gradientColor != 'transparent') - { - canvas.setGradient(fillColor, gradientColor, bg.x, bg.y, bg.width, bg.height, direction); - } - else - { - canvas.setFillColor(fillColor); - } - } - - // Draws background and foreground of shape - glass = shape.drawShape(canvas, state, bg, true, false) && glass; - shape.drawShape(canvas, state, bg, false, false); - } - - // Draws the glass effect - // Requires background in generic shape for clipping - if (glass && mxUtils.getValue(state.style, mxConstants.STYLE_GLASS, 0) == 1) - { - this.drawGlass(state, canvas, bb, shape, this.glassSize); - } - - // Draws the image (currently disabled for everything but image and label shapes) - if (imageShape || shp == mxConstants.SHAPE_LABEL) - { - var src = state.view.graph.getImage(state); - - if (src != null) - { - var imgBounds = this.getImageBounds(state); - - if (imgBounds != null) - { - this.drawImage(state, canvas, imgBounds, src); - } - } - } - - // Restores canvas state - canvas.restore(); - - // Draws the label (label has separate rotation) - var txt = state.text; - - // Does not use mxCellRenderer.getLabelValue to avoid conversion of HTML entities for VML - var label = state.view.graph.getLabel(state.cell); - - if (txt != null && label != null && label.length > 0) - { - canvas.save(); - canvas.setAlpha(mxUtils.getValue(state.style, mxConstants.STYLE_TEXT_OPACITY, 100) / 100); - var bounds = new mxRectangle(txt.boundingBox.x, txt.boundingBox.y, txt.boundingBox.width, txt.boundingBox.height); - var vert = mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, 1) == 0; - - // Vertical error offset - bounds.y += 2; - - if (vert) - { - if (txt.dialect != mxConstants.DIALECT_SVG) - { - var cx = bounds.x + bounds.width / 2; - var cy = bounds.y + bounds.height / 2; - var tmp = bounds.width; - bounds.width = bounds.height; - bounds.height = tmp; - bounds.x = cx - bounds.width / 2; - bounds.y = cy - bounds.height / 2; - } - else if (txt.dialect == mxConstants.DIALECT_SVG) - { - // Workarounds for different label bounding boxes (mostly ignoring rotation). - // LATER: Fix in mxText so that the bounding box is consistent and rotated. - // TODO: Check non-center/middle-aligned vertical labels in VML for IE8. - var b = state.y + state.height; - var cx = bounds.getCenterX() - state.x; - var cy = bounds.getCenterY() - state.y; - - var y = b - cx - bounds.height / 2; - bounds.x = state.x + cy - bounds.width / 2; - bounds.y = y; - //bounds.x -= state.height / 2 - state.width / 2; - //bounds.y -= state.width / 2 - state.height / 2; - } - } - - this.drawLabelBackground(state, canvas, bounds, vert); - this.drawLabel(state, canvas, bounds, vert, label); - canvas.restore(); - } -}; - -/** - * Function: drawGlass - * - * Draws the given state to the given canvas. - */ -mxImageExport.prototype.drawShadow = function(canvas, state, shape, rotation, flipH, flipV, bounds, alpha, filled) -{ - // Requires background in generic shape for shadow, looks like only one - // fillAndStroke is allowed per current path, try working around that - // Computes rotated shadow offset - var rad = rotation * Math.PI / 180; - var cos = Math.cos(-rad); - var sin = Math.sin(-rad); - var offset = mxUtils.getRotatedPoint(new mxPoint(mxConstants.SHADOW_OFFSET_X, mxConstants.SHADOW_OFFSET_Y), cos, sin); - - if (flipH) - { - offset.x *= -1; - } - - if (flipV) - { - offset.y *= -1; - } - - // TODO: Use save/restore instead of negative offset to restore (requires fix for HTML canvas) - canvas.translate(offset.x, offset.y); - - // Returns true if a shadow has been painted (path has been created) - if (shape.drawShape(canvas, state, bounds, true, true)) - { - canvas.setAlpha(mxConstants.SHADOW_OPACITY * alpha); - canvas.shadow(mxConstants.SHADOWCOLOR, filled); - } - - canvas.translate(-offset.x, -offset.y); -}; - -/** - * Function: drawGlass - * - * Draws the given state to the given canvas. - */ -mxImageExport.prototype.drawGlass = function(state, canvas, bounds, shape, size) -{ - // LATER: Clipping region should include stroke - if (shape.drawShape(canvas, state, bounds, true, false)) - { - canvas.save(); - canvas.clip(); - canvas.setGlassGradient(bounds.x, bounds.y, bounds.width, bounds.height); - - canvas.begin(); - canvas.moveTo(bounds.x, bounds.y); - canvas.lineTo(bounds.x, (bounds.y + bounds.height * size)); - canvas.quadTo((bounds.x + bounds.width * 0.5), - (bounds.y + bounds.height * 0.7), bounds.x + bounds.width, - (bounds.y + bounds.height * size)); - canvas.lineTo(bounds.x + bounds.width, bounds.y); - canvas.close(); - - canvas.fill(); - canvas.restore(); - } -}; - -/** - * Function: drawImage - * - * Draws the given state to the given canvas. - */ -mxImageExport.prototype.drawImage = function(state, canvas, bounds, image) -{ - var aspect = mxUtils.getValue(state.style, mxConstants.STYLE_IMAGE_ASPECT, 1) == 1; - var flipH = mxUtils.getValue(state.style, mxConstants.STYLE_IMAGE_FLIPH, 0) == 1; - var flipV = mxUtils.getValue(state.style, mxConstants.STYLE_IMAGE_FLIPV, 0) == 1; - - canvas.image(bounds.x, bounds.y, bounds.width, bounds.height, image, aspect, flipH, flipV); -}; - -/** - * Function: drawLabelBackground - * - * Draws background for the label of the given state to the given canvas. - */ -mxImageExport.prototype.drawLabelBackground = function(state, canvas, bounds, vert) -{ - var stroke = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_BORDERCOLOR); - var fill = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_BACKGROUNDCOLOR); - - if (stroke == mxConstants.NONE) - { - stroke = null; - } - - if (fill == mxConstants.NONE) - { - fill = null; - } - - if (stroke != null || fill != null) - { - var x = bounds.x; - var y = bounds.y - mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_PADDING, 0); - var w = bounds.width; - var h = bounds.height; - - if (vert) - { - x += (w - h) / 2; - y += (h - w) / 2; - var tmp = w; - w = h; - h = tmp; - } - - if (fill != null) - { - canvas.setFillColor(fill); - } - - if (stroke != null) - { - canvas.setStrokeColor(stroke); - canvas.setStrokeWidth(1); - canvas.setDashed(false); - } - - canvas.rect(x, y, w, h); - - if (fill != null && stroke != null) - { - canvas.fillAndStroke(); - } - else if (fill != null) - { - canvas.fill(); - } - else if (stroke != null) - { - canvas.stroke(); - } - } -}; - -/** - * Function: drawLabel - * - * Draws the given state to the given canvas. - */ -mxImageExport.prototype.drawLabel = function(state, canvas, bounds, vert, str) -{ - var scale = state.view.scale; - - // Applies color - canvas.setFontColor(mxUtils.getValue(state.style, mxConstants.STYLE_FONTCOLOR, '#000000')); - - // Applies font settings - canvas.setFontFamily(mxUtils.getValue(state.style, mxConstants.STYLE_FONTFAMILY, - mxConstants.DEFAULT_FONTFAMILY)); - canvas.setFontStyle(mxUtils.getValue(state.style, mxConstants.STYLE_FONTSTYLE, 0)); - canvas.setFontSize(mxUtils.getValue(state.style, mxConstants.STYLE_FONTSIZE, - mxConstants.DEFAULT_FONTSIZE) * scale); - - var align = mxUtils.getValue(state.style, mxConstants.STYLE_ALIGN, mxConstants.ALIGN_LEFT); - - // Uses null alignment for default values (valign default is 'top' which is fine) - if (align == 'left') - { - align = null; - } - - var y = bounds.y - mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_PADDING, 0); - var wrap = state.view.graph.isWrapping(state.cell); - var html = state.view.graph.isHtmlLabel(state.cell); - - // Replaces linefeeds in HTML markup to match the display output - if (html && mxText.prototype.replaceLinefeeds) - { - str = str.replace(/\n/g, '<br/>'); - } - - canvas.text(bounds.x, y, bounds.width, bounds.height, str, align, null, vert, wrap, (html) ? 'html' : ''); -}; - -/** - * Function: getBackgroundBounds - * - * Draws the given state to the given canvas. - */ -mxImageExport.prototype.getBackgroundBounds = function(state) -{ - if (state.style[mxConstants.STYLE_SHAPE] == mxConstants.SHAPE_SWIMLANE) - { - var scale = state.view.scale; - var start = mxUtils.getValue(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE) * scale; - var w = state.width; - var h = state.height; - - if (mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, true)) - { - h = start; - } - else - { - w = start; - } - - return new mxRectangle(state.x, state.y, Math.min(state.width, w), Math.min(state.height, h)); - } - else - { - return new mxRectangle(state.x, state.y, state.width, state.height); - } -}; - -/** - * Function: getImageBounds - * - * Draws the given state to the given canvas. - */ -mxImageExport.prototype.getImageBounds = function(state) -{ - var bounds = new mxRectangle(state.x, state.y, state.width, state.height); - var style = state.style; - - if (mxUtils.getValue(style, mxConstants.STYLE_SHAPE) != mxConstants.SHAPE_IMAGE) - { - var imgAlign = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_ALIGN, mxConstants.ALIGN_LEFT); - var imgValign = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE); - var imgWidth = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_WIDTH, mxConstants.DEFAULT_IMAGESIZE); - var imgHeight = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_HEIGHT, mxConstants.DEFAULT_IMAGESIZE); - var spacing = mxUtils.getValue(style, mxConstants.STYLE_SPACING, 2); - - if (imgAlign == mxConstants.ALIGN_CENTER) - { - bounds.x += (bounds.width - imgWidth) / 2; - } - else if (imgAlign == mxConstants.ALIGN_RIGHT) - { - bounds.x += bounds.width - imgWidth - spacing - 2; - } - else - // LEFT - { - bounds.x += spacing + 4; - } - - if (imgValign == mxConstants.ALIGN_TOP) - { - bounds.y += spacing; - } - else if (imgValign == mxConstants.ALIGN_BOTTOM) - { - bounds.y += bounds.height - imgHeight - spacing; - } - else - // MIDDLE - { - bounds.y += (bounds.height - imgHeight) / 2; - } - - bounds.width = imgWidth; - bounds.height = imgHeight; - } - - return bounds; -}; - -/** - * Function: drawMarker - * - * Initializes the built-in shapes. - */ -mxImageExport.prototype.drawMarker = function(canvas, state, source) -{ - var offset = null; - - // Computes the norm and the inverse norm - var pts = state.absolutePoints; - var n = pts.length; - - var p0 = (source) ? pts[1] : pts[n - 2]; - var pe = (source) ? pts[0] : pts[n - 1]; - - var dx = pe.x - p0.x; - var dy = pe.y - p0.y; - - var dist = Math.max(1, Math.sqrt(dx * dx + dy * dy)); - - var unitX = dx / dist; - var unitY = dy / dist; - - var size = mxUtils.getValue(state.style, (source) ? - mxConstants.STYLE_STARTSIZE : - mxConstants.STYLE_ENDSIZE, - mxConstants.DEFAULT_MARKERSIZE); - - // Allow for stroke width in the end point used and the - // orthogonal vectors describing the direction of the marker - // TODO: Should get strokewidth from canvas (same for strokecolor) - var sw = mxUtils.getValue(state.style, mxConstants.STYLE_STROKEWIDTH, 1); - - pe = pe.clone(); - - var type = mxUtils.getValue(state.style, (source) ? - mxConstants.STYLE_STARTARROW : - mxConstants.STYLE_ENDARROW); - var f = this.markers[type]; - - if (f != null) - { - offset = f(canvas, state, type, pe, unitX, unitY, size, source, sw); - } - - return offset; -}; - -/** - * Function: initShapes - * - * Initializes the built-in shapes. - */ -mxImageExport.prototype.initShapes = function() -{ - this.shapes = []; - - // Implements the rectangle and rounded rectangle shape - this.shapes['rectangle'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - // Paints the shape - if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) - { - var f = mxUtils.getValue(state.style, mxConstants.STYLE_ARCSIZE, mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100; - var r = Math.min(bounds.width * f, bounds.height * f); - canvas.roundrect(bounds.x, bounds.y, bounds.width, bounds.height, r, r); - } - else - { - canvas.rect(bounds.x, bounds.y, bounds.width, bounds.height); - } - - return true; - } - else - { - canvas.fillAndStroke(); - } - } - }; - - // Implements the swimlane shape - this.shapes['swimlane'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) - { - var r = Math.min(bounds.width * mxConstants.RECTANGLE_ROUNDING_FACTOR, - bounds.height * mxConstants.RECTANGLE_ROUNDING_FACTOR); - canvas.roundrect(bounds.x, bounds.y, bounds.width, bounds.height, r, r); - } - else - { - canvas.rect(bounds.x, bounds.y, bounds.width, bounds.height); - } - - return true; - } - else - { - canvas.fillAndStroke(); - canvas.begin(); - - var x = state.x; - var y = state.y; - var w = state.width; - var h = state.height; - - if (mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, 1) == 0) - { - x += bounds.width; - w -= bounds.width; - - canvas.moveTo(x, y); - canvas.lineTo(x + w, y); - canvas.lineTo(x + w, y + h); - canvas.lineTo(x, y + h); - } - else - { - y += bounds.height; - h -= bounds.height; - - canvas.moveTo(x, y); - canvas.lineTo(x, y + h); - canvas.lineTo(x + w, y + h); - canvas.lineTo(x + w, y); - } - - canvas.stroke(); - } - } - }; - - this.shapes['image'] = this.shapes['rectangle']; - this.shapes['label'] = this.shapes['rectangle']; - - var imageExport = this; - - this.shapes['connector'] = - { - translatePoint: function(points, index, offset) - { - if (offset != null) - { - var pt = points[index].clone(); - pt.x += offset.x; - pt.y += offset.y; - points[index] = pt; - } - }, - - drawShape: function(canvas, state, bounds, background, shadow) - { - if (background) - { - var rounded = mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false); - var arcSize = mxConstants.LINE_ARCSIZE / 2; - - // Does not draw the markers in the shadow to match the display - canvas.setFillColor((shadow) ? mxConstants.NONE : mxUtils.getValue(state.style, mxConstants.STYLE_STROKECOLOR, "#000000")); - canvas.setDashed(false); - var pts = state.absolutePoints.slice(); - this.translatePoint(pts, 0, imageExport.drawMarker(canvas, state, true)); - this.translatePoint(pts, pts.length - 1, imageExport.drawMarker(canvas, state, false)); - canvas.setDashed(mxUtils.getValue(state.style, mxConstants.STYLE_DASHED, '0') == '1'); - - var pt = pts[0]; - var pe = pts[pts.length - 1]; - canvas.begin(); - canvas.moveTo(pt.x, pt.y); - - // Draws the line segments - for (var i = 1; i < pts.length - 1; i++) - { - var tmp = pts[i]; - var dx = pt.x - tmp.x; - var dy = pt.y - tmp.y; - - if ((rounded && i < pts.length - 1) && (dx != 0 || dy != 0)) - { - // Draws a line from the last point to the current - // point with a spacing of size off the current point - // into direction of the last point - var dist = Math.sqrt(dx * dx + dy * dy); - var nx1 = dx * Math.min(arcSize, dist / 2) / dist; - var ny1 = dy * Math.min(arcSize, dist / 2) / dist; - - var x1 = tmp.x + nx1; - var y1 = tmp.y + ny1; - canvas.lineTo(x1, y1); - - // Draws a curve from the last point to the current - // point with a spacing of size off the current point - // into direction of the next point - var next = pts[i + 1]; - dx = next.x - tmp.x; - dy = next.y - tmp.y; - - dist = Math.max(1, Math.sqrt(dx * dx + dy * dy)); - var nx2 = dx * Math.min(arcSize, dist / 2) / dist; - var ny2 = dy * Math.min(arcSize, dist / 2) / dist; - - var x2 = tmp.x + nx2; - var y2 = tmp.y + ny2; - - canvas.curveTo(tmp.x, tmp.y, tmp.x, tmp.y, x2, y2); - tmp = new mxPoint(x2, y2); - } - else - { - canvas.lineTo(tmp.x, tmp.y); - } - - pt = tmp; - } - - canvas.lineTo(pe.x, pe.y); - canvas.stroke(); - - return true; - } - else - { - // no foreground - } - } - }; - - this.shapes['arrow'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - // Geometry of arrow - var spacing = mxConstants.ARROW_SPACING; - var width = mxConstants.ARROW_WIDTH; - var arrow = mxConstants.ARROW_SIZE; - - // Base vector (between end points) - var pts = state.absolutePoints; - var p0 = pts[0]; - var pe = pts[pts.length - 1]; - var dx = pe.x - p0.x; - var dy = pe.y - p0.y; - var dist = Math.sqrt(dx * dx + dy * dy); - var length = dist - 2 * spacing - arrow; - - // Computes the norm and the inverse norm - var nx = dx / dist; - var ny = dy / dist; - var basex = length * nx; - var basey = length * ny; - var floorx = width * ny/3; - var floory = -width * nx/3; - - // Computes points - var p0x = p0.x - floorx / 2 + spacing * nx; - var p0y = p0.y - floory / 2 + spacing * ny; - var p1x = p0x + floorx; - var p1y = p0y + floory; - var p2x = p1x + basex; - var p2y = p1y + basey; - var p3x = p2x + floorx; - var p3y = p2y + floory; - // p4 not necessary - var p5x = p3x - 3 * floorx; - var p5y = p3y - 3 * floory; - - canvas.begin(); - canvas.moveTo(p0x, p0y); - canvas.lineTo(p1x, p1y); - canvas.lineTo(p2x, p2y); - canvas.lineTo(p3x, p3y); - canvas.lineTo(pe.x - spacing * nx, pe.y - spacing * ny); - canvas.lineTo(p5x, p5y); - canvas.lineTo(p5x + floorx, p5y + floory); - canvas.close(); - - return true; - } - else - { - canvas.fillAndStroke(); - } - } - }; - - this.shapes['cylinder'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - return false; - } - else - { - var x = bounds.x; - var y = bounds.y; - var w = bounds.width; - var h = bounds.height; - var dy = Math.min(mxCylinder.prototype.maxHeight, Math.floor(h / 5)); - - canvas.begin(); - canvas.moveTo(x, y + dy); - canvas.curveTo(x, y - dy / 3, x + w, y - dy / 3, x + w, y + dy); - canvas.lineTo(x + w, y + h - dy); - canvas.curveTo(x + w, y + h + dy / 3, x, y + h + dy / 3, x, y + h - dy); - canvas.close(); - canvas.fillAndStroke(); - - canvas.begin(); - canvas.moveTo(x, y + dy); - canvas.curveTo(x, y + 2 * dy, x + w, y + 2 * dy, x + w, y + dy); - canvas.stroke(); - } - } - }; - - this.shapes['line'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - return false; - } - else - { - canvas.begin(); - - var mid = state.getCenterY(); - canvas.moveTo(bounds.x, mid); - canvas.lineTo(bounds.x + bounds.width, mid); - - canvas.stroke(); - } - } - }; - - this.shapes['ellipse'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - canvas.ellipse(bounds.x, bounds.y, bounds.width, bounds.height); - - return true; - } - else - { - canvas.fillAndStroke(); - } - } - }; - - this.shapes['doubleEllipse'] = - { - drawShape: function(canvas, state, bounds, background) - { - var x = bounds.x; - var y = bounds.y; - var w = bounds.width; - var h = bounds.height; - - if (background) - { - canvas.ellipse(x, y, w, h); - - return true; - } - else - { - canvas.fillAndStroke(); - - var inset = Math.min(4, Math.min(w / 5, h / 5)); - x += inset; - y += inset; - w -= 2 * inset; - h -= 2 * inset; - - if (w > 0 && h > 0) - { - canvas.ellipse(x, y, w, h); - } - - canvas.stroke(); - } - } - }; - - this.shapes['triangle'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - var x = bounds.x; - var y = bounds.y; - var w = bounds.width; - var h = bounds.height; - canvas.begin(); - canvas.moveTo(x, y); - canvas.lineTo(x + w, y + h / 2); - canvas.lineTo(x, y + h); - canvas.close(); - - return true; - } - else - { - canvas.fillAndStroke(); - } - } - }; - - this.shapes['rhombus'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - var x = bounds.x; - var y = bounds.y; - var w = bounds.width; - var h = bounds.height; - var hw = w / 2; - var hh = h / 2; - - canvas.begin(); - canvas.moveTo(x + hw, y); - canvas.lineTo(x + w, y + hh); - canvas.lineTo(x + hw, y + h); - canvas.lineTo(x, y + hh); - canvas.close(); - - return true; - } - else - { - canvas.fillAndStroke(); - } - } - - }; - - this.shapes['hexagon'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - var x = bounds.x; - var y = bounds.y; - var w = bounds.width; - var h = bounds.height; - - canvas.begin(); - canvas.moveTo(x + 0.25 * w, y); - canvas.lineTo(x + 0.75 * w, y); - canvas.lineTo(x + w, y + 0.5 * h); - canvas.lineTo(x + 0.75 * w, y + h); - canvas.lineTo(x + 0.25 * w, y + h); - canvas.lineTo(x, y + 0.5 * h); - canvas.close(); - - return true; - } - else - { - canvas.fillAndStroke(); - } - } - }; - - this.shapes['actor'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - var x = bounds.x; - var y = bounds.y; - var w = bounds.width; - var h = bounds.height; - var width = w * 2 / 6; - - canvas.begin(); - canvas.moveTo(x, y + h); - canvas.curveTo(x, y + 3 * h / 5, x, y + 2 * h / 5, x + w / 2, y + 2 * h - / 5); - canvas.curveTo(x + w / 2 - width, y + 2 * h / 5, x + w / 2 - width, y, x - + w / 2, y); - canvas.curveTo(x + w / 2 + width, y, x + w / 2 + width, y + 2 * h / 5, x - + w / 2, y + 2 * h / 5); - canvas.curveTo(x + w, y + 2 * h / 5, x + w, y + 3 * h / 5, x + w, y + h); - canvas.close(); - - return true; - } - else - { - canvas.fillAndStroke(); - } - } - }; - - this.shapes['cloud'] = - { - drawShape: function(canvas, state, bounds, background) - { - if (background) - { - var x = bounds.x; - var y = bounds.y; - var w = bounds.width; - var h = bounds.height; - - canvas.begin(); - canvas.moveTo(x + 0.25 * w, y + 0.25 * h); - canvas.curveTo(x + 0.05 * w, y + 0.25 * h, x, - y + 0.5 * h, x + 0.16 * w, y + 0.55 * h); - canvas.curveTo(x, y + 0.66 * h, x + 0.18 * w, - y + 0.9 * h, x + 0.31 * w, y + 0.8 * h); - canvas.curveTo(x + 0.4 * w, y + h, x + 0.7 * w, - y + h, x + 0.8 * w, y + 0.8 * h); - canvas.curveTo(x + w, y + 0.8 * h, x + w, - y + 0.6 * h, x + 0.875 * w, y + 0.5 * h); - canvas.curveTo(x + w, y + 0.3 * h, x + 0.8 * w, - y + 0.1 * h, x + 0.625 * w, y + 0.2 * h); - canvas.curveTo(x + 0.5 * w, y + 0.05 * h, - x + 0.3 * w, y + 0.05 * h, - x + 0.25 * w, y + 0.25 * h); - canvas.close(); - - return true; - } - else - { - canvas.fillAndStroke(); - } - } - }; - -}; - -/** - * Function: initMarkers - * - * Initializes the built-in markers. - */ -mxImageExport.prototype.initMarkers = function() -{ - this.markers = []; - - var tmp = function(canvas, state, type, pe, unitX, unitY, size, source, sw) - { - // The angle of the forward facing arrow sides against the x axis is - // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for - // only half the strokewidth is processed ). - var endOffsetX = unitX * sw * 1.118; - var endOffsetY = unitY * sw * 1.118; - - pe.x -= endOffsetX; - pe.y -= endOffsetY; - - unitX = unitX * (size + sw); - unitY = unitY * (size + sw); - - canvas.begin(); - canvas.moveTo(pe.x, pe.y); - canvas.lineTo(pe.x - unitX - unitY / 2, pe.y - unitY + unitX / 2); - - if (type == mxConstants.ARROW_CLASSIC) - { - canvas.lineTo(pe.x - unitX * 3 / 4, pe.y - unitY * 3 / 4); - } - - canvas.lineTo(pe.x + unitY / 2 - unitX, pe.y - unitY - unitX / 2); - canvas.close(); - - var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL; - - if (state.style[key] == 0) - { - canvas.stroke(); - } - else - { - canvas.fillAndStroke(); - } - - var f = (type != mxConstants.ARROW_CLASSIC) ? 1 : 3 / 4; - return new mxPoint(-unitX * f - endOffsetX, -unitY * f - endOffsetY); - }; - - this.markers['classic'] = tmp; - this.markers['block'] = tmp; - - this.markers['open'] = function(canvas, state, type, pe, unitX, unitY, size, source, sw) - { - // The angle of the forward facing arrow sides against the x axis is - // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for - // only half the strokewidth is processed ). - var endOffsetX = unitX * sw * 1.118; - var endOffsetY = unitY * sw * 1.118; - - pe.x -= endOffsetX; - pe.y -= endOffsetY; - - unitX = unitX * (size + sw); - unitY = unitY * (size + sw); - - canvas.begin(); - canvas.moveTo(pe.x - unitX - unitY / 2, pe.y - unitY + unitX / 2); - canvas.lineTo(pe.x, pe.y); - canvas.lineTo(pe.x + unitY / 2 - unitX, pe.y - unitY - unitX / 2); - canvas.stroke(); - - return new mxPoint(-endOffsetX * 2, -endOffsetY * 2); - }; - - this.markers['oval'] = function(canvas, state, type, pe, unitX, unitY, size, source, sw) - { - var a = size / 2; - - canvas.ellipse(pe.x - a, pe.y - a, size, size); - - var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL; - - if (state.style[key] == 0) - { - canvas.stroke(); - } - else - { - canvas.fillAndStroke(); - } - - return new mxPoint(-unitX / 2, -unitY / 2); - }; - - var tmp_diamond = function(canvas, state, type, pe, unitX, unitY, size, source, sw) - { - // The angle of the forward facing arrow sides against the x axis is - // 45 degrees, 1/sin(45) = 1.4142 / 2 = 0.7071 ( / 2 allows for - // only half the strokewidth is processed ). Or 0.9862 for thin diamond. - // Note these values and the tk variable below are dependent, update - // both together (saves trig hard coding it). - var swFactor = (type == mxConstants.ARROW_DIAMOND) ? 0.7071 : 0.9862; - var endOffsetX = unitX * sw * swFactor; - var endOffsetY = unitY * sw * swFactor; - - unitX = unitX * (size + sw); - unitY = unitY * (size + sw); - - pe.x -= endOffsetX; - pe.y -= endOffsetY; - - // thickness factor for diamond - var tk = ((type == mxConstants.ARROW_DIAMOND) ? 2 : 3.4); - - canvas.begin(); - canvas.moveTo(pe.x, pe.y); - canvas.lineTo(pe.x - unitX / 2 - unitY / tk, pe.y + unitX / tk - unitY / 2); - canvas.lineTo(pe.x - unitX, pe.y - unitY); - canvas.lineTo(pe.x - unitX / 2 + unitY / tk, pe.y - unitY / 2 - unitX / tk); - canvas.close(); - - var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL; - - if (state.style[key] == 0) - { - canvas.stroke(); - } - else - { - canvas.fillAndStroke(); - } - - return new mxPoint(-endOffsetX - unitX, -endOffsetY - unitY); - }; - - this.markers['diamond'] = tmp_diamond; - this.markers['diamondThin'] = tmp_diamond; -}; |