123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104 |
- /**
- * Copyright (c) 2006-2015, JGraph Ltd
- * Copyright (c) 2006-2015, Gaudenz Alder
- */
- /**
- *
- * Class: mxVmlCanvas2D
- *
- * Implements a canvas to be used for rendering VML. Here is an example of implementing a
- * fallback for SVG images which are not supported in VML-based browsers.
- *
- * (code)
- * var mxVmlCanvas2DImage = mxVmlCanvas2D.prototype.image;
- * mxVmlCanvas2D.prototype.image = function(x, y, w, h, src, aspect, flipH, flipV)
- * {
- * if (src.substring(src.length - 4, src.length) == '.svg')
- * {
- * src = 'http://www.jgraph.com/images/mxgraph.gif';
- * }
- *
- * mxVmlCanvas2DImage.apply(this, arguments);
- * };
- * (end)
- *
- * To disable anti-aliasing in the output, use the following code.
- *
- * (code)
- * document.createStyleSheet().cssText = mxClient.VML_PREFIX + '\\:*{antialias:false;)}';
- * (end)
- *
- * A description of the public API is available in <mxXmlCanvas2D>. Note that
- * there is a known issue in VML where gradients are painted using the outer
- * bounding box of rotated shapes, not the actual bounds of the shape. See
- * also <text> for plain text label restrictions in shapes for VML.
- */
- var mxVmlCanvas2D = function(root)
- {
- mxAbstractCanvas2D.call(this);
- /**
- * Variable: root
- *
- * Reference to the container for the SVG content.
- */
- this.root = root;
- };
- /**
- * Extends mxAbstractCanvas2D
- */
- mxUtils.extend(mxVmlCanvas2D, mxAbstractCanvas2D);
- /**
- * Variable: path
- *
- * Holds the current DOM node.
- */
- mxVmlCanvas2D.prototype.node = null;
- /**
- * Variable: textEnabled
- *
- * Specifies if text output should be enabledetB. Default is true.
- */
- mxVmlCanvas2D.prototype.textEnabled = true;
- /**
- * Variable: moveOp
- *
- * Contains the string used for moving in paths. Default is 'm'.
- */
- mxVmlCanvas2D.prototype.moveOp = 'm';
- /**
- * Variable: lineOp
- *
- * Contains the string used for moving in paths. Default is 'l'.
- */
- mxVmlCanvas2D.prototype.lineOp = 'l';
- /**
- * Variable: curveOp
- *
- * Contains the string used for bezier curves. Default is 'c'.
- */
- mxVmlCanvas2D.prototype.curveOp = 'c';
- /**
- * Variable: closeOp
- *
- * Holds the operator for closing curves. Default is 'x e'.
- */
- mxVmlCanvas2D.prototype.closeOp = 'x';
- /**
- * Variable: rotatedHtmlBackground
- *
- * Background color for rotated HTML. Default is ''. This can be set to eg.
- * white to improve rendering of rotated text in VML for IE9.
- */
- mxVmlCanvas2D.prototype.rotatedHtmlBackground = '';
- /**
- * Variable: vmlScale
- *
- * Specifies the scale used to draw VML shapes.
- */
- mxVmlCanvas2D.prototype.vmlScale = 1;
- /**
- * Function: createElement
- *
- * Creates the given element using the document.
- */
- mxVmlCanvas2D.prototype.createElement = function(name)
- {
- return document.createElement(name);
- };
- /**
- * Function: createVmlElement
- *
- * Creates a new element using <createElement> and prefixes the given name with
- * <mxClient.VML_PREFIX>.
- */
- mxVmlCanvas2D.prototype.createVmlElement = function(name)
- {
- return this.createElement(mxClient.VML_PREFIX + ':' + name);
- };
- /**
- * Function: addNode
- *
- * Adds the current node to the <root>.
- */
- mxVmlCanvas2D.prototype.addNode = function(filled, stroked)
- {
- var node = this.node;
- var s = this.state;
-
- if (node != null)
- {
- if (node.nodeName == 'shape')
- {
- // Checks if the path is not empty
- if (this.path != null && this.path.length > 0)
- {
- node.path = this.path.join(' ') + ' e';
- node.style.width = this.root.style.width;
- node.style.height = this.root.style.height;
- node.coordsize = parseInt(node.style.width) + ' ' + parseInt(node.style.height);
- }
- else
- {
- return;
- }
- }
- node.strokeweight = this.format(Math.max(1, s.strokeWidth * s.scale / this.vmlScale)) + 'px';
-
- if (s.shadow)
- {
- this.root.appendChild(this.createShadow(node,
- filled && s.fillColor != null,
- stroked && s.strokeColor != null));
- }
-
- if (stroked && s.strokeColor != null)
- {
- node.stroked = 'true';
- node.strokecolor = s.strokeColor;
- }
- else
- {
- node.stroked = 'false';
- }
- node.appendChild(this.createStroke());
- if (filled && s.fillColor != null)
- {
- node.appendChild(this.createFill());
- }
- else if (this.pointerEvents && (node.nodeName != 'shape' ||
- this.path[this.path.length - 1] == this.closeOp))
- {
- node.appendChild(this.createTransparentFill());
- }
- else
- {
- node.filled = 'false';
- }
- // LATER: Update existing DOM for performance
- this.root.appendChild(node);
- }
- };
- /**
- * Function: createTransparentFill
- *
- * Creates a transparent fill.
- */
- mxVmlCanvas2D.prototype.createTransparentFill = function()
- {
- var fill = this.createVmlElement('fill');
- fill.src = mxClient.imageBasePath + '/transparent.gif';
- fill.type = 'tile';
-
- return fill;
- };
- /**
- * Function: createFill
- *
- * Creates a fill for the current state.
- */
- mxVmlCanvas2D.prototype.createFill = function()
- {
- var s = this.state;
-
- // Gradients in foregrounds not supported because special gradients
- // with bounds must be created for each element in graphics-canvases
- var fill = this.createVmlElement('fill');
- fill.color = s.fillColor;
- if (s.gradientColor != null)
- {
- fill.type = 'gradient';
- fill.method = 'none';
- fill.color2 = s.gradientColor;
- var angle = 180 - s.rotation;
-
- if (s.gradientDirection == mxConstants.DIRECTION_WEST)
- {
- angle -= 90 + ((this.root.style.flip == 'x') ? 180 : 0);
- }
- else if (s.gradientDirection == mxConstants.DIRECTION_EAST)
- {
- angle += 90 + ((this.root.style.flip == 'x') ? 180 : 0);
- }
- else if (s.gradientDirection == mxConstants.DIRECTION_NORTH)
- {
- angle -= 180 + ((this.root.style.flip == 'y') ? -180 : 0);
- }
- else
- {
- angle += ((this.root.style.flip == 'y') ? -180 : 0);
- }
-
- if (this.root.style.flip == 'x' || this.root.style.flip == 'y')
- {
- angle *= -1;
- }
- // LATER: Fix outer bounding box for rotated shapes used in VML.
- fill.angle = mxUtils.mod(angle, 360);
- fill.opacity = (s.alpha * s.gradientFillAlpha * 100) + '%';
- fill.setAttribute(mxClient.OFFICE_PREFIX + ':opacity2', (s.alpha * s.gradientAlpha * 100) + '%');
- }
- else if (s.alpha < 1 || s.fillAlpha < 1)
- {
- fill.opacity = (s.alpha * s.fillAlpha * 100) + '%';
- }
-
- return fill;
- };
- /**
- * Function: createStroke
- *
- * Creates a fill for the current state.
- */
- mxVmlCanvas2D.prototype.createStroke = function()
- {
- var s = this.state;
- var stroke = this.createVmlElement('stroke');
- stroke.endcap = s.lineCap || 'flat';
- stroke.joinstyle = s.lineJoin || 'miter';
- stroke.miterlimit = s.miterLimit || '10';
-
- if (s.alpha < 1 || s.strokeAlpha < 1)
- {
- stroke.opacity = (s.alpha * s.strokeAlpha * 100) + '%';
- }
-
- if (s.dashed)
- {
- stroke.dashstyle = this.getVmlDashStyle();
- }
-
- return stroke;
- };
- /**
- * Function: getVmlDashPattern
- *
- * Returns a VML dash pattern for the current dashPattern.
- * See http://msdn.microsoft.com/en-us/library/bb264085(v=vs.85).aspx
- */
- mxVmlCanvas2D.prototype.getVmlDashStyle = function()
- {
- var result = 'dash';
-
- if (typeof(this.state.dashPattern) === 'string')
- {
- var tok = this.state.dashPattern.split(' ');
-
- if (tok.length > 0 && tok[0] == 1)
- {
- result = '0 2';
- }
- }
-
- return result;
- };
- /**
- * Function: createShadow
- *
- * Creates a shadow for the given node.
- */
- mxVmlCanvas2D.prototype.createShadow = function(node, filled, stroked)
- {
- var s = this.state;
- var rad = -s.rotation * (Math.PI / 180);
- var cos = Math.cos(rad);
- var sin = Math.sin(rad);
- var dx = s.shadowDx * s.scale;
- var dy = s.shadowDy * s.scale;
- if (this.root.style.flip == 'x')
- {
- dx *= -1;
- }
- else if (this.root.style.flip == 'y')
- {
- dy *= -1;
- }
-
- var shadow = node.cloneNode(true);
- shadow.style.marginLeft = Math.round(dx * cos - dy * sin) + 'px';
- shadow.style.marginTop = Math.round(dx * sin + dy * cos) + 'px';
- // Workaround for wrong cloning in IE8 standards mode
- if (document.documentMode == 8)
- {
- shadow.strokeweight = node.strokeweight;
-
- if (node.nodeName == 'shape')
- {
- shadow.path = this.path.join(' ') + ' e';
- shadow.style.width = this.root.style.width;
- shadow.style.height = this.root.style.height;
- shadow.coordsize = parseInt(node.style.width) + ' ' + parseInt(node.style.height);
- }
- }
-
- if (stroked)
- {
- shadow.strokecolor = s.shadowColor;
- shadow.appendChild(this.createShadowStroke());
- }
- else
- {
- shadow.stroked = 'false';
- }
-
- if (filled)
- {
- shadow.appendChild(this.createShadowFill());
- }
- else
- {
- shadow.filled = 'false';
- }
-
- return shadow;
- };
- /**
- * Function: createShadowFill
- *
- * Creates the fill for the shadow.
- */
- mxVmlCanvas2D.prototype.createShadowFill = function()
- {
- var fill = this.createVmlElement('fill');
- fill.color = this.state.shadowColor;
- fill.opacity = (this.state.alpha * this.state.shadowAlpha * 100) + '%';
-
- return fill;
- };
- /**
- * Function: createShadowStroke
- *
- * Creates the stroke for the shadow.
- */
- mxVmlCanvas2D.prototype.createShadowStroke = function()
- {
- var stroke = this.createStroke();
- stroke.opacity = (this.state.alpha * this.state.shadowAlpha * 100) + '%';
-
- return stroke;
- };
- /**
- * Function: rotate
- *
- * Sets the rotation of the canvas. Note that rotation cannot be concatenated.
- */
- mxVmlCanvas2D.prototype.rotate = function(theta, flipH, flipV, cx, cy)
- {
- if (flipH && flipV)
- {
- theta += 180;
- }
- else if (flipH)
- {
- this.root.style.flip = 'x';
- }
- else if (flipV)
- {
- this.root.style.flip = 'y';
- }
- if (flipH ? !flipV : flipV)
- {
- theta *= -1;
- }
- this.root.style.rotation = theta;
- this.state.rotation = this.state.rotation + theta;
- this.state.rotationCx = cx;
- this.state.rotationCy = cy;
- };
- /**
- * Function: begin
- *
- * Extends superclass to create path.
- */
- mxVmlCanvas2D.prototype.begin = function()
- {
- mxAbstractCanvas2D.prototype.begin.apply(this, arguments);
- this.node = this.createVmlElement('shape');
- this.node.style.position = 'absolute';
- };
- /**
- * Function: quadTo
- *
- * Replaces quadratic curve with bezier curve in VML.
- */
- mxVmlCanvas2D.prototype.quadTo = function(x1, y1, x2, y2)
- {
- var s = this.state;
- var cpx0 = (this.lastX + s.dx) * s.scale;
- var cpy0 = (this.lastY + s.dy) * s.scale;
- var qpx1 = (x1 + s.dx) * s.scale;
- var qpy1 = (y1 + s.dy) * s.scale;
- var cpx3 = (x2 + s.dx) * s.scale;
- var cpy3 = (y2 + s.dy) * s.scale;
-
- var cpx1 = cpx0 + 2/3 * (qpx1 - cpx0);
- var cpy1 = cpy0 + 2/3 * (qpy1 - cpy0);
-
- var cpx2 = cpx3 + 2/3 * (qpx1 - cpx3);
- var cpy2 = cpy3 + 2/3 * (qpy1 - cpy3);
-
- this.path.push('c ' + this.format(cpx1) + ' ' + this.format(cpy1) +
- ' ' + this.format(cpx2) + ' ' + this.format(cpy2) +
- ' ' + this.format(cpx3) + ' ' + this.format(cpy3));
- this.lastX = (cpx3 / s.scale) - s.dx;
- this.lastY = (cpy3 / s.scale) - s.dy;
-
- };
- /**
- * Function: createRect
- *
- * Sets the glass gradient.
- */
- mxVmlCanvas2D.prototype.createRect = function(nodeName, x, y, w, h)
- {
- var s = this.state;
- var n = this.createVmlElement(nodeName);
- n.style.position = 'absolute';
- n.style.left = this.format((x + s.dx) * s.scale) + 'px';
- n.style.top = this.format((y + s.dy) * s.scale) + 'px';
- n.style.width = this.format(w * s.scale) + 'px';
- n.style.height = this.format(h * s.scale) + 'px';
-
- return n;
- };
- /**
- * Function: rect
- *
- * Sets the current path to a rectangle.
- */
- mxVmlCanvas2D.prototype.rect = function(x, y, w, h)
- {
- this.node = this.createRect('rect', x, y, w, h);
- };
- /**
- * Function: roundrect
- *
- * Sets the current path to a rounded rectangle.
- */
- mxVmlCanvas2D.prototype.roundrect = function(x, y, w, h, dx, dy)
- {
- this.node = this.createRect('roundrect', x, y, w, h);
- // SetAttribute needed here for IE8
- this.node.setAttribute('arcsize', Math.max(dx * 100 / w, dy * 100 / h) + '%');
- };
- /**
- * Function: ellipse
- *
- * Sets the current path to an ellipse.
- */
- mxVmlCanvas2D.prototype.ellipse = function(x, y, w, h)
- {
- this.node = this.createRect('oval', x, y, w, h);
- };
- /**
- * Function: image
- *
- * Paints an image.
- */
- mxVmlCanvas2D.prototype.image = function(x, y, w, h, src, aspect, flipH, flipV)
- {
- var node = null;
-
- if (!aspect)
- {
- node = this.createRect('image', x, y, w, h);
- node.src = src;
- }
- else
- {
- // Uses fill with aspect to avoid asynchronous update of size
- node = this.createRect('rect', x, y, w, h);
- node.stroked = 'false';
-
- // Handles image aspect via fill
- var fill = this.createVmlElement('fill');
- fill.aspect = (aspect) ? 'atmost' : 'ignore';
- fill.rotate = 'true';
- fill.type = 'frame';
- fill.src = src;
- node.appendChild(fill);
- }
-
- if (flipH && flipV)
- {
- node.style.rotation = '180';
- }
- else if (flipH)
- {
- node.style.flip = 'x';
- }
- else if (flipV)
- {
- node.style.flip = 'y';
- }
-
- if (this.state.alpha < 1 || this.state.fillAlpha < 1)
- {
- // KNOWN: Borders around transparent images in IE<9. Using fill.opacity
- // fixes this problem by adding a white background in all IE versions.
- node.style.filter += 'alpha(opacity=' + (this.state.alpha * this.state.fillAlpha * 100) + ')';
- }
- this.root.appendChild(node);
- };
- /**
- * Function: createText
- *
- * Creates the innermost element that contains the HTML text.
- */
- mxVmlCanvas2D.prototype.createDiv = function(str, align, valign, overflow)
- {
- var div = this.createElement('div');
- var state = this.state;
- var css = '';
-
- if (state.fontBackgroundColor != null)
- {
- css += 'background-color:' + mxUtils.htmlEntities(state.fontBackgroundColor) + ';';
- }
-
- if (state.fontBorderColor != null)
- {
- css += 'border:1px solid ' + mxUtils.htmlEntities(state.fontBorderColor) + ';';
- }
-
- if (mxUtils.isNode(str))
- {
- div.appendChild(str);
- }
- else
- {
- if (overflow != 'fill' && overflow != 'width')
- {
- var div2 = this.createElement('div');
- div2.style.cssText = css;
- div2.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block';
- div2.style.zoom = '1';
- div2.style.textDecoration = 'inherit';
- div2.innerHTML = str;
- div.appendChild(div2);
- }
- else
- {
- div.style.cssText = css;
- div.innerHTML = str;
- }
- }
-
- var style = div.style;
- style.fontSize = (state.fontSize / this.vmlScale) + 'px';
- style.fontFamily = state.fontFamily;
- style.color = state.fontColor;
- style.verticalAlign = 'top';
- style.textAlign = align || 'left';
- style.lineHeight = (mxConstants.ABSOLUTE_LINE_HEIGHT) ? (state.fontSize * mxConstants.LINE_HEIGHT / this.vmlScale) + 'px' : mxConstants.LINE_HEIGHT;
- if ((state.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD)
- {
- style.fontWeight = 'bold';
- }
- if ((state.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC)
- {
- style.fontStyle = 'italic';
- }
-
- if ((state.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE)
- {
- style.textDecoration = 'underline';
- }
-
- return div;
- };
- /**
- * Function: text
- *
- * Paints the given text. Possible values for format are empty string for plain
- * text and html for HTML markup. Clipping, text background and border are not
- * supported for plain text in VML.
- */
- mxVmlCanvas2D.prototype.text = function(x, y, w, h, str, align, valign, wrap, format, overflow, clip, rotation, dir)
- {
- if (this.textEnabled && str != null)
- {
- var s = this.state;
-
- if (format == 'html')
- {
- if (s.rotation != null)
- {
- var pt = this.rotatePoint(x, y, s.rotation, s.rotationCx, s.rotationCy);
-
- x = pt.x;
- y = pt.y;
- }
- if (document.documentMode == 8 && !mxClient.IS_EM)
- {
- x += s.dx;
- y += s.dy;
-
- // Workaround for rendering offsets
- if (overflow != 'fill' && valign == mxConstants.ALIGN_TOP)
- {
- y -= 1;
- }
- }
- else
- {
- x *= s.scale;
- y *= s.scale;
- }
- // Adds event transparency in IE8 standards without the transparent background
- // filter which cannot be used due to bugs in the zoomed bounding box (too slow)
- // FIXME: No event transparency if inside v:rect (ie part of shape)
- // KNOWN: Offset wrong for rotated text with word that are longer than the wrapping
- // width in IE8 because real width of text cannot be determined here.
- // This should be fixed in mxText.updateBoundingBox by calling before this and
- // passing the real width to this method if not clipped and wrapped.
- var abs = (document.documentMode == 8 && !mxClient.IS_EM) ? this.createVmlElement('group') : this.createElement('div');
- abs.style.position = 'absolute';
- abs.style.display = 'inline';
- abs.style.left = this.format(x) + 'px';
- abs.style.top = this.format(y) + 'px';
- abs.style.zoom = s.scale;
- var box = this.createElement('div');
- box.style.position = 'relative';
- box.style.display = 'inline';
-
- var margin = mxUtils.getAlignmentAsPoint(align, valign);
- var dx = margin.x;
- var dy = margin.y;
- var div = this.createDiv(str, align, valign, overflow);
- var inner = this.createElement('div');
-
- if (dir != null)
- {
- div.setAttribute('dir', dir);
- }
- if (wrap && w > 0)
- {
- if (!clip)
- {
- div.style.width = Math.round(w) + 'px';
- }
-
- div.style.wordWrap = mxConstants.WORD_WRAP;
- div.style.whiteSpace = 'normal';
-
- // LATER: Check if other cases need to be handled
- if (div.style.wordWrap == 'break-word')
- {
- var tmp = div;
-
- if (tmp.firstChild != null && tmp.firstChild.nodeName == 'DIV')
- {
- tmp.firstChild.style.width = '100%';
- }
- }
- }
- else
- {
- div.style.whiteSpace = 'nowrap';
- }
-
- var rot = s.rotation + (rotation || 0);
-
- if (this.rotateHtml && rot != 0)
- {
- inner.style.display = 'inline';
- inner.style.zoom = '1';
- inner.appendChild(div);
- // Box not needed for rendering in IE8 standards
- if (document.documentMode == 8 && !mxClient.IS_EM && this.root.nodeName != 'DIV')
- {
- box.appendChild(inner);
- abs.appendChild(box);
- }
- else
- {
- abs.appendChild(inner);
- }
- }
- else if (document.documentMode == 8 && !mxClient.IS_EM)
- {
- box.appendChild(div);
- abs.appendChild(box);
- }
- else
- {
- div.style.display = 'inline';
- abs.appendChild(div);
- }
-
- // Inserts the node into the DOM
- if (this.root.nodeName != 'DIV')
- {
- // Rectangle to fix position in group
- var rect = this.createVmlElement('rect');
- rect.stroked = 'false';
- rect.filled = 'false';
- rect.appendChild(abs);
- this.root.appendChild(rect);
- }
- else
- {
- this.root.appendChild(abs);
- }
-
- if (clip)
- {
- div.style.overflow = 'hidden';
- div.style.width = Math.round(w) + 'px';
-
- if (!mxClient.IS_QUIRKS)
- {
- div.style.maxHeight = Math.round(h) + 'px';
- }
- }
- else if (overflow == 'fill')
- {
- // KNOWN: Affects horizontal alignment in quirks
- // but fill should only be used with align=left
- div.style.overflow = 'hidden';
- div.style.width = (Math.max(0, w) + 1) + 'px';
- div.style.height = (Math.max(0, h) + 1) + 'px';
- }
- else if (overflow == 'width')
- {
- // KNOWN: Affects horizontal alignment in quirks
- // but fill should only be used with align=left
- div.style.overflow = 'hidden';
- div.style.width = (Math.max(0, w) + 1) + 'px';
- div.style.maxHeight = (Math.max(0, h) + 1) + 'px';
- }
-
- if (this.rotateHtml && rot != 0)
- {
- var rad = rot * (Math.PI / 180);
-
- // Precalculate cos and sin for the rotation
- var real_cos = parseFloat(parseFloat(Math.cos(rad)).toFixed(8));
- var real_sin = parseFloat(parseFloat(Math.sin(-rad)).toFixed(8));
- rad %= 2 * Math.PI;
- if (rad < 0) rad += 2 * Math.PI;
- rad %= Math.PI;
- if (rad > Math.PI / 2) rad = Math.PI - rad;
-
- var cos = Math.cos(rad);
- var sin = Math.sin(rad);
- // Adds div to document to measure size
- if (document.documentMode == 8 && !mxClient.IS_EM)
- {
- div.style.display = 'inline-block';
- inner.style.display = 'inline-block';
- box.style.display = 'inline-block';
- }
-
- div.style.visibility = 'hidden';
- div.style.position = 'absolute';
- document.body.appendChild(div);
-
- var sizeDiv = div;
-
- if (sizeDiv.firstChild != null && sizeDiv.firstChild.nodeName == 'DIV')
- {
- sizeDiv = sizeDiv.firstChild;
- }
-
- var tmp = sizeDiv.offsetWidth + 3;
- var oh = sizeDiv.offsetHeight;
-
- if (clip)
- {
- w = Math.min(w, tmp);
- oh = Math.min(oh, h);
- }
- else
- {
- w = tmp;
- }
- // Handles words that are longer than the given wrapping width
- if (wrap)
- {
- div.style.width = w + 'px';
- }
-
- // Simulates max-height in quirks
- if (mxClient.IS_QUIRKS && (clip || overflow == 'width') && oh > h)
- {
- oh = h;
-
- // Quirks does not support maxHeight
- div.style.height = oh + 'px';
- }
-
- h = oh;
- var top_fix = (h - h * cos + w * -sin) / 2 - real_sin * w * (dx + 0.5) + real_cos * h * (dy + 0.5);
- var left_fix = (w - w * cos + h * -sin) / 2 + real_cos * w * (dx + 0.5) + real_sin * h * (dy + 0.5);
- if (abs.nodeName == 'group' && this.root.nodeName == 'DIV')
- {
- // Workaround for bug where group gets moved away if left and top are non-zero in IE8 standards
- var pos = this.createElement('div');
- pos.style.display = 'inline-block';
- pos.style.position = 'absolute';
- pos.style.left = this.format(x + (left_fix - w / 2) * s.scale) + 'px';
- pos.style.top = this.format(y + (top_fix - h / 2) * s.scale) + 'px';
-
- abs.parentNode.appendChild(pos);
- pos.appendChild(abs);
- }
- else
- {
- var sc = (document.documentMode == 8 && !mxClient.IS_EM) ? 1 : s.scale;
-
- abs.style.left = this.format(x + (left_fix - w / 2) * sc) + 'px';
- abs.style.top = this.format(y + (top_fix - h / 2) * sc) + 'px';
- }
-
- // KNOWN: Rotated text rendering quality is bad for IE9 quirks
- inner.style.filter = "progid:DXImageTransform.Microsoft.Matrix(M11="+real_cos+", M12="+
- real_sin+", M21="+(-real_sin)+", M22="+real_cos+", sizingMethod='auto expand')";
- inner.style.backgroundColor = this.rotatedHtmlBackground;
-
- if (this.state.alpha < 1)
- {
- inner.style.filter += 'alpha(opacity=' + (this.state.alpha * 100) + ')';
- }
- // Restore parent node for DIV
- inner.appendChild(div);
- div.style.position = '';
- div.style.visibility = '';
- }
- else if (document.documentMode != 8 || mxClient.IS_EM)
- {
- div.style.verticalAlign = 'top';
-
- if (this.state.alpha < 1)
- {
- abs.style.filter = 'alpha(opacity=' + (this.state.alpha * 100) + ')';
- }
-
- // Adds div to document to measure size
- var divParent = div.parentNode;
- div.style.visibility = 'hidden';
- document.body.appendChild(div);
-
- w = div.offsetWidth;
- var oh = div.offsetHeight;
-
- // Simulates max-height in quirks
- if (mxClient.IS_QUIRKS && clip && oh > h)
- {
- oh = h;
-
- // Quirks does not support maxHeight
- div.style.height = oh + 'px';
- }
-
- h = oh;
-
- div.style.visibility = '';
- divParent.appendChild(div);
-
- abs.style.left = this.format(x + w * dx * this.state.scale) + 'px';
- abs.style.top = this.format(y + h * dy * this.state.scale) + 'px';
- }
- else
- {
- if (this.state.alpha < 1)
- {
- div.style.filter = 'alpha(opacity=' + (this.state.alpha * 100) + ')';
- }
-
- // Faster rendering in IE8 without offsetWidth/Height
- box.style.left = (dx * 100) + '%';
- box.style.top = (dy * 100) + '%';
- }
- }
- else
- {
- this.plainText(x, y, w, h, mxUtils.htmlEntities(str, false), align, valign, wrap, format, overflow, clip, rotation, dir);
- }
- }
- };
- /**
- * Function: plainText
- *
- * Paints the outline of the current path.
- */
- mxVmlCanvas2D.prototype.plainText = function(x, y, w, h, str, align, valign, wrap, format, overflow, clip, rotation, dir)
- {
- // TextDirection is ignored since this code is not used (format is always HTML in the text function)
- var s = this.state;
- x = (x + s.dx) * s.scale;
- y = (y + s.dy) * s.scale;
-
- var node = this.createVmlElement('shape');
- node.style.width = '1px';
- node.style.height = '1px';
- node.stroked = 'false';
- var fill = this.createVmlElement('fill');
- fill.color = s.fontColor;
- fill.opacity = (s.alpha * 100) + '%';
- node.appendChild(fill);
-
- var path = this.createVmlElement('path');
- path.textpathok = 'true';
- path.v = 'm ' + this.format(0) + ' ' + this.format(0) + ' l ' + this.format(1) + ' ' + this.format(0);
-
- node.appendChild(path);
-
- // KNOWN: Font family and text decoration ignored
- var tp = this.createVmlElement('textpath');
- tp.style.cssText = 'v-text-align:' + align;
- tp.style.align = align;
- tp.style.fontFamily = s.fontFamily;
- tp.string = str;
- tp.on = 'true';
-
- // Scale via fontsize instead of node.style.zoom for correct offsets in IE8
- var size = s.fontSize * s.scale / this.vmlScale;
- tp.style.fontSize = size + 'px';
-
- // Bold
- if ((s.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD)
- {
- tp.style.fontWeight = 'bold';
- }
-
- // Italic
- if ((s.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC)
- {
- tp.style.fontStyle = 'italic';
- }
- // Underline
- if ((s.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE)
- {
- tp.style.textDecoration = 'underline';
- }
- var lines = str.split('\n');
- var textHeight = size + (lines.length - 1) * size * mxConstants.LINE_HEIGHT;
- var dx = 0;
- var dy = 0;
- if (valign == mxConstants.ALIGN_BOTTOM)
- {
- dy = - textHeight / 2;
- }
- else if (valign != mxConstants.ALIGN_MIDDLE) // top
- {
- dy = textHeight / 2;
- }
- if (rotation != null)
- {
- node.style.rotation = rotation;
- var rad = rotation * (Math.PI / 180);
- dx = Math.sin(rad) * dy;
- dy = Math.cos(rad) * dy;
- }
- // FIXME: Clipping is relative to bounding box
- /*if (clip)
- {
- node.style.clip = 'rect(0px ' + this.format(w) + 'px ' + this.format(h) + 'px 0px)';
- }*/
-
- node.appendChild(tp);
- node.style.left = this.format(x - dx) + 'px';
- node.style.top = this.format(y + dy) + 'px';
-
- this.root.appendChild(node);
- };
- /**
- * Function: stroke
- *
- * Paints the outline of the current path.
- */
- mxVmlCanvas2D.prototype.stroke = function()
- {
- this.addNode(false, true);
- };
- /**
- * Function: fill
- *
- * Fills the current path.
- */
- mxVmlCanvas2D.prototype.fill = function()
- {
- this.addNode(true, false);
- };
- /**
- * Function: fillAndStroke
- *
- * Fills and paints the outline of the current path.
- */
- mxVmlCanvas2D.prototype.fillAndStroke = function()
- {
- this.addNode(true, true);
- };
- __mxOutput.mxVmlCanvas2D = typeof mxVmlCanvas2D !== 'undefined' ? mxVmlCanvas2D : undefined;
|