コード例 #1
0
        /// <summary>
        /// Draws the shadow.
        /// </summary>
        /// <param name="canvas"></param>
        /// <param name="state"></param>
        /// <param name="rotation"></param>
        /// <param name="flipH"></param>
        /// <param name="flipV"></param>
        /// <param name="bounds"></param>
        /// <param name="alpha"></param>
        protected void DrawShadow(mxGdiCanvas2D canvas, mxCellState state, double rotation, bool flipH,
                                  bool flipV, mxRectangle bounds, double alpha, bool 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
            double  rad    = rotation * Math.PI / 180;
            double  cos    = Math.Cos(-rad);
            double  sin    = Math.Sin(-rad);
            mxPoint offset = mxUtils.GetRotatedPoint(new mxPoint(mxConstants.SHADOW_OFFSETX, mxConstants.SHADOW_OFFSETY), 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 (DrawShape(canvas, state, bounds, true))
            {
                canvas.Alpha = mxConstants.STENCIL_SHADOW_OPACITY * alpha;
                // TODO: Implement new shadow
                //canvas.Shadow(mxConstants.STENCIL_SHADOWCOLOR, filled);
            }

            canvas.Translate(-offset.X, -offset.Y);
        }
コード例 #2
0
        /// <summary>
        /// Parses the bounds, absolute points and label information from the style
        /// of the state into its respective fields and returns the label of the
        /// cell.
        /// </summary>
        public string ParseState(mxCellState state, bool edge)
        {
            Dictionary <string, object> style = state.Style;

            // Parses the bounds
            state.X      = mxUtils.GetDouble(style, "x");
            state.Y      = mxUtils.GetDouble(style, "y");
            state.Width  = mxUtils.GetDouble(style, "width");
            state.Height = mxUtils.GetDouble(style, "height");

            // Parses the absolute points list
            List <mxPoint> pts = ParsePoints(mxUtils.GetString(style, "points"));

            if (pts.Count > 0)
            {
                state.AbsolutePoints = pts;
            }

            // Parses the label and label bounds
            string label = mxUtils.GetString(style, "label");

            if (label != null && label.Length > 0)
            {
                mxPoint offset = new mxPoint(mxUtils.GetDouble(style, "dx"),
                                             mxUtils.GetDouble(style, "dy"));
                mxRectangle vertexBounds = (!edge) ? state : null;
                state.LabelBounds = mxUtils.GetLabelPaintBounds(label, style,
                                                                mxUtils.IsTrue(style, "html", false), offset, vertexBounds,
                                                                scale);
            }

            return(label);
        }
コード例 #3
0
        /// <summary>
        /// Returns a point that defines the location of the intersection point between
        /// the perimeter and the line between the center of the shape and the given point.
        /// </summary>
        /// <param name="terminal">State for the source or target terminal.</param>
        /// <param name="next">Point that lies outside of the given terminal.</param>
        /// <param name="orthogonal">Specifies if the orthogonal projection onto
        /// the perimeter should be returned. If this is false then the intersection
        /// of the perimeter and the line between the next and the center point is
        /// returned.</param>
        /// <param name="border">Optional border between the perimeter and the shape.</param>
        public mxPoint GetPerimeterPoint(mxCellState terminal, mxPoint next, bool orthogonal, double border)
        {
            mxPoint point = null;

            if (terminal != null)
            {
                mxPerimeterFunction perimeter = GetPerimeterFunction(terminal);

                if (perimeter != null && next != null)
                {
                    mxRectangle bounds = GetPerimeterBounds(terminal, border);

                    if (bounds.Width > 0 || bounds.Height > 0)
                    {
                        point = perimeter(bounds, terminal, next, orthogonal);
                    }
                }

                if (point == null)
                {
                    point = GetPoint(terminal);
                }
            }

            return(point);
        }
コード例 #4
0
        /// <summary>
        /// First validates all bounds and then validates all points recursively on
        /// all visible cells.
        /// </summary>
        public void Validate()
        {
            Object cell = graph.Model.Root;

            if (cell != null && states.Count == 0)
            {
                mxRectangle graphBounds = GetBoundingBox(ValidateCellState(ValidateCell(cell)));
                GraphBounds = (graphBounds != null) ? graphBounds : new mxRectangle();
            }
        }
コード例 #5
0
        /// <summary>
        /// Returns the rectangle that should be used as the perimeter of the cell.
        /// </summary>
        /// <param name="border"></param>
        /// <returns>Returns the rectangle that defines the perimeter.</returns>
        public mxRectangle GetPerimeterBounds(double border)
        {
            mxRectangle bounds = new mxRectangle(this);

            if (border != 0)
            {
                bounds.Grow(border);
            }

            return(bounds);
        }
コード例 #6
0
        /* (non-Dotnetdoc)
         * see com.mxgraph.mxGraphViewReader.CreateCanvas()
         */

        override public mxICanvas CreateCanvas(Dictionary <string, Object> attrs)
        {
            int width  = 0;
            int height = 0;
            int dx     = 0;
            int dy     = 0;

            mxRectangle tmp = Clip;

            if (tmp != null)
            {
                dx    -= (int)tmp.X;
                dy    -= (int)tmp.Y;
                width  = (int)tmp.Width;
                height = (int)tmp.Height;
            }
            else
            {
                int x = (int)Math.Round(mxUtils.GetDouble(attrs, "x"));
                int y = (int)Math.Round(mxUtils.GetDouble(attrs, "y"));
                width = (int)(Math.Round(mxUtils.GetDouble(attrs, "width")))
                        + border + 3;
                height = (int)(Math.Round(mxUtils.GetDouble(attrs, "height")))
                         + border + 3;

                if (cropping)
                {
                    dx = -x + 3;
                    dy = -y + 3;
                }
                else
                {
                    width  += x;
                    height += y;
                }
            }

            mxImageCanvas canvas = new mxImageCanvas(new mxGdiCanvas(),
                                                     width, height, Background, AntiAlias);

            canvas.Translate = new Point(dx, dy);

            return(canvas);
        }
コード例 #7
0
        /// <summary>
        /// Updates the label bounds in the given state.
        /// </summary>
        /// <param name="state"></param>
        public void UpdateLabelBounds(mxCellState state)
        {
            Object cell = state.Cell;
            Dictionary <string, Object> style = state.Style;

            if (mxUtils.GetString(style, mxConstants.STYLE_OVERFLOW, "").Equals("fill"))
            {
                state.LabelBounds = new mxRectangle(state);
            }
            else
            {
                string      label        = graph.GetLabel(cell);
                mxRectangle vertexBounds = (!graph.Model.IsEdge(cell)) ?
                                           state : null;
                state.LabelBounds = mxUtils.GetLabelPaintBounds(label,
                                                                style, false, state.AbsoluteOffset, vertexBounds,
                                                                scale);
            }
        }
コード例 #8
0
        /// <summary>
        /// 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 rectangle.
        /// </summary>
        /// <param name="state"></param>
        /// <param name="bounds"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        protected mxRectangle ComputeAspect(mxCellState state, mxRectangle bounds,
                                            string direction)
        {
            double x0 = bounds.X;
            double y0 = bounds.Y;
            double sx = bounds.Width / w0;
            double sy = bounds.Height / h0;

            bool inverse = (direction != null && (direction.Equals("north") || direction
                                                  .Equals("south")));

            if (inverse)
            {
                sy = bounds.Width / h0;
                sx = bounds.Height / w0;

                double delta = (bounds.Width - bounds.Height) / 2;

                x0 += delta;
                y0 -= delta;
            }

            if (aspect.Equals("fixed"))
            {
                sy = Math.Min(sx, sy);
                sx = sy;

                // Centers the shape inside the available space
                if (inverse)
                {
                    x0 += (bounds.Height - this.w0 * sx) / 2;
                    y0 += (bounds.Width - this.h0 * sy) / 2;
                }
                else
                {
                    x0 += (bounds.Width - this.w0 * sx) / 2;
                    y0 += (bounds.Height - this.h0 * sy) / 2;
                }
            }

            return(new mxRectangle(x0, y0, sx, sy));
        }
コード例 #9
0
        /// <summary>
        /// Returns the bounding box of the shape and the label for the given
        /// cell state and its children if recurse is true.
        /// </summary>
        /// <param name="state">Cell state whose bounding box should be returned.</param>
        /// <param name="recurse">Boolean indicating if the children should be included.</param>
        public mxRectangle GetBoundingBox(mxCellState state, Boolean recurse)
        {
            mxRectangle bbox = null;

            if (state != null)
            {
                if (state.BoundingBox != null)
                {
                    bbox = (mxRectangle)state.BoundingBox.Clone();
                }

                if (recurse)
                {
                    mxIGraphModel model      = graph.Model;
                    int           childCount = model.GetChildCount(state.Cell);

                    for (int i = 0; i < childCount; i++)
                    {
                        mxRectangle bounds = GetBoundingBox(
                            GetState(model.GetChildAt(state.Cell, i)), true);

                        if (bounds != null)
                        {
                            if (bbox == null)
                            {
                                bbox = bounds;
                            }
                            else
                            {
                                bbox.Add(bounds);
                            }
                        }
                    }
                }
            }

            return(bbox);
        }
コード例 #10
0
        /**
         * Draws this stencil inside the given bounds.
         */

        public bool DrawShape(mxGdiCanvas2D canvas, mxCellState state,
                              mxRectangle bounds, bool background)
        {
            XmlNode elt = (background) ? bgNode : fgNode;

            if (elt != null)
            {
                String direction = mxUtils.GetString(state.Style,
                                                     mxConstants.STYLE_DIRECTION, null);
                mxRectangle aspect   = ComputeAspect(state, bounds, direction);
                double      minScale = Math.Min(aspect.Width, aspect.Height);
                double      sw       = strokewidth.Equals("inherit") ? mxUtils.GetDouble(
                    state.Style, mxConstants.STYLE_STROKEWIDTH, 1)
                                       * state.View.Scale : double
                                       .Parse(strokewidth) * minScale;
                lastMoveX          = 0;
                lastMoveY          = 0;
                canvas.StrokeWidth = sw;

                XmlNode tmp = elt.FirstChild;

                while (tmp != null)
                {
                    if (tmp.NodeType == XmlNodeType.Element)
                    {
                        DrawElement(canvas, state, (XmlElement)tmp, aspect);
                    }

                    tmp = tmp.NextSibling;
                }

                return(true);
            }

            return(false);
        }
コード例 #11
0
        /// <summary>
        /// Constructs a copy of the given geometry.
        /// </summary>
        /// <param name="geometry">Geometry to construct a copy of.</param>
        public mxGeometry(mxGeometry geometry)
            : base(geometry.X, geometry.Y, geometry.Width, geometry
                   .Height)
        {
            if (geometry.points != null)
            {
                points = new List <mxPoint>(geometry.points.Count);

                foreach (mxPoint pt in geometry.points)
                {
                    points.Add(pt.Clone());
                }
            }

            if (geometry.sourcePoint != null)
            {
                sourcePoint = geometry.sourcePoint.Clone();
            }

            if (geometry.targetPoint != null)
            {
                targetPoint = geometry.targetPoint.Clone();
            }

            if (geometry.offset != null)
            {
                offset = geometry.offset.Clone();
            }

            if (geometry.alternateBounds != null)
            {
                alternateBounds = geometry.alternateBounds.Clone();
            }

            relative = geometry.relative;
        }
コード例 #12
0
        /// <summary>
        /// Returns the bounding box for an array of cells or null, if no cells are
        /// specified.
        /// </summary>
        public mxRectangle GetBounds(Object[] cells, bool boundingBox)
        {
            mxRectangle result = null;

            if (cells != null && cells.Length > 0)
            {
                mxIGraphModel model = graph.Model;

                for (int i = 0; i < cells.Length; i++)
                {
                    if (model.IsVertex(cells[i]) || model.IsEdge(cells[i]))
                    {
                        mxCellState state = GetState(cells[i]);

                        if (state != null)
                        {
                            mxRectangle tmp = (boundingBox) ? state.BoundingBox : state;

                            if (tmp != null)
                            {
                                if (result == null)
                                {
                                    result = new mxRectangle(tmp);
                                }
                                else
                                {
                                    result.Add(tmp);
                                }
                            }
                        }
                    }
                }
            }

            return(result);
        }
コード例 #13
0
        /// <summary>
        /// Draws the given element.
        /// </summary>
        /// <param name="canvas"></param>
        /// <param name="state"></param>
        /// <param name="node"></param>
        /// <param name="aspect"></param>
        protected void DrawElement(mxGdiCanvas2D canvas, mxCellState state,
                                   XmlElement node, mxRectangle aspect)
        {
            string name     = node.Name;
            double x0       = aspect.X;
            double y0       = aspect.Y;
            double sx       = aspect.Width;
            double sy       = aspect.Height;
            double minScale = Math.Min(sx, sy);

            // LATER: Move to lookup table
            if (name.Equals("save"))
            {
                canvas.Save();
            }
            else if (name.Equals("restore"))
            {
                canvas.Restore();
            }
            else if (name.Equals("path"))
            {
                canvas.Begin();

                // Renders the elements inside the given path
                XmlNode childNode = node.FirstChild;

                while (childNode != null)
                {
                    if (childNode.NodeType == XmlNodeType.Element)
                    {
                        DrawElement(canvas, state, (XmlElement)childNode, aspect);
                    }

                    childNode = childNode.NextSibling;
                }
            }
            else if (name.Equals("close"))
            {
                canvas.Close();
            }
            else if (name.Equals("move"))
            {
                lastMoveX = x0 + GetDouble(node, "x") * sx;
                lastMoveY = y0 + GetDouble(node, "y") * sy;
                canvas.MoveTo(lastMoveX, lastMoveY);
            }
            else if (name.Equals("line"))
            {
                lastMoveX = x0 + GetDouble(node, "x") * sx;
                lastMoveY = y0 + GetDouble(node, "y") * sy;
                canvas.LineTo(lastMoveX, lastMoveY);
            }
            else if (name.Equals("quad"))
            {
                lastMoveX = x0 + GetDouble(node, "x2") * sx;
                lastMoveY = y0 + GetDouble(node, "y2") * sy;
                canvas.QuadTo(x0 + GetDouble(node, "x1") * sx,
                              y0 + GetDouble(node, "y1") * sy, lastMoveX, lastMoveY);
            }
            else if (name.Equals("curve"))
            {
                lastMoveX = x0 + GetDouble(node, "x3") * sx;
                lastMoveY = y0 + GetDouble(node, "y3") * sy;
                canvas.CurveTo(x0 + GetDouble(node, "x1") * sx,
                               y0 + GetDouble(node, "y1") * sy, x0 + GetDouble(node, "x2")
                               * sx, y0 + GetDouble(node, "y2") * sy, lastMoveX,
                               lastMoveY);
            }
            else if (name.Equals("arc"))
            {
                // Arc from stencil is turned into curves in image output
                double r1           = GetDouble(node, "rx") * sx;
                double r2           = GetDouble(node, "ry") * sy;
                double angle        = GetDouble(node, "x-axis-rotation");
                double largeArcFlag = GetDouble(node, "large-arc-flag");
                double sweepFlag    = GetDouble(node, "sweep-flag");
                double x            = x0 + GetDouble(node, "x") * sx;
                double y            = y0 + GetDouble(node, "y") * sy;

                double[] curves = mxUtils.ArcToCurves(this.lastMoveX,
                                                      this.lastMoveY, r1, r2, angle, largeArcFlag, sweepFlag, x,
                                                      y);

                for (int i = 0; i < curves.Length; i += 6)
                {
                    canvas.CurveTo(curves[i], curves[i + 1], curves[i + 2],
                                   curves[i + 3], curves[i + 4], curves[i + 5]);

                    lastMoveX = curves[i + 4];
                    lastMoveY = curves[i + 5];
                }
            }
            else if (name.Equals("rect"))
            {
                canvas.Rect(x0 + GetDouble(node, "x") * sx,
                            y0 + GetDouble(node, "y") * sy, GetDouble(node, "w") * sx,
                            GetDouble(node, "h") * sy);
            }
            else if (name.Equals("roundrect"))
            {
                double arcsize = GetDouble(node, "arcsize");

                if (arcsize == 0)
                {
                    arcsize = mxConstants.RECTANGLE_ROUNDING_FACTOR * 100;
                }

                double w      = GetDouble(node, "w") * sx;
                double h      = GetDouble(node, "h") * sy;
                double factor = arcsize / 100;
                double r      = Math.Min(w * factor, h * factor);

                canvas.Roundrect(x0 + GetDouble(node, "x") * sx,
                                 y0 + GetDouble(node, "y") * sy, GetDouble(node, "w") * sx,
                                 GetDouble(node, "h") * sy, r, r);
            }
            else if (name.Equals("ellipse"))
            {
                canvas.Ellipse(x0 + GetDouble(node, "x") * sx,
                               y0 + GetDouble(node, "y") * sy, GetDouble(node, "w") * sx,
                               GetDouble(node, "h") * sy);
            }
            else if (name.Equals("image"))
            {
                string src = EvaluateAttribute(node, "src", state);

                canvas.Image(x0 + GetDouble(node, "x") * sx,
                             y0 + GetDouble(node, "y") * sy, GetDouble(node, "w") * sx,
                             GetDouble(node, "h") * sy, src, false,
                             GetString(node, "flipH", "0").Equals("1"),
                             GetString(node, "flipV", "0").Equals("1"));
            }
            else if (name.Equals("text"))
            {
                String str      = EvaluateAttribute(node, "str", state);
                double rotation = GetString(node, "vertical", "0").Equals("1") ? -90 : 0;

                canvas.Text(x0 + GetDouble(node, "x") * sx,
                            y0 + GetDouble(node, "y") * sy, 0, 0, str,
                            node.GetAttribute("align"), node.GetAttribute("valign"),
                            false, "", null, false, rotation, null);
            }
            else if (name.Equals("include-shape"))
            {
                mxStencil stencil = mxStencilRegistry.GetStencil(node
                                                                 .GetAttribute("name"));

                if (stencil != null)
                {
                    double x = x0 + GetDouble(node, "x") * sx;
                    double y = y0 + GetDouble(node, "y") * sy;
                    double w = GetDouble(node, "w") * sx;
                    double h = GetDouble(node, "h") * sy;

                    mxRectangle tmp = new mxRectangle(x, y, w, h);
                    stencil.DrawShape(canvas, state, tmp, true);
                    stencil.DrawShape(canvas, state, tmp, false);
                }
            }
            else if (name.Equals("fillstroke"))
            {
                canvas.FillAndStroke();
            }
            else if (name.Equals("fill"))
            {
                canvas.Fill();
            }
            else if (name.Equals("stroke"))
            {
                canvas.Stroke();
            }
            else if (name.Equals("strokewidth"))
            {
                canvas.StrokeWidth = GetDouble(node, "width") * minScale;
            }
            else if (name.Equals("dashed"))
            {
                canvas.Dashed = node.GetAttribute("dashed") == "1";
            }
            else if (name.Equals("dashpattern"))
            {
                string value = node.GetAttribute("pattern");

                if (value != null)
                {
                    string[]      tmp = value.Split(' ');
                    StringBuilder pat = new StringBuilder();

                    for (int i = 0; i < tmp.Length; i++)
                    {
                        if (tmp[i].Length > 0)
                        {
                            pat.Append(double.Parse(tmp[i]) * minScale);
                            pat.Append(" ");
                        }
                    }

                    value = pat.ToString();
                }

                canvas.DashPattern = value;
            }
            else if (name.Equals("strokecolor"))
            {
                canvas.StrokeColor = node.GetAttribute("color");
            }
            else if (name.Equals("linecap"))
            {
                canvas.LineCap = node.GetAttribute("cap");
            }
            else if (name.Equals("linejoin"))
            {
                canvas.LineJoin = node.GetAttribute("join");
            }
            else if (name.Equals("miterlimit"))
            {
                canvas.MiterLimit = GetDouble(node, "limit");
            }
            else if (name.Equals("fillcolor"))
            {
                canvas.FillColor = node.GetAttribute("color");
            }
            else if (name.Equals("fontcolor"))
            {
                canvas.FontColor = node.GetAttribute("color");
            }
            else if (name.Equals("fontstyle"))
            {
                canvas.FontStyle = GetInt(node, "style", 0);
            }
            else if (name.Equals("fontfamily"))
            {
                canvas.FontFamily = node.GetAttribute("family");
            }
            else if (name.Equals("fontsize"))
            {
                canvas.FontSize = GetDouble(node, "size") * minScale;
            }
        }
コード例 #14
0
        public void execute(Object parent)
        {
            mxIGraphModel model = graph.Model; //.GetModel();

            // Moves the vertices to build a circle. Makes sure the
            // radius is large enough for the vertices to not
            // overlap
            model.BeginUpdate();
            try
            {
                // Gets all vertices inside the parent and finds
                // the maximum dimension of the largest vertex
                double        max        = 0;
                Double        top        = 0;
                Double        left       = 0;
                List <Object> vertices   = new List <Object>();
                int           childCount = model.GetChildCount(parent);

                for (int i = 0; i < childCount; i++)
                {
                    Object cell = model.GetChildAt(parent, i);

                    if (!isVertexIgnored(cell))
                    {
                        vertices.add(cell);
                        mxRectangle bounds = getVertexBounds(cell);

                        if (top == null)
                        {
                            top = bounds.getY();
                        }
                        else
                        {
                            top = Math.Min(top, bounds.getY());
                        }

                        if (left == null)
                        {
                            left = bounds.getX();
                        }
                        else
                        {
                            left = Math.Min(left, bounds.getX());
                        }

                        max = Math.Max(max, Math.Max(bounds.getWidth(), bounds
                                                     .getHeight()));
                    }
                    else if (!isEdgeIgnored(cell))
                    {
                        if (isResetEdges())
                        {
                            graph.resetEdge(cell);
                        }

                        if (isDisableEdgeStyle())
                        {
                            setEdgeStyleEnabled(cell, false);
                        }
                    }
                }

                int    vertexCount = vertices.size();
                double r           = Math.Max(vertexCount * max / Math.PI, radius);

                // Moves the circle to the specified origin
                if (moveCircle)
                {
                    left = x0;
                    top  = y0;
                }

                circle(vertices.ToArray(), r, left, top);
            }
            finally
            {
                model.EndUpdate();
            }
        }
コード例 #15
0
        /// <summary>
        /// Updates the bounding box in the given cell state.
        /// </summary>
        /// <param name="state">Cell state whose bounding box should be
        /// updated.</param>
        /// <returns></returns>
        public mxRectangle UpdateBoundingBox(mxCellState state)
        {
            // Gets the cell bounds and adds shadows and markers
            mxRectangle rect = new mxRectangle(state.GetRectangle());
            Dictionary <string, Object> style = state.Style;

            // Adds extra pixels for the marker and stroke assuming
            // that the border stroke is centered around the bounds
            // and the first pixel is drawn inside the bounds
            double strokeWidth = Math.Max(1, Math.Round(mxUtils.GetInt(style,
                                                                       mxConstants.STYLE_STROKEWIDTH, 1)
                                                        * scale));

            strokeWidth -= Math.Max(1, strokeWidth / 2);

            if (graph.Model.IsEdge(state.Cell))
            {
                int ms = 0;

                if (style.ContainsKey(mxConstants.STYLE_ENDARROW) ||
                    style.ContainsKey(mxConstants.STYLE_STARTARROW))
                {
                    ms = (int)Math.Round(mxConstants.DEFAULT_MARKERSIZE * scale);
                }

                // Adds the strokewidth
                rect.Grow(ms + strokeWidth);

                // Adds worst case border for an arrow shape
                if (mxUtils.GetString(style, mxConstants.STYLE_SHAPE, "").Equals(
                        mxConstants.SHAPE_ARROW))
                {
                    rect.Grow(mxConstants.ARROW_WIDTH / 2);
                }
            }
            else
            {
                rect.Grow(strokeWidth);
            }

            // Adds extra pixels for the shadow
            if (mxUtils.IsTrue(style, mxConstants.STYLE_SHADOW))
            {
                rect.Width  += mxConstants.SHADOW_OFFSETX;
                rect.Height += mxConstants.SHADOW_OFFSETY;
            }

            // Adds oversize images in labels
            if (mxUtils.GetString(style, mxConstants.STYLE_SHAPE, "").Equals(
                    mxConstants.SHAPE_LABEL))
            {
                if (mxUtils.GetString(style, mxConstants.STYLE_IMAGE) != null)
                {
                    double w = mxUtils.GetInt(style,
                                              mxConstants.STYLE_IMAGE_WIDTH,
                                              mxConstants.DEFAULT_IMAGESIZE) * scale;
                    double h = mxUtils.GetInt(style,
                                              mxConstants.STYLE_IMAGE_HEIGHT,
                                              mxConstants.DEFAULT_IMAGESIZE) * scale;

                    double x = state.X;
                    double y = 0;

                    string imgAlign = mxUtils
                                      .GetString(style, mxConstants.STYLE_IMAGE_ALIGN,
                                                 mxConstants.ALIGN_LEFT);
                    string imgValign = mxUtils.GetString(style,
                                                         mxConstants.STYLE_IMAGE_VERTICAL_ALIGN,
                                                         mxConstants.ALIGN_MIDDLE);

                    if (imgAlign.Equals(mxConstants.ALIGN_RIGHT))
                    {
                        x += state.Width - w;
                    }
                    else if (imgAlign.Equals(mxConstants.ALIGN_CENTER))
                    {
                        x += (state.Width - w) / 2;
                    }

                    if (imgValign.Equals(mxConstants.ALIGN_TOP))
                    {
                        y = state.Y;
                    }
                    else if (imgValign.Equals(mxConstants.ALIGN_BOTTOM))
                    {
                        y = state.Y + state.Height - h;
                    }
                    else
                    {
                        y = state.Y + (state.Height - h) / 2;
                    }

                    rect.Add(new mxRectangle(x, y, w, h));
                }
            }

            // Adds the rotated bounds to the bounding box if the
            // shape is rotated
            double      rotation = mxUtils.GetDouble(style, mxConstants.STYLE_ROTATION);
            mxRectangle bbox     = mxUtils.GetBoundingBox(rect, rotation);

            // Add the rotated bounding box to the non-rotated so
            // that all handles are also covered
            if (bbox != null)
            {
                rect.Add(bbox);
            }

            // Unifies the cell bounds and the label bounds
            if (!mxUtils.GetString(style, mxConstants.STYLE_OVERFLOW, "").Equals("hidden"))
            {
                rect.Add(state.LabelBounds);
            }

            state.BoundingBox = rect;

            return(rect);
        }