protected void Clip(GdiGraphicsWrapper gr)
        {
            if (element == null)
            {
                return;
            }

            SvgRenderingHint hint = element.RenderingHint;

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

            #region Clip with clip
            // see http://www.w3.org/TR/SVG/masking.html#OverflowAndClipProperties
            if (element is ISvgSvgElement    || element is ISvgMarkerElement ||
                element is ISvgSymbolElement || element is ISvgPatternElement)
            {
                // check overflow property
                CssValue overflow = ((SvgElement)element).GetComputedCssValue("overflow", String.Empty) as CssValue;
                // TODO: clip can have "rect(10 10 auto 10)"
                CssPrimitiveValue clip = ((SvgElement)element).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 (element is ISvgSvgElement)
                            {
                                ISvgSvgElement svgElement = (ISvgSvgElement)element;
                                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 (element is ISvgSvgElement)
                            {
                                ISvgSvgElement svgElement = (ISvgSvgElement)element;
                                SvgRect viewPort = svgElement.Viewport as SvgRect;
                                clipRect = GdiConverter.ToRectangle(viewPort);
                            }
                            else if (element is ISvgMarkerElement ||
                              element is ISvgSymbolElement ||
                              element is ISvgPatternElement)
                            {
                                // TODO: what to do here?
                            }
                        }
                        if (clipRect != RectangleF.Empty)
                        {
                            gr.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)
            {
                CssPrimitiveValue clipPath = ((SvgElement)element).GetComputedCssValue("clip-path", String.Empty) as CssPrimitiveValue;

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

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

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

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

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

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

                        if (pathUnits == SvgUnitType.ObjectBoundingBox)
                        {
                            SvgTransformableElement transElement = element 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);
                                gr.SetClip(gpClip);

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

                        gpClip.Dispose();
                        gpClip = null;
                    }
                }
            }
            #endregion
        }
Beispiel #2
0
        protected void Clip(GdiGraphicsWrapper gr)
        {
            if (element == null)
            {
                return;
            }

            SvgRenderingHint hint = element.RenderingHint;

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

            #region Clip with clip
            // see http://www.w3.org/TR/SVG/masking.html#OverflowAndClipProperties
            if (element is ISvgSvgElement || element is ISvgMarkerElement ||
                element is ISvgSymbolElement || element is ISvgPatternElement)
            {
                // check overflow property
                CssValue overflow = ((SvgElement)element).GetComputedCssValue("overflow", String.Empty) as CssValue;
                // TODO: clip can have "rect(10 10 auto 10)"
                CssPrimitiveValue clip = ((SvgElement)element).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 (element is ISvgSvgElement)
                            {
                                ISvgSvgElement svgElement = (ISvgSvgElement)element;
                                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 (element is ISvgSvgElement)
                            {
                                ISvgSvgElement svgElement = (ISvgSvgElement)element;
                                SvgRect        viewPort   = svgElement.Viewport as SvgRect;
                                clipRect = GdiConverter.ToRectangle(viewPort);
                            }
                            else if (element is ISvgMarkerElement ||
                                     element is ISvgSymbolElement ||
                                     element is ISvgPatternElement)
                            {
                                // TODO: what to do here?
                            }
                        }
                        if (clipRect != RectangleF.Empty)
                        {
                            gr.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)
            {
                CssPrimitiveValue clipPath = ((SvgElement)element).GetComputedCssValue("clip-path", String.Empty) as CssPrimitiveValue;

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

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

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

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

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

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

                        if (pathUnits == SvgUnitType.ObjectBoundingBox)
                        {
                            SvgTransformableElement transElement = element 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);
                                gr.SetClip(gpClip);

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

                        gpClip.Dispose();
                        gpClip = null;
                    }
                }
            }
            #endregion
        }