| /** |
| * Copyright (c) 2006-2015, JGraph Ltd |
| * Copyright (c) 2006-2015, Gaudenz Alder |
| */ |
| /** |
| * Class: mxStencil |
| * |
| * Implements a generic shape which is based on a XML node as a description. |
| * |
| * shape: |
| * |
| * The outer element is *shape*, that has attributes: |
| * |
| * - "name", string, required. The stencil name that uniquely identifies the shape. |
| * - "w" and "h" are optional decimal view bounds. This defines your co-ordinate |
| * system for the graphics operations in the shape. The default is 100,100. |
| * - "aspect", optional string. Either "variable", the default, or "fixed". Fixed |
| * means always render the shape with the aspect ratio defined by the ratio w/h. |
| * Variable causes the ratio to match that of the geometry of the current vertex. |
| * - "strokewidth", optional string. Either an integer or the string "inherit". |
| * "inherit" indicates that the strokeWidth of the cell is only changed on scaling, |
| * not on resizing. Default is "1". |
| * If numeric values are used, the strokeWidth of the cell is changed on both |
| * scaling and resizing and the value defines the multiple that is applied to |
| * the width. |
| * |
| * connections: |
| * |
| * If you want to define specific fixed connection points on the shape use the |
| * *connections* element. Each *constraint* element within connections defines |
| * a fixed connection point on the shape. Constraints have attributes: |
| * |
| * - "perimeter", required. 1 or 0. 0 sets the connection point where specified |
| * by x,y. 1 Causes the position of the connection point to be extrapolated from |
| * the center of the shape, through x,y to the point of intersection with the |
| * perimeter of the shape. |
| * - "x" and "y" are the position of the fixed point relative to the bounds of |
| * the shape. They can be automatically adjusted if perimeter=1. So, (0,0) is top |
| * left, (0.5,0.5) the center, (1,0.5) the center of the right hand edge of the |
| * bounds, etc. Values may be less than 0 or greater than 1 to be positioned |
| * outside of the shape. |
| * - "name", optional string. A unique identifier for the port on the shape. |
| * |
| * background and foreground: |
| * |
| * The path of the graphics drawing is split into two elements, *foreground* and |
| * *background*. The split is to define which part any shadow applied to the shape |
| * is derived from (the background). This, generally, means the background is the |
| * line tracing of the outside of the shape, but not always. |
| * |
| * Any stroke, fill or fillstroke of a background must be the first element of the |
| * foreground element, they must not be used within *background*. If the background |
| * is empty, this is not required. |
| * |
| * Because the background cannot have any fill or stroke, it can contain only one |
| * *path*, *rect*, *roundrect* or *ellipse* element (or none). It can also not |
| * include *image*, *text* or *include-shape*. |
| * |
| * Note that the state, styling and drawing in mxGraph stencils is very close in |
| * design to that of HTML 5 canvas. Tutorials on this subject, if you're not |
| * familiar with the topic, will give a good high-level introduction to the |
| * concepts used. |
| * |
| * State: |
| * |
| * Rendering within the foreground and background elements has the concept of |
| * state. There are two types of operations other than state save/load, styling |
| * and drawing. The styling operations change the current state, so you can save |
| * the current state with <save/> and pull the last saved state from the state |
| * stack using <restore/>. |
| * |
| * Styling: |
| * |
| * The elements that change colors within the current state all take a hash |
| * prefixed hex color code ("#FFEA80"). |
| * |
| * - *strokecolor*, this sets the color that drawing paths will be rendered in |
| * when a stroke or fillstroke command is issued. |
| * - *fillcolor*, this sets the color that the inside of closed paths will be |
| * rendered in when a fill or fillstroke command is issued. |
| * - *fontcolor*, this sets the color that fonts are rendered in when text is drawn. |
| * |
| * *alpha* defines the degree of transparency used between 1.0 for fully opaque |
| * and 0.0 for fully transparent. |
| * |
| * *strokewidth* defines the integer thickness of drawing elements rendered by |
| * stroking. Use fixed="1" to apply the value as-is, without scaling. |
| * |
| * *dashed* is "1" for dashing enabled and "0" for disabled. |
| * |
| * When *dashed* is enabled the current dash pattern, defined by *dashpattern*, |
| * is used on strokes. dashpattern is a sequence of space separated "on, off" |
| * lengths that define what distance to paint the stroke for, then what distance |
| * to paint nothing for, repeat... The default is "3 3". You could define a more |
| * complex pattern with "5 3 2 6", for example. Generally, it makes sense to have |
| * an even number of elements in the dashpattern, but that's not required. |
| * |
| * *linejoin*, *linecap* and *miterlimit* are best explained by the Mozilla page |
| * on Canvas styling (about halfway down). The values are all the same except we |
| * use "flat" for linecap, instead of Canvas' "butt". |
| * |
| * For font styling there are. |
| * |
| * - *fontsize*, an integer, |
| * - *fontstyle*, an ORed bit pattern of bold (1), italic (2) and underline (4), |
| * i.e bold underline is "5". |
| * - *fontfamily*, is a string defining the typeface to be used. |
| * |
| * Drawing: |
| * |
| * Most drawing is contained within a *path* element. Again, the graphic |
| * primitives are very similar to that of HTML 5 canvas. |
| * |
| * - *move* to attributes required decimals (x,y). |
| * - *line* to attributes required decimals (x,y). |
| * - *quad* to required decimals (x2,y2) via control point required decimals |
| * (x1,y1). |
| * - *curve* to required decimals (x3,y3), via control points required decimals |
| * (x1,y1) and (x2,y2). |
| * - *arc*, this doesn't follow the HTML Canvas signatures, instead it's a copy |
| * of the SVG arc command. The SVG specification documentation gives the best |
| * description of its behaviors. The attributes are named identically, they are |
| * decimals and all required. |
| * - *close* ends the current subpath and causes an automatic straight line to |
| * be drawn from the current point to the initial point of the current subpath. |
| * |
| * Complex drawing: |
| * |
| * In addition to the graphics primitive operations there are non-primitive |
| * operations. These provide an easy method to draw some basic shapes. |
| * |
| * - *rect*, attributes "x", "y", "w", "h", all required decimals |
| * - *roundrect*, attributes "x", "y", "w", "h", all required decimals. Also |
| * "arcsize" an optional decimal attribute defining how large, the corner curves |
| * are. |
| * - *ellipse*, attributes "x", "y", "w", "h", all required decimals. |
| * |
| * Note that these 3 shapes and all paths must be followed by either a fill, |
| * stroke, or fillstroke. |
| * |
| * Text: |
| * |
| * *text* elements have the following attributes. |
| * |
| * - "str", the text string to display, required. |
| * - "x" and "y", the decimal location (x,y) of the text element, required. |
| * - "align", the horizontal alignment of the text element, either "left", |
| * "center" or "right". Optional, default is "left". |
| * - "valign", the vertical alignment of the text element, either "top", "middle" |
| * or "bottom". Optional, default is "top". |
| * - "localized", 0 or 1, if 1 then the "str" actually contains a key to use to |
| * fetch the value out of mxResources. Optional, default is |
| * <mxStencil.defaultLocalized>. |
| * - "vertical", 0 or 1, if 1 the label is rendered vertically (rotated by 90 |
| * degrees). Optional, default is 0. |
| * - "rotation", angle in degrees (0 to 360). The angle to rotate the text by. |
| * Optional, default is 0. |
| * - "align-shape", 0 or 1, if 0 ignore the rotation of the shape when setting |
| * the text rotation. Optional, default is 1. |
| * |
| * If <allowEval> is true, then the text content of the this element can define |
| * a function which is invoked with the shape as the only argument and returns |
| * the value for the text element (ignored if the str attribute is not null). |
| * |
| * Images: |
| * |
| * *image* elements can either be external URLs, or data URIs, where supported |
| * (not in IE 7-). Attributes are: |
| * |
| * - "src", required string. Either a data URI or URL. |
| * - "x", "y", required decimals. The (x,y) position of the image. |
| * - "w", "h", required decimals. The width and height of the image. |
| * - "flipH" and "flipV", optional 0 or 1. Whether to flip the image along the |
| * horizontal/vertical axis. Default is 0 for both. |
| * |
| * If <allowEval> is true, then the text content of the this element can define |
| * a function which is invoked with the shape as the only argument and returns |
| * the value for the image source (ignored if the src attribute is not null). |
| * |
| * Sub-shapes: |
| * |
| * *include-shape* allow stencils to be rendered within the current stencil by |
| * referencing the sub-stencil by name. Attributes are: |
| * |
| * - "name", required string. The unique shape name of the stencil. |
| * - "x", "y", "w", "h", required decimals. The (x,y) position of the sub-shape |
| * and its width and height. |
| * |
| * Constructor: mxStencil |
| * |
| * Constructs a new generic shape by setting <desc> to the given XML node and |
| * invoking <parseDescription> and <parseConstraints>. |
| * |
| * Parameters: |
| * |
| * desc - XML node that contains the stencil description. |
| */ |
| function mxStencil(desc) |
| { |
| this.desc = desc; |
| this.parseDescription(); |
| this.parseConstraints(); |
| }; |
| |
| /** |
| * Variable: defaultLocalized |
| * |
| * Static global variable that specifies the default value for the localized |
| * attribute of the text element. Default is false. |
| */ |
| mxStencil.defaultLocalized = false; |
| |
| /** |
| * Function: allowEval |
| * |
| * Static global switch that specifies if the use of eval is allowed for |
| * evaluating text content and images. Default is false. Set this to true |
| * if stencils can not contain user input. |
| */ |
| mxStencil.allowEval = false; |
| |
| /** |
| * Variable: desc |
| * |
| * Holds the XML node with the stencil description. |
| */ |
| mxStencil.prototype.desc = null; |
| |
| /** |
| * Variable: constraints |
| * |
| * Holds an array of <mxConnectionConstraints> as defined in the shape. |
| */ |
| mxStencil.prototype.constraints = null; |
| |
| /** |
| * Variable: aspect |
| * |
| * Holds the aspect of the shape. Default is 'auto'. |
| */ |
| mxStencil.prototype.aspect = null; |
| |
| /** |
| * Variable: w0 |
| * |
| * Holds the width of the shape. Default is 100. |
| */ |
| mxStencil.prototype.w0 = null; |
| |
| /** |
| * Variable: h0 |
| * |
| * Holds the height of the shape. Default is 100. |
| */ |
| mxStencil.prototype.h0 = null; |
| |
| /** |
| * Variable: bgNodes |
| * |
| * Holds the XML node with the stencil description. |
| */ |
| mxStencil.prototype.bgNode = null; |
| |
| /** |
| * Variable: fgNodes |
| * |
| * Holds the XML node with the stencil description. |
| */ |
| mxStencil.prototype.fgNode = null; |
| |
| /** |
| * Variable: strokewidth |
| * |
| * Holds the strokewidth direction from the description. |
| */ |
| mxStencil.prototype.strokewidth = null; |
| |
| /** |
| * Function: parseDescription |
| * |
| * Reads <w0>, <h0>, <aspect>, <bgNodes> and <fgNodes> from <desc>. |
| */ |
| mxStencil.prototype.parseDescription = function() |
| { |
| // LATER: Preprocess nodes for faster painting |
| this.fgNode = this.desc.getElementsByTagName('foreground')[0]; |
| this.bgNode = this.desc.getElementsByTagName('background')[0]; |
| this.w0 = Number(this.desc.getAttribute('w') || 100); |
| this.h0 = Number(this.desc.getAttribute('h') || 100); |
| |
| // Possible values for aspect are: variable and fixed where |
| // variable means fill the available space and fixed means |
| // use w0 and h0 to compute the aspect. |
| var aspect = this.desc.getAttribute('aspect'); |
| this.aspect = (aspect != null) ? aspect : 'variable'; |
| |
| // Possible values for strokewidth are all numbers and "inherit" |
| // where the inherit means take the value from the style (ie. the |
| // user-defined stroke-width). Note that the strokewidth is scaled |
| // by the minimum scaling that is used to draw the shape (sx, sy). |
| var sw = this.desc.getAttribute('strokewidth'); |
| this.strokewidth = (sw != null) ? sw : '1'; |
| }; |
| |
| /** |
| * Function: parseConstraints |
| * |
| * Reads the constraints from <desc> into <constraints> using |
| * <parseConstraint>. |
| */ |
| mxStencil.prototype.parseConstraints = function() |
| { |
| var conns = this.desc.getElementsByTagName('connections')[0]; |
| |
| if (conns != null) |
| { |
| var tmp = mxUtils.getChildNodes(conns); |
| |
| if (tmp != null && tmp.length > 0) |
| { |
| this.constraints = []; |
| |
| for (var i = 0; i < tmp.length; i++) |
| { |
| this.constraints.push(this.parseConstraint(tmp[i])); |
| } |
| } |
| } |
| }; |
| |
| /** |
| * Function: parseConstraint |
| * |
| * Parses the given XML node and returns its <mxConnectionConstraint>. |
| */ |
| mxStencil.prototype.parseConstraint = function(node) |
| { |
| var x = Number(node.getAttribute('x')); |
| var y = Number(node.getAttribute('y')); |
| var perimeter = node.getAttribute('perimeter') == '1'; |
| var name = node.getAttribute('name'); |
| |
| return new mxConnectionConstraint(new mxPoint(x, y), perimeter, name); |
| }; |
| |
| /** |
| * Function: evaluateTextAttribute |
| * |
| * Gets the given attribute as a text. The return value from <evaluateAttribute> |
| * is used as a key to <mxResources.get> if the localized attribute in the text |
| * node is 1 or if <defaultLocalized> is true. |
| */ |
| mxStencil.prototype.evaluateTextAttribute = function(node, attribute, shape) |
| { |
| var result = this.evaluateAttribute(node, attribute, shape); |
| var loc = node.getAttribute('localized'); |
| |
| if ((mxStencil.defaultLocalized && loc == null) || loc == '1') |
| { |
| result = mxResources.get(result); |
| } |
| |
| return result; |
| }; |
| |
| /** |
| * Function: evaluateAttribute |
| * |
| * Gets the attribute for the given name from the given node. If the attribute |
| * does not exist then the text content of the node is evaluated and if it is |
| * a function it is invoked with <shape> as the only argument and the return |
| * value is used as the attribute value to be returned. |
| */ |
| mxStencil.prototype.evaluateAttribute = function(node, attribute, shape) |
| { |
| var result = node.getAttribute(attribute); |
| |
| if (result == null) |
| { |
| var text = mxUtils.getTextContent(node); |
| |
| if (text != null && mxStencil.allowEval) |
| { |
| var funct = mxUtils.eval(text); |
| |
| if (typeof(funct) == 'function') |
| { |
| result = funct(shape); |
| } |
| } |
| } |
| |
| return result; |
| }; |
| |
| /** |
| * Function: drawShape |
| * |
| * Draws this stencil inside the given bounds. |
| */ |
| mxStencil.prototype.drawShape = function(canvas, shape, x, y, w, h) |
| { |
| // TODO: Internal structure (array of special structs?), relative and absolute |
| // coordinates (eg. note shape, process vs star, actor etc.), text rendering |
| // and non-proportional scaling, how to implement pluggable edge shapes |
| // (start, segment, end blocks), pluggable markers, how to implement |
| // swimlanes (title area) with this API, add icon, horizontal/vertical |
| // label, indicator for all shapes, rotation |
| var direction = mxUtils.getValue(shape.style, mxConstants.STYLE_DIRECTION, null); |
| var aspect = this.computeAspect(shape.style, x, y, w, h, direction); |
| var minScale = Math.min(aspect.width, aspect.height); |
| var sw = (this.strokewidth == 'inherit') ? |
| Number(mxUtils.getNumber(shape.style, mxConstants.STYLE_STROKEWIDTH, 1)) : |
| Number(this.strokewidth) * minScale; |
| canvas.setStrokeWidth(sw); |
| |
| this.drawChildren(canvas, shape, x, y, w, h, this.bgNode, aspect, false); |
| this.drawChildren(canvas, shape, x, y, w, h, this.fgNode, aspect, true); |
| }; |
| |
| /** |
| * Function: drawChildren |
| * |
| * Draws this stencil inside the given bounds. |
| */ |
| mxStencil.prototype.drawChildren = function(canvas, shape, x, y, w, h, node, aspect, disableShadow) |
| { |
| if (node != null && w > 0 && h > 0) |
| { |
| var tmp = node.firstChild; |
| |
| while (tmp != null) |
| { |
| if (tmp.nodeType == mxConstants.NODETYPE_ELEMENT) |
| { |
| this.drawNode(canvas, shape, tmp, aspect, disableShadow); |
| } |
| |
| tmp = tmp.nextSibling; |
| } |
| } |
| }; |
| |
| /** |
| * Function: computeAspect |
| * |
| * Returns a rectangle that contains the offset in x and y and the horizontal |
| * and vertical scale in width and height used to draw this shape inside the |
| * given <mxRectangle>. |
| * |
| * Parameters: |
| * |
| * shape - <mxShape> to be drawn. |
| * bounds - <mxRectangle> that should contain the stencil. |
| * direction - Optional direction of the shape to be darwn. |
| */ |
| mxStencil.prototype.computeAspect = function(shape, x, y, w, h, direction) |
| { |
| var x0 = x; |
| var y0 = y; |
| var sx = w / this.w0; |
| var sy = h / this.h0; |
| |
| var inverse = (direction == mxConstants.DIRECTION_NORTH || direction == mxConstants.DIRECTION_SOUTH); |
| |
| if (inverse) |
| { |
| sy = w / this.h0; |
| sx = h / this.w0; |
| |
| var delta = (w - h) / 2; |
| |
| x0 += delta; |
| y0 -= delta; |
| } |
| |
| if (this.aspect == 'fixed') |
| { |
| sy = Math.min(sx, sy); |
| sx = sy; |
| |
| // Centers the shape inside the available space |
| if (inverse) |
| { |
| x0 += (h - this.w0 * sx) / 2; |
| y0 += (w - this.h0 * sy) / 2; |
| } |
| else |
| { |
| x0 += (w - this.w0 * sx) / 2; |
| y0 += (h - this.h0 * sy) / 2; |
| } |
| } |
| |
| return new mxRectangle(x0, y0, sx, sy); |
| }; |
| |
| /** |
| * Function: drawNode |
| * |
| * Draws this stencil inside the given bounds. |
| */ |
| mxStencil.prototype.drawNode = function(canvas, shape, node, aspect, disableShadow) |
| { |
| var name = node.nodeName; |
| var x0 = aspect.x; |
| var y0 = aspect.y; |
| var sx = aspect.width; |
| var sy = aspect.height; |
| var minScale = Math.min(sx, sy); |
| |
| if (name == 'save') |
| { |
| canvas.save(); |
| } |
| else if (name == 'restore') |
| { |
| canvas.restore(); |
| } |
| else if (name == 'path') |
| { |
| canvas.begin(); |
| |
| // Renders the elements inside the given path |
| var childNode = node.firstChild; |
| |
| while (childNode != null) |
| { |
| if (childNode.nodeType == mxConstants.NODETYPE_ELEMENT) |
| { |
| this.drawNode(canvas, shape, childNode, aspect, disableShadow); |
| } |
| |
| childNode = childNode.nextSibling; |
| } |
| } |
| else if (name == 'close') |
| { |
| canvas.close(); |
| } |
| else if (name == 'move') |
| { |
| canvas.moveTo(x0 + Number(node.getAttribute('x')) * sx, y0 + Number(node.getAttribute('y')) * sy); |
| } |
| else if (name == 'line') |
| { |
| canvas.lineTo(x0 + Number(node.getAttribute('x')) * sx, y0 + Number(node.getAttribute('y')) * sy); |
| } |
| else if (name == 'quad') |
| { |
| canvas.quadTo(x0 + Number(node.getAttribute('x1')) * sx, |
| y0 + Number(node.getAttribute('y1')) * sy, |
| x0 + Number(node.getAttribute('x2')) * sx, |
| y0 + Number(node.getAttribute('y2')) * sy); |
| } |
| else if (name == 'curve') |
| { |
| canvas.curveTo(x0 + Number(node.getAttribute('x1')) * sx, |
| y0 + Number(node.getAttribute('y1')) * sy, |
| x0 + Number(node.getAttribute('x2')) * sx, |
| y0 + Number(node.getAttribute('y2')) * sy, |
| x0 + Number(node.getAttribute('x3')) * sx, |
| y0 + Number(node.getAttribute('y3')) * sy); |
| } |
| else if (name == 'arc') |
| { |
| canvas.arcTo(Number(node.getAttribute('rx')) * sx, |
| Number(node.getAttribute('ry')) * sy, |
| Number(node.getAttribute('x-axis-rotation')), |
| Number(node.getAttribute('large-arc-flag')), |
| Number(node.getAttribute('sweep-flag')), |
| x0 + Number(node.getAttribute('x')) * sx, |
| y0 + Number(node.getAttribute('y')) * sy); |
| } |
| else if (name == 'rect') |
| { |
| canvas.rect(x0 + Number(node.getAttribute('x')) * sx, |
| y0 + Number(node.getAttribute('y')) * sy, |
| Number(node.getAttribute('w')) * sx, |
| Number(node.getAttribute('h')) * sy); |
| } |
| else if (name == 'roundrect') |
| { |
| var arcsize = Number(node.getAttribute('arcsize')); |
| |
| if (arcsize == 0) |
| { |
| arcsize = mxConstants.RECTANGLE_ROUNDING_FACTOR * 100; |
| } |
| |
| var w = Number(node.getAttribute('w')) * sx; |
| var h = Number(node.getAttribute('h')) * sy; |
| var factor = Number(arcsize) / 100; |
| var r = Math.min(w * factor, h * factor); |
| |
| canvas.roundrect(x0 + Number(node.getAttribute('x')) * sx, |
| y0 + Number(node.getAttribute('y')) * sy, |
| w, h, r, r); |
| } |
| else if (name == 'ellipse') |
| { |
| canvas.ellipse(x0 + Number(node.getAttribute('x')) * sx, |
| y0 + Number(node.getAttribute('y')) * sy, |
| Number(node.getAttribute('w')) * sx, |
| Number(node.getAttribute('h')) * sy); |
| } |
| else if (name == 'image') |
| { |
| if (!shape.outline) |
| { |
| var src = this.evaluateAttribute(node, 'src', shape); |
| |
| canvas.image(x0 + Number(node.getAttribute('x')) * sx, |
| y0 + Number(node.getAttribute('y')) * sy, |
| Number(node.getAttribute('w')) * sx, |
| Number(node.getAttribute('h')) * sy, |
| src, false, node.getAttribute('flipH') == '1', |
| node.getAttribute('flipV') == '1'); |
| } |
| } |
| else if (name == 'text') |
| { |
| if (!shape.outline) |
| { |
| var str = this.evaluateTextAttribute(node, 'str', shape); |
| var rotation = node.getAttribute('vertical') == '1' ? -90 : 0; |
| |
| if (node.getAttribute('align-shape') == '0') |
| { |
| var dr = shape.rotation; |
| |
| // Depends on flipping |
| var flipH = mxUtils.getValue(shape.style, mxConstants.STYLE_FLIPH, 0) == 1; |
| var flipV = mxUtils.getValue(shape.style, mxConstants.STYLE_FLIPV, 0) == 1; |
| |
| if (flipH && flipV) |
| { |
| rotation -= dr; |
| } |
| else if (flipH || flipV) |
| { |
| rotation += dr; |
| } |
| else |
| { |
| rotation -= dr; |
| } |
| } |
| |
| rotation -= node.getAttribute('rotation'); |
| |
| canvas.text(x0 + Number(node.getAttribute('x')) * sx, |
| y0 + Number(node.getAttribute('y')) * sy, |
| 0, 0, str, node.getAttribute('align') || 'left', |
| node.getAttribute('valign') || 'top', false, '', |
| null, false, rotation); |
| } |
| } |
| else if (name == 'include-shape') |
| { |
| var stencil = mxStencilRegistry.getStencil(node.getAttribute('name')); |
| |
| if (stencil != null) |
| { |
| var x = x0 + Number(node.getAttribute('x')) * sx; |
| var y = y0 + Number(node.getAttribute('y')) * sy; |
| var w = Number(node.getAttribute('w')) * sx; |
| var h = Number(node.getAttribute('h')) * sy; |
| |
| stencil.drawShape(canvas, shape, x, y, w, h); |
| } |
| } |
| else if (name == 'fillstroke') |
| { |
| canvas.fillAndStroke(); |
| } |
| else if (name == 'fill') |
| { |
| canvas.fill(); |
| } |
| else if (name == 'stroke') |
| { |
| canvas.stroke(); |
| } |
| else if (name == 'strokewidth') |
| { |
| var s = (node.getAttribute('fixed') == '1') ? 1 : minScale; |
| canvas.setStrokeWidth(Number(node.getAttribute('width')) * s); |
| } |
| else if (name == 'dashed') |
| { |
| canvas.setDashed(node.getAttribute('dashed') == '1'); |
| } |
| else if (name == 'dashpattern') |
| { |
| var value = node.getAttribute('pattern'); |
| |
| if (value != null) |
| { |
| var tmp = value.split(' '); |
| var pat = []; |
| |
| for (var i = 0; i < tmp.length; i++) |
| { |
| if (tmp[i].length > 0) |
| { |
| pat.push(Number(tmp[i]) * minScale); |
| } |
| } |
| |
| value = pat.join(' '); |
| canvas.setDashPattern(value); |
| } |
| } |
| else if (name == 'strokecolor') |
| { |
| canvas.setStrokeColor(node.getAttribute('color')); |
| } |
| else if (name == 'linecap') |
| { |
| canvas.setLineCap(node.getAttribute('cap')); |
| } |
| else if (name == 'linejoin') |
| { |
| canvas.setLineJoin(node.getAttribute('join')); |
| } |
| else if (name == 'miterlimit') |
| { |
| canvas.setMiterLimit(Number(node.getAttribute('limit'))); |
| } |
| else if (name == 'fillcolor') |
| { |
| canvas.setFillColor(node.getAttribute('color')); |
| } |
| else if (name == 'alpha') |
| { |
| canvas.setAlpha(node.getAttribute('alpha')); |
| } |
| else if (name == 'fontcolor') |
| { |
| canvas.setFontColor(node.getAttribute('color')); |
| } |
| else if (name == 'fontstyle') |
| { |
| canvas.setFontStyle(node.getAttribute('style')); |
| } |
| else if (name == 'fontfamily') |
| { |
| canvas.setFontFamily(node.getAttribute('family')); |
| } |
| else if (name == 'fontsize') |
| { |
| canvas.setFontSize(Number(node.getAttribute('size')) * minScale); |
| } |
| |
| if (disableShadow && (name == 'fillstroke' || name == 'fill' || name == 'stroke')) |
| { |
| disableShadow = false; |
| canvas.setShadow(false); |
| } |
| }; |