Esempio n. 1
0
        public static bool TryGetTransform(ISvgTransformable element, out Transform transform)
        {
            transform = null;

            if (element == null)
            {
                return(false);
            }

            ISvgTransformList svgTList  = element.Transform.AnimVal;
            ISvgMatrix        svgMatrix = ((SvgTransformList)element.Transform.AnimVal).TotalMatrix;
            ISvgElement       nVE       = element.NearestViewportElement;

            if (nVE != null)
            {
                SvgTransformableElement par = (element as SvgElement).ParentNode as SvgTransformableElement;
                while (par != null && par != nVE)
                {
                    svgTList  = par.Transform.AnimVal;
                    svgMatrix = svgTList.Consolidate().Matrix.Multiply(svgMatrix);
                    par       = par.ParentNode as SvgTransformableElement;
                }
            }

            if (svgMatrix.IsIdentity)
            {
                transform = Transform.Identity;
                return(false);
            }

            transform = new MatrixTransform(ToWpfMatrix(svgMatrix));
            return(true);
        }
		public void TestShapeBBox()
		{
			SvgTransformableElement elm = Util.GetXmlElement("<rect x='1' y='2' width='3' height='4' />", "", "rect") as SvgTransformableElement;
			ISvgRect rect = elm.GetBBox();
			Assert.AreEqual(1, rect.X);
			Assert.AreEqual(2, rect.Y);
			Assert.AreEqual(3, rect.Width);
			Assert.AreEqual(4, rect.Height);
		}
		public void TestContainerBBoxWithMulipleChilds()
		{
			SvgTransformableElement elm = Util.GetXmlElement("<g><rect x='1' y='2' width='3' height='4' /><rect x='10' y='20' width='3' height='4' /></g>", "", "g") as SvgTransformableElement;
			ISvgRect rect = elm.GetBBox();
			Assert.AreEqual(1, rect.X);
			Assert.AreEqual(2, rect.Y);
			Assert.AreEqual(12, rect.Width);
			Assert.AreEqual(22, rect.Height);
		}
        public ISvgRect GetRenderedBounds(ISvgElement element, float margin)
        {
            SvgTransformableElement transElement = element as SvgTransformableElement;

            if (transElement != null)
            {
                SvgRectF rect = this.GetElementBounds(transElement, margin);

                return(new SvgRect(rect.X, rect.Y, rect.Width, rect.Height));
            }

            return(null);
        }
        protected void SetClip(GdiGraphics graphics)
        {
            if (_svgElement == null)
            {
                return;
            }

            SvgRenderingHint hint = _svgElement.RenderingHint;

            // todo: should we correct the clipping to adjust to the off-one-pixel drawing?
            graphics.TranslateClip(1, 1);

            #region Clip with clip
            // see http://www.w3.org/TR/SVG/masking.html#OverflowAndClipProperties
            if (_svgElement is ISvgSvgElement || _svgElement is ISvgMarkerElement ||
                _svgElement is ISvgSymbolElement || _svgElement is ISvgPatternElement)
            {
                // check overflow property
                CssValue overflow = _svgElement.GetComputedCssValue("overflow", string.Empty) as CssValue;
                // TODO: clip can have "rect(10 10 auto 10)"
                CssPrimitiveValue clip = _svgElement.GetComputedCssValue("clip", string.Empty) as CssPrimitiveValue;

                string sOverflow = null;

                if (overflow != null || overflow.CssText == "")
                {
                    sOverflow = overflow.CssText;
                }
                else
                {
                    if (this is ISvgSvgElement)
                    {
                        sOverflow = "hidden";
                    }
                }

                if (sOverflow != null)
                {
                    // "If the 'overflow' property has a value other than hidden or scroll, the property has no effect (i.e., a clipping rectangle is not created)."
                    if (sOverflow == "hidden" || sOverflow == "scroll")
                    {
                        RectangleF clipRect = RectangleF.Empty;
                        if (clip != null && clip.PrimitiveType == CssPrimitiveType.Rect)
                        {
                            if (_svgElement is ISvgSvgElement)
                            {
                                ISvgSvgElement svgElement = (ISvgSvgElement)_svgElement;
                                SvgRect        viewPort   = svgElement.Viewport as SvgRect;
                                clipRect = GdiConverter.ToRectangle(viewPort);
                                ICssRect clipShape = (CssRect)clip.GetRectValue();
                                if (clipShape.Top.PrimitiveType != CssPrimitiveType.Ident)
                                {
                                    clipRect.Y += (float)clipShape.Top.GetFloatValue(CssPrimitiveType.Number);
                                }
                                if (clipShape.Left.PrimitiveType != CssPrimitiveType.Ident)
                                {
                                    clipRect.X += (float)clipShape.Left.GetFloatValue(CssPrimitiveType.Number);
                                }
                                if (clipShape.Right.PrimitiveType != CssPrimitiveType.Ident)
                                {
                                    clipRect.Width = (clipRect.Right - clipRect.X) - (float)clipShape.Right.GetFloatValue(CssPrimitiveType.Number);
                                }
                                if (clipShape.Bottom.PrimitiveType != CssPrimitiveType.Ident)
                                {
                                    clipRect.Height = (clipRect.Bottom - clipRect.Y) - (float)clipShape.Bottom.GetFloatValue(CssPrimitiveType.Number);
                                }
                            }
                        }
                        else if (clip == null || (clip.PrimitiveType == CssPrimitiveType.Ident && clip.GetStringValue() == "auto"))
                        {
                            if (_svgElement is ISvgSvgElement)
                            {
                                ISvgSvgElement svgElement = (ISvgSvgElement)_svgElement;
                                SvgRect        viewPort   = svgElement.Viewport as SvgRect;
                                clipRect = GdiConverter.ToRectangle(viewPort);
                            }
                            else if (_svgElement is ISvgMarkerElement || _svgElement is ISvgSymbolElement ||
                                     _svgElement is ISvgPatternElement)
                            {
                                // TODO: what to do here?
                            }
                        }
                        if (clipRect != RectangleF.Empty)
                        {
                            graphics.SetClip(clipRect);
                        }
                    }
                }
            }
            #endregion

            #region Clip with clip-path

            // see: http://www.w3.org/TR/SVG/masking.html#EstablishingANewClippingPath

            if (hint == SvgRenderingHint.Shape || hint == SvgRenderingHint.Text ||
                hint == SvgRenderingHint.Clipping || hint == SvgRenderingHint.Masking ||
                hint == SvgRenderingHint.Containment || hint == SvgRenderingHint.Image)
            {
                CssPrimitiveValue clipPath = _svgElement.GetComputedCssValue("clip-path", string.Empty) as CssPrimitiveValue;

                if (clipPath != null && clipPath.PrimitiveType == CssPrimitiveType.Uri)
                {
                    string absoluteUri = _svgElement.ResolveUri(clipPath.GetStringValue());

                    SvgClipPathElement eClipPath = _svgElement.OwnerDocument.GetNodeByUri(absoluteUri) as SvgClipPathElement;

                    if (eClipPath != null)
                    {
                        GraphicsPath gpClip = CreateClippingRegion(graphics, eClipPath);

                        RectangleF clipBounds = gpClip != null?gpClip.GetBounds() : RectangleF.Empty;

                        if (clipBounds.Width.Equals(0) || clipBounds.Height.Equals(0))
                        {
                            return;
                        }

                        SvgUnitType pathUnits = (SvgUnitType)eClipPath.ClipPathUnits.AnimVal;

                        if (pathUnits == SvgUnitType.ObjectBoundingBox)
                        {
                            SvgTransformableElement transElement = _svgElement as SvgTransformableElement;

                            if (transElement != null)
                            {
                                ISvgRect bbox = transElement.GetBBox();

                                // scale clipping path
                                Matrix matrix = new Matrix();
                                matrix.Scale((float)bbox.Width, (float)bbox.Height);
                                gpClip.Transform(matrix);
                                graphics.SetClip(gpClip);

                                // offset clip
                                graphics.TranslateClip((float)bbox.X, (float)bbox.Y);
                            }
                            else
                            {
                                throw new NotImplementedException("clip-path with SvgUnitType.ObjectBoundingBox "
                                                                  + "not supported for this type of element: " + _svgElement.GetType());
                            }
                        }
                        else
                        {
                            graphics.SetClip(gpClip);
                        }

                        gpClip.Dispose();
                        gpClip = null;
                    }
                }
            }
            #endregion
        }
        private SvgRectF GetElementBounds(SvgTransformableElement element, float margin)
        {
            SvgRenderingHint hint = element.RenderingHint;

            if (hint == SvgRenderingHint.Shape || hint == SvgRenderingHint.Text)
            {
                GraphicsPath gp        = GdiRendering.CreatePath(element);
                ISvgMatrix   svgMatrix = element.GetScreenCTM();

                Matrix matrix = new Matrix((float)svgMatrix.A, (float)svgMatrix.B, (float)svgMatrix.C,
                                           (float)svgMatrix.D, (float)svgMatrix.E, (float)svgMatrix.F);
                SvgRectF bounds = SvgConverter.ToRect(gp.GetBounds(matrix));
                bounds = SvgRectF.Inflate(bounds, margin, margin);

                return(bounds);
            }

            SvgUseElement useElement = element as SvgUseElement;

            if (useElement != null)
            {
                SvgTransformableElement refEl = useElement.ReferencedElement as SvgTransformableElement;
                if (refEl == null)
                {
                    return(SvgRectF.Empty);
                }

                XmlElement refElParent = (XmlElement)refEl.ParentNode;
                element.OwnerDocument.Static = true;
                useElement.CopyToReferencedElement(refEl);
                element.AppendChild(refEl);

                SvgRectF bbox = this.GetElementBounds(refEl, margin);

                element.RemoveChild(refEl);
                useElement.RestoreReferencedElement(refEl);
                refElParent.AppendChild(refEl);
                element.OwnerDocument.Static = false;

                return(bbox);
            }

            SvgRectF union = SvgRectF.Empty;
            SvgTransformableElement transformChild;

            foreach (XmlNode childNode in element.ChildNodes)
            {
                if (childNode is SvgDefsElement)
                {
                    continue;
                }
                if (childNode is ISvgTransformable)
                {
                    transformChild = (SvgTransformableElement)childNode;
                    SvgRectF bbox = this.GetElementBounds(transformChild, margin);
                    if (bbox != SvgRectF.Empty)
                    {
                        if (union == SvgRectF.Empty)
                        {
                            union = bbox;
                        }
                        else
                        {
                            union = SvgRectF.Union(union, bbox);
                        }
                    }
                }
            }

            return(union);
        }
        protected FontWeight GetTextFontWeight(SvgTextContentElement element)
        {
            string fontWeight = element.GetPropertyValue("font-weight");

            if (string.IsNullOrWhiteSpace(fontWeight))
            {
                return(FontWeights.Normal);
            }

            switch (fontWeight)
            {
            case "normal":
                return(FontWeights.Normal);

            case "bold":
                return(FontWeights.Bold);

            case "100":
                return(FontWeights.Thin);

            case "200":
                return(FontWeights.ExtraLight);

            case "300":
                return(FontWeights.Light);

            case "400":
                return(FontWeights.Normal);

            case "500":
                return(FontWeights.Medium);

            case "600":
                return(FontWeights.SemiBold);

            case "700":
                return(FontWeights.Bold);

            case "800":
                return(FontWeights.ExtraBold);

            case "900":
                return(FontWeights.Black);

            case "950":
                return(FontWeights.UltraBlack);
            }

            if (string.Equals(fontWeight, "bolder", StringComparison.OrdinalIgnoreCase))
            {
                SvgTransformableElement parentElement = element.ParentNode as SvgTransformableElement;
                if (parentElement != null)
                {
                    fontWeight = parentElement.GetPropertyValue("font-weight");
                    if (!string.IsNullOrWhiteSpace(fontWeight))
                    {
                        return(this.GetBolderFontWeight(fontWeight));
                    }
                }
                return(FontWeights.ExtraBold);
            }
            if (string.Equals(fontWeight, "lighter", StringComparison.OrdinalIgnoreCase))
            {
                SvgTransformableElement parentElement = element.ParentNode as SvgTransformableElement;
                if (parentElement != null)
                {
                    fontWeight = parentElement.GetPropertyValue("font-weight");
                    if (!string.IsNullOrWhiteSpace(fontWeight))
                    {
                        return(this.GetLighterFontWeight(fontWeight));
                    }
                }
                return(FontWeights.Light);
            }

            return(FontWeights.Normal);
        }