public void TestCalcAngleBiSector() { Assert.AreEqual(135, SvgNumber.CalcAngleBisection(180, 90)); Assert.AreEqual(315, SvgNumber.CalcAngleBisection(90, 180)); Assert.AreEqual(185, SvgNumber.CalcAngleBisection(280, 90)); Assert.AreEqual(185, SvgNumber.CalcAngleBisection(0, 370)); }
private GradientStopCollection GetGradientStops(XmlNodeList stops) { int itemCount = stops.Count; GradientStopCollection gradientStops = new GradientStopCollection(itemCount); double lastOffset = 0; for (int i = 0; i < itemCount; i++) { SvgStopElement stop = (SvgStopElement)stops.Item(i); string prop = stop.GetAttribute("stop-color"); string style = stop.GetAttribute("style"); Color color = Colors.Transparent; // no auto-inherited... if (!String.IsNullOrEmpty(prop) || !String.IsNullOrEmpty(style)) { WpfSvgColor svgColor = new WpfSvgColor(stop, "stop-color"); color = svgColor.Color; } else { color = Colors.Black; // the default color... double alpha = 255; string opacity; opacity = stop.GetAttribute("stop-opacity"); // no auto-inherit if (opacity == "inherit") // if explicitly defined... { opacity = stop.GetPropertyValue("stop-opacity"); } if (opacity != null && opacity.Length > 0) { alpha *= SvgNumber.ParseNumber(opacity); } alpha = Math.Min(alpha, 255); alpha = Math.Max(alpha, 0); color = Color.FromArgb((byte)Convert.ToInt32(alpha), color.R, color.G, color.B); } double offset = stop.Offset.AnimVal; offset /= 100; offset = Math.Max(lastOffset, offset); gradientStops.Add(new GradientStop(color, offset)); lastOffset = offset; } if (itemCount == 0) { gradientStops.Add(new GradientStop(Colors.Black, 0)); gradientStops.Add(new GradientStop(Colors.Black, 1)); } return(gradientStops); }
private Tuple <string, ICssValue> ParseValue(string name, string value, string priority, bool presentation) { var important = priority == "important"; if (!presentation) { name = name.ToLower(); } ICssValue parsedValue = null; switch (name) { case "fill": case "stroke": parsedValue = new SvgPaint(value); break; case "stroke-width": parsedValue = SvgLength.Parse(value, presentation); break; case "stop-color": parsedValue = new SvgColor(value); break; case "fill-opacity": case "stroke-opacity": case "stop-opacity": case "opacity": parsedValue = SvgNumber.Parse(value, 0.0F, 1.0F); break; case "clip-path": parsedValue = new SvgIri(value); break; case "fill-rule": case "clip-rule": parsedValue = new SvgFillRule(presentation ? value : value.ToLower()); break; } if (!this._cache.ContainsKey(name)) { var result = Tuple.Create(value, parsedValue); this._cache.Add(name, result); return(result); } else if (important) { var result = Tuple.Create(value, parsedValue); this._cache[name] = result; return(result); } return(null); }
public override void Render(ISvgRenderer renderer) { GraphicsWrapper graphics = ((GdiRenderer)renderer).GraphicsWrapper; SvgImageElement iElement = (SvgImageElement)element; //HttpResource resource = iElement.ReferencedResource; /*if (resource != null ) * {*/ ImageAttributes imageAttributes = new ImageAttributes(); string sOpacity = iElement.GetPropertyValue("opacity"); if (sOpacity.Length > 0) { double opacity = SvgNumber.ParseToFloat(sOpacity); ColorMatrix myColorMatrix = new ColorMatrix(); myColorMatrix.Matrix00 = 1.00f; // Red myColorMatrix.Matrix11 = 1.00f; // Green myColorMatrix.Matrix22 = 1.00f; // Blue myColorMatrix.Matrix33 = (float)opacity; // alpha myColorMatrix.Matrix44 = 1.00f; // w imageAttributes.SetColorMatrix(myColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); } float width = (float)iElement.Width.AnimVal.Value; float height = (float)iElement.Height.AnimVal.Value; Rectangle destRect = new Rectangle(); destRect.X = Convert.ToInt32(iElement.X.AnimVal.Value); destRect.Y = Convert.ToInt32(iElement.Y.AnimVal.Value); destRect.Width = Convert.ToInt32(width); destRect.Height = Convert.ToInt32(height); Image image; if (iElement.IsSvgImage) { SvgWindow wnd = getSvgWindow(); gdiRenderer.BackColor = Color.Empty; gdiRenderer.Render(wnd.Document as SvgDocument); //wnd.Render(); image = gdiRenderer.RasterImage; image.Save(@"c:\inlinesvg.png", ImageFormat.Png); } else { image = iElement.Bitmap; } if (image != null) { graphics.DrawImage(this, image, destRect, 0f, 0f, image.Width, image.Height, GraphicsUnit.Pixel, imageAttributes); } //} }
public static GradientStopCollection ToGradientStops(System.Xml.XmlNodeList stops) { int itemCount = stops.Count; GradientStopCollection gradientStops = new GradientStopCollection(itemCount); double lastOffset = 0; for (int i = 0; i < itemCount; i++) { SvgStopElement stop = (SvgStopElement)stops.Item(i); string prop = stop.GetAttribute("stop-color"); string style = stop.GetAttribute("style"); Color color = Colors.Transparent; // no auto-inherited... if (!string.IsNullOrWhiteSpace(prop) || !string.IsNullOrWhiteSpace(style)) { SvgColor svgColor = new SvgColor(stop.GetComputedStyle(string.Empty).GetPropertyValue("stop-color")); if (svgColor.ColorType == SvgColorType.CurrentColor) { string sCurColor = stop.GetComputedStyle(string.Empty).GetPropertyValue(CssConstants.PropColor); svgColor = new SvgColor(sCurColor); } TryConvertColor(svgColor.RgbColor, out color); } else { color = Colors.Black; // the default color... } double alpha = 255; string opacity; opacity = stop.GetAttribute("stop-opacity"); // no auto-inherit if (opacity == "inherit") // if explicitly defined... { opacity = stop.GetPropertyValue("stop-opacity"); } if (!string.IsNullOrWhiteSpace(opacity)) { alpha *= SvgNumber.ParseNumber(opacity); } alpha = Math.Min(alpha, 255); alpha = Math.Max(alpha, 0); color = Color.FromArgb((byte)Convert.ToInt32(alpha), color.R, color.G, color.B); double offset = stop.Offset.AnimVal; offset /= 100; offset = Math.Max(lastOffset, offset); gradientStops.Add(new GradientStop(color, offset)); lastOffset = offset; } return(gradientStops); }
private void RenderTSpanPath(SvgTSpanElement element, WpfPathTextBuilder pathBuilder, ref Point ctp) { WpfTextPlacement placement = WpfTextPlacement.Create(element, ctp, true); ctp = placement.Location; double rotate = placement.Rotation; if (!placement.HasPositions) { placement = null; // Render it useless. } string sBaselineShift = element.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; var comparer = StringComparison.OrdinalIgnoreCase; if (sBaselineShift.Length > 0) { SvgTextBaseElement textElement = (SvgTextBaseElement)element.SelectSingleNode("ancestor::svg:text", element.OwnerDocument.NamespaceManager); double textFontSize = GetComputedFontSize(textElement); if (sBaselineShift.EndsWith("%", comparer)) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100f * textFontSize; } else if (string.Equals(sBaselineShift, "sub", comparer)) { shiftBy = -0.6F * textFontSize; } else if (string.Equals(sBaselineShift, "super", comparer)) { shiftBy = 0.6F * textFontSize; } else if (string.Equals(sBaselineShift, "baseline", comparer)) { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } foreach (XmlNode child in element.ChildNodes) { if (child.NodeType == XmlNodeType.Text) { ctp.Y -= shiftBy; RenderTextPath(element, pathBuilder, GetText(element, child), new Point(ctp.X, ctp.Y), rotate, placement); ctp.Y += shiftBy; } } }
private void RenderTSpanPath(SvgTSpanElement element, WpfTextOnPathDrawing pathDrawing, ref Point ctp) { WpfTextPlacement placement = GetCurrentTextPosition(element, ctp); ctp = placement.Location; double rotate = placement.Rotation; if (!placement.HasPositions) { placement = null; // Render it useless. } string sBaselineShift = element.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; if (sBaselineShift.Length > 0) { SvgTextElement textElement = (SvgTextElement)element.SelectSingleNode("ancestor::svg:text", element.OwnerDocument.NamespaceManager); double textFontSize = GetComputedFontSize(textElement); if (sBaselineShift.EndsWith("%")) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100f * textFontSize; } else if (sBaselineShift == "sub") { shiftBy = -0.6F * textFontSize; } else if (sBaselineShift == "super") { shiftBy = 0.6F * textFontSize; } else if (sBaselineShift == "baseline") { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } foreach (XmlNode child in element.ChildNodes) { if (child.NodeType == XmlNodeType.Text) { ctp.Y -= shiftBy; RenderTextPath(element, pathDrawing, GetText(element, child), new Point(ctp.X, ctp.Y), rotate, placement); ctp.Y += shiftBy; } } }
private void diffAndBisectTest(SvgPathSegList list, int startSeg, float expectedDiff, float expectedBisect) { float diff = SvgNumber.CalcAngleDiff(((SvgPathSeg)list[startSeg]).EndAngle, ((SvgPathSeg)list[startSeg + 1]).StartAngle); float bisect = SvgNumber.CalcAngleBisection(((SvgPathSeg)list[startSeg]).EndAngle, ((SvgPathSeg)list[startSeg + 1]).StartAngle); string label = startSeg + "-" + (startSeg + 1); floatsTest(label + " diff", expectedDiff, diff); floatsTest(label + " bisect", expectedBisect, bisect); }
private Color?GetNodeColor(ISvgElement targetNode, string property) { //StyleColor fillColor = new StyleColor(); //fillColor.FillType = ColorFillType.Solid; string szRGB = null; string szOpacity = null; string szNodeopacity = null; if (targetNode.RenderingHint == SvgRenderingHint.Text || targetNode.RenderingHint == SvgRenderingHint.Shape) { szRGB = (targetNode as SvgElement).GetComputedStyle("").GetPropertyValue(property); szOpacity = (targetNode as SvgElement).GetComputedStyle("").GetPropertyValue(property + @"-opacity"); szNodeopacity = (targetNode as SvgElement).GetComputedStyle("").GetPropertyValue("opacity"); if (string.IsNullOrEmpty(szRGB)) { return(null); } } //Get RGB Color SvgPaint paint = new SvgPaint(szRGB); if (paint.RgbColor == null) { return(null); } Color?solidColor = WpfConvert.ToColor(paint.RgbColor); if (solidColor == null) { return(null); } //Get Aplha Color result = solidColor.Value; if (szNodeopacity != null || szOpacity != null) { double opacityValue = 1; if (szNodeopacity != null && szNodeopacity.Length > 0) { opacityValue *= SvgNumber.ParseNumber(szNodeopacity); } else if (szOpacity != null && szOpacity.Length > 0) { opacityValue *= SvgNumber.ParseNumber(szOpacity); } opacityValue = Math.Min(opacityValue, 1); opacityValue = Math.Max(opacityValue, 0); result.A = Convert.ToByte(opacityValue * 255); } return(result); }
public void TestCalcAngleDiff() { Assert.AreEqual(107, SvgNumber.CalcAngleDiff(197, 90)); Assert.AreEqual(287, SvgNumber.CalcAngleDiff(197, -90)); Assert.AreEqual(287, SvgNumber.CalcAngleDiff(197, 270)); Assert.AreEqual(186, SvgNumber.CalcAngleDiff(23, 197)); Assert.AreEqual(230, SvgNumber.CalcAngleDiff(230, 0)); Assert.AreEqual(0, SvgNumber.CalcAngleDiff(360, 0)); Assert.AreEqual(15, SvgNumber.CalcAngleDiff(375, 0)); Assert.AreEqual(345, SvgNumber.CalcAngleDiff(0, 375)); }
public override void Render(WpfDrawingRenderer renderer) { if (_drawGroup != null) { Geometry clipGeom = this.ClipGeometry; if (clipGeom != null) { _drawGroup.ClipGeometry = clipGeom; } Transform transform = this.Transform; if (transform != null) { _drawGroup.Transform = transform; } float opacityValue = -1; SvgGElement element = (SvgGElement)_svgElement; string opacity = element.GetAttribute("opacity"); if (string.IsNullOrWhiteSpace(opacity)) { opacity = element.GetPropertyValue("opacity"); } if (!string.IsNullOrWhiteSpace(opacity)) { opacityValue = (float)SvgNumber.ParseNumber(opacity); opacityValue = Math.Min(opacityValue, 1); opacityValue = Math.Max(opacityValue, 0); } if (opacityValue >= 0 && opacityValue < 1) { _drawGroup.Opacity = opacityValue; } string sVisibility = element.GetPropertyValue("visibility"); string sDisplay = element.GetPropertyValue("display"); if (string.Equals(sVisibility, "hidden") || string.Equals(sDisplay, "none")) { _drawGroup.Opacity = 0; } } // Register this drawing with the Drawing-Document... this.Rendered(_drawGroup); base.Render(renderer); }
private double GetMiterLimit(double strokeWidth) { // Use this to prevent the default value of "4" being used... string miterLimitAttr = _element.GetAttribute("stroke-miterlimit"); if (String.IsNullOrEmpty(miterLimitAttr)) { string strokeLinecap = _element.GetAttribute("stroke-linecap"); if (String.Equals(strokeLinecap, "round", StringComparison.OrdinalIgnoreCase)) { return(1.0d); } return(-1.0d); } string miterLimitStr = _element.GetPropertyValue("stroke-miterlimit"); if (String.IsNullOrEmpty(miterLimitStr) || (float)(strokeWidth) <= 0) { return(-1.0d); } double miterLimit = SvgNumber.ParseNumber(miterLimitStr); if (miterLimit < 1) { throw new SvgException(SvgExceptionType.SvgInvalidValueErr, "stroke-miterlimit can not be less then 1"); } //if (miterLimit < 1.0d) //{ // return -1.0d; //} double ratioLimit = miterLimit / strokeWidth; if (ratioLimit >= 1.8d) { return(miterLimit); } else { return(1.0d); } }
private void AddTSpanElementPath(SvgTSpanElement element, ref PointF ctp) { ctp = GetCurrentTextPosition(element, ctp); string sBaselineShift = element.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; if (sBaselineShift.Length > 0) { SvgTextBaseElement textElement = (SvgTextBaseElement)element.SelectSingleNode("ancestor::svg:text", element.OwnerDocument.NamespaceManager); float textFontSize = GetComputedFontSize(textElement); if (sBaselineShift.EndsWith("%", StringComparison.OrdinalIgnoreCase)) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100 * textFontSize; } else if (sBaselineShift == "sub") { shiftBy = -0.6F * textFontSize; } else if (sBaselineShift == "super") { shiftBy = 0.6F * textFontSize; } else if (sBaselineShift == "baseline") { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } foreach (XmlNode child in element.ChildNodes) { if (child.NodeType == XmlNodeType.Text) { ctp.Y -= (float)shiftBy; AddGraphicsPath(element, ref ctp, GetText(element, child)); ctp.Y += (float)shiftBy; } } }
private float GetMiterLimit() { string miterLimitStr = _element.GetPropertyValue("stroke-miterlimit"); if (miterLimitStr.Length == 0) { miterLimitStr = "4"; } float miterLimit = (float)SvgNumber.ParseNumber(miterLimitStr); if (miterLimit < 1) { throw new SvgException(SvgExceptionType.SvgInvalidValueErr, "stroke-miterlimit can not be less then 1"); } return(miterLimit); }
public static double GetOpacity(SvgStyleableElement element, string fillOrStroke) { double opacityValue = 1; string opacity = element.GetPropertyValue(fillOrStroke + "-opacity"); if (opacity != null && opacity.Length > 0) { opacityValue *= SvgNumber.ParseNumber(opacity); } opacity = element.GetPropertyValue("opacity"); if (opacity != null && opacity.Length > 0) { opacityValue *= SvgNumber.ParseNumber(opacity); } opacityValue = Math.Min(opacityValue, 1); opacityValue = Math.Max(opacityValue, 0); return(opacityValue); }
private double GetOpacity(string fillOrStroke) { double opacityValue = 1; string opacity = _element.GetPropertyValue(fillOrStroke + "-opacity"); if (opacity != null && opacity.Length > 0) { opacityValue *= SvgNumber.ParseNumber(opacity); } opacity = _element.GetPropertyValue("opacity"); if (opacity != null && opacity.Length > 0) { opacityValue *= SvgNumber.ParseNumber(opacity); } opacityValue = Math.Min(opacityValue, 1); opacityValue = Math.Max(opacityValue, 0); return(opacityValue); }
private double GetOpacity(string fillOrStroke) { double opacityValue = 1; string opacity = _element.GetPropertyValue(fillOrStroke + "-opacity"); if (!string.IsNullOrWhiteSpace(opacity)) { opacityValue *= SvgNumber.ParseNumber(opacity); } opacity = _element.GetPropertyValue("opacity"); if (!string.IsNullOrWhiteSpace(opacity)) { opacityValue *= SvgNumber.ParseNumber(opacity); } opacityValue = Math.Min(opacityValue, 1); opacityValue = Math.Max(opacityValue, 0); return(opacityValue); }
private int GetOpacity(string fillOrStroke) { double alpha = 255; string opacity; opacity = _element.GetPropertyValue(fillOrStroke + "-opacity"); if (opacity.Length > 0) { alpha *= SvgNumber.ParseNumber(opacity); } opacity = _element.GetPropertyValue("opacity"); if (opacity.Length > 0) { alpha *= SvgNumber.ParseNumber(opacity); } alpha = Math.Min(alpha, 255); alpha = Math.Max(alpha, 0); return(Convert.ToInt32(alpha)); }
public static bool TryGetMiterLimit(SvgStyleableElement element, double strokeWidth, out double miterLimit) { string miterLimitAttr = element.GetAttribute("stroke-miterlimit"); if (string.IsNullOrWhiteSpace(miterLimitAttr)) { string strokeLinecap = element.GetAttribute("stroke-linecap"); if (string.Equals(strokeLinecap, "round", StringComparison.OrdinalIgnoreCase)) { miterLimit = 1.0d; return(true); } miterLimit = -1.0d; return(false); } string miterLimitStr = element.GetPropertyValue("stroke-miterlimit"); if (string.IsNullOrWhiteSpace(miterLimitStr) || strokeWidth <= 0) { miterLimit = -1.0d; return(false); } miterLimit = SvgNumber.ParseNumber(miterLimitStr); if (miterLimit < 1) { return(false); } double ratioLimit = miterLimit / strokeWidth; if (ratioLimit < 1.8d) { miterLimit = 1.0d; } return(true); }
public void RenderMarker(WpfDrawingRenderer renderer, WpfDrawingContext gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgPointF[] vertexPositions = markerHostElm.MarkerPositions; int start = 0; int len = 0; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } int end = start + len; TransformGroup transform = new TransformGroup(); for (int i = start; i < end; i++) { SvgPointF point = vertexPositions[i]; //GdiGraphicsContainer gc = gr.BeginContainer(); this.BeforeRender(renderer); //Matrix matrix = Matrix.Identity; Matrix matrix = GetTransformMatrix(_svgElement, transform); ISvgAnimatedEnumeration orientType = _markerElement.OrientType; if (orientType.AnimVal.Equals((ushort)SvgMarkerOrient.Angle)) { double scaleValue = _markerElement.OrientAngle.AnimVal.Value; if (!scaleValue.Equals(0)) { matrix.Rotate(scaleValue); transform.Children.Add(new RotateTransform(scaleValue)); } } else { bool isAutoReverse = orientType.AnimVal.Equals((ushort)SvgMarkerOrient.AutoStartReverse); double angle = 0; switch (markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i); //angle = markerHostElm.GetStartAngle(i + 1); if (vertexPositions.Length >= 2) { SvgPointF pMarkerPoint1 = vertexPositions[start]; SvgPointF pMarkerPoint2 = vertexPositions[end]; float xDiff = pMarkerPoint2.X - pMarkerPoint1.X; float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y; double angleMarker = (float)(Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI); if (!angleMarker.Equals(angle)) { angle = angleMarker; } } // A value of 'auto-start-reverse' means the same as 'auto' except that for a // marker placed by 'marker-start', the orientation is 180° different from // the orientation as determined by 'auto'. if (isAutoReverse) { angle += 180; } break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i - 1); //angle = markerHostElm.GetEndAngle(i); if (vertexPositions.Length >= 2) { SvgPointF pMarkerPoint1 = vertexPositions[start - 1]; SvgPointF pMarkerPoint2 = vertexPositions[start]; float xDiff = pMarkerPoint2.X - pMarkerPoint1.X; float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y; double angleMarker = (float)(Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI); if (!angleMarker.Equals(angle)) { angle = angleMarker; } } break; } matrix.Rotate(angle); transform.Children.Add(new RotateTransform(angle)); } // 'viewBox' and 'preserveAspectRatio' attributes // viewBox -> viewport(0, 0, markerWidth, markerHeight) SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)_markerElement.PreserveAspectRatio.AnimVal; double[] translateAndScale = spar.FitToViewBox((SvgRect)_markerElement.ViewBox.AnimVal, new SvgRect(0, 0, _markerElement.MarkerWidth.AnimVal.Value, _markerElement.MarkerHeight.AnimVal.Value)); // Warning at this time, refX and refY are relative to the painted element's coordinate system. // We need to move the reference point to the marker's coordinate system double refX = _markerElement.RefX.AnimVal.Value; double refY = _markerElement.RefY.AnimVal.Value; if (!(refX.Equals(0) && refY.Equals(0))) { var ptRef = matrix.Transform(new Point(refX, refY)); refX = ptRef.X; refY = ptRef.Y; matrix.Translate(-refX, -refY); transform.Children.Add(new TranslateTransform(-refX, -refY)); } //matrix.Translate(-markerElm.RefX.AnimVal.Value * translateAndScale[2], // -markerElm.RefY.AnimVal.Value * translateAndScale[3]); //transform.Children.Add(new TranslateTransform(-markerElm.RefX.AnimVal.Value * translateAndScale[2], // -markerElm.RefY.AnimVal.Value * translateAndScale[3])); // compute an additional transform for 'strokeWidth' coordinate system ISvgAnimatedEnumeration markerUnits = _markerElement.MarkerUnits; if (markerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { SvgLength strokeWidthLength = new SvgLength(refElement, "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, "1"); double strokeWidth = strokeWidthLength.Value; if (!strokeWidth.Equals(1)) { matrix.Scale(strokeWidth, strokeWidth); transform.Children.Add(new ScaleTransform(strokeWidth, strokeWidth)); } } if (!(translateAndScale[2].Equals(1) && translateAndScale[3].Equals(1))) { matrix.Scale(translateAndScale[2], translateAndScale[3]); transform.Children.Add(new ScaleTransform(translateAndScale[2], translateAndScale[3])); } matrix.Translate(point.X, point.Y); transform.Children.Add(new TranslateTransform(point.X, point.Y)); _matrix = matrix; this.Transform = transform; this.Render(renderer); //Clip(gr); renderer.RenderChildren(_markerElement); //gr.EndContainer(gc); this.AfterRender(renderer); } }
public override void Render(WpfDrawingRenderer renderer) { Geometry clipGeom = this.ClipGeometry; Transform transform = this.Transform; WpfDrawingContext context = renderer.Context; SvgSwitchElement switchElement = (SvgSwitchElement)_svgElement; string elementId = this.GetElementName(); float opacityValue = -1; string opacity = switchElement.GetAttribute("opacity"); if (string.IsNullOrWhiteSpace(opacity)) { opacity = switchElement.GetPropertyValue("opacity"); } if (!string.IsNullOrWhiteSpace(opacity)) { opacityValue = (float)SvgNumber.ParseNumber(opacity); opacityValue = Math.Min(opacityValue, 1); opacityValue = Math.Max(opacityValue, 0); } if (clipGeom != null || transform != null || (opacityValue >= 0 && opacityValue < 1) || (!string.IsNullOrWhiteSpace(elementId) && !context.IsRegisteredId(elementId))) { _drawGroup = new DrawingGroup(); DrawingGroup currentGroup = context.Peek(); if (currentGroup == null) { throw new InvalidOperationException("An existing group is expected."); } currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); if (clipGeom != null) { _drawGroup.ClipGeometry = clipGeom; } if (transform != null) { _drawGroup.Transform = transform; } if (opacityValue >= 0 && opacityValue < 1) { _drawGroup.Opacity = opacityValue; } if (!string.IsNullOrWhiteSpace(elementId) && !context.IsRegisteredId(elementId)) { SvgObject.SetName(_drawGroup, elementId); context.RegisterId(elementId); if (context.IncludeRuntime) { SvgObject.SetId(_drawGroup, elementId); } } } base.Render(renderer); }
private double[] FitToViewBox(SvgPreserveAspectRatioType alignment, SvgRect viewBox, SvgRect rectToFit) { double translateX = 0; double translateY = 0; double scaleX = 1; double scaleY = 1; if (!viewBox.IsEmpty) { // calculate scale values for non-uniform scaling scaleX = rectToFit.Width / viewBox.Width; scaleY = rectToFit.Height / viewBox.Height; if (alignment != SvgPreserveAspectRatioType.None) { // uniform scaling scaleX = Math.Max(scaleX, scaleY); scaleY = scaleX; if (alignment == SvgPreserveAspectRatioType.XMidYMax || alignment == SvgPreserveAspectRatioType.XMidYMid || alignment == SvgPreserveAspectRatioType.XMidYMin) { // align to the Middle X translateX = (rectToFit.X + rectToFit.Width / 2) - scaleX * (viewBox.X + viewBox.Width / 2); } else if (alignment == SvgPreserveAspectRatioType.XMaxYMax || alignment == SvgPreserveAspectRatioType.XMaxYMid || alignment == SvgPreserveAspectRatioType.XMaxYMin) { // align to the right X translateX = (rectToFit.Width - viewBox.Width * scaleX); } if (alignment == SvgPreserveAspectRatioType.XMaxYMid || alignment == SvgPreserveAspectRatioType.XMidYMid || alignment == SvgPreserveAspectRatioType.XMinYMid) { // align to the Middle Y translateY = (rectToFit.Y + rectToFit.Height / 2) - scaleY * (viewBox.Y + viewBox.Height / 2); } else if (alignment == SvgPreserveAspectRatioType.XMaxYMax || alignment == SvgPreserveAspectRatioType.XMidYMax || alignment == SvgPreserveAspectRatioType.XMinYMax) { // align to the bottom Y translateY = (rectToFit.Height - viewBox.Height * scaleY); } } else { translateX = -viewBox.X * scaleX; translateY = -viewBox.Y * scaleY; } } if (!SvgNumber.IsValid(translateX)) { translateX = 0; } if (!SvgNumber.IsValid(translateY)) { translateY = 0; } if (!SvgNumber.IsValid(scaleX)) { scaleX = 1; } if (!SvgNumber.IsValid(scaleY)) { scaleY = 1; } return(new double[] { translateX, translateY, scaleX, scaleY }); }
private void AddTSpanElementRun(SvgTSpanElement element, ref Point ctp, bool isVertical, bool isSingleLine) { WpfTextPlacement placement = WpfTextRenderer.GetCurrentTextPosition(element, ctp); ctp = placement.Location; double rotate = placement.Rotation; if (!placement.HasPositions) { placement = null; // render it useless } string sBaselineShift = element.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; if (sBaselineShift.Length > 0) { double textFontSize = WpfTextRenderer.GetComputedFontSize(_textElement); if (sBaselineShift.EndsWith("%", StringComparison.OrdinalIgnoreCase)) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100f * textFontSize; } else if (sBaselineShift == "sub") { shiftBy = -0.6F * textFontSize; } else if (sBaselineShift == "super") { shiftBy = 0.6F * textFontSize; } else if (sBaselineShift == "baseline") { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } foreach (XmlNode child in element.ChildNodes) { if (child.NodeType == XmlNodeType.Text) { if (isVertical) { ctp.X += shiftBy; if (isSingleLine) { RenderSingleLineTextV(element, ref ctp, WpfTextRenderer.GetText(element, child), rotate, placement); } else { RenderTextRunV(element, ref ctp, WpfTextRenderer.GetText(element, child), rotate, placement); } ctp.X -= shiftBy; } else { ctp.Y -= shiftBy; if (isSingleLine) { RenderSingleLineTextH(element, ref ctp, WpfTextRenderer.GetText(element, child), rotate, placement); } else { RenderTextRunH(element, ref ctp, WpfTextRenderer.GetText(element, child), rotate, placement); } ctp.Y += shiftBy; } } } }
public override void Render(WpfDrawingRenderer renderer) { if (_drawGroup == null || _drawContext == null) { return; } Point ctp = new Point(0, 0); // current text position WpfTextPlacement placement = WpfTextRenderer.GetCurrentTextPosition(_textElement, ctp); ctp = placement.Location; double rotate = placement.Rotation; if (!placement.HasPositions) { placement = null; // render it useless } string sBaselineShift = _textElement.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; if (sBaselineShift.Length > 0) { double textFontSize = WpfTextRenderer.GetComputedFontSize(_textElement); if (sBaselineShift.EndsWith("%", StringComparison.OrdinalIgnoreCase)) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100 * textFontSize; } else if (sBaselineShift == "sub") { shiftBy = -0.6F * textFontSize; } else if (sBaselineShift == "super") { shiftBy = 0.6F * textFontSize; } else if (sBaselineShift == "baseline") { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } XmlNodeType nodeType = XmlNodeType.None; bool isVertical = false; string writingMode = _textElement.GetPropertyValue("writing-mode"); if (!string.IsNullOrWhiteSpace(writingMode) && string.Equals(writingMode, "tb", StringComparison.OrdinalIgnoreCase)) { isVertical = true; } if (_svgElement.ChildNodes.Count == 1) { XmlNode child = _svgElement.ChildNodes[0]; nodeType = child.NodeType; if (nodeType == XmlNodeType.Text || nodeType == XmlNodeType.CDATA) { if (isVertical) { ctp.X -= shiftBy; RenderSingleLineTextV(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderSingleLineTextH(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.Y += shiftBy; } } else if (nodeType == XmlNodeType.Element) { string nodeName = child.Name; if (string.Equals(nodeName, "tref")) { AddTRefElementRun((SvgTRefElement)child, ref ctp, isVertical, true); } else if (string.Equals(nodeName, "tspan")) { AddTSpanElementRun((SvgTSpanElement)child, ref ctp, isVertical, true); } else if (string.Equals(nodeName, "textPath")) { RenderTextPath((SvgTextPathElement)child, ref ctp, rotate, placement); } } else if (nodeType == XmlNodeType.Whitespace) { if (isVertical) { ctp.X -= shiftBy; RenderSingleLineTextV(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderSingleLineTextH(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.Y += shiftBy; } } } else { string textAnchor = _textElement.GetPropertyValue("text-anchor"); WpfTextAnchor anchor = WpfTextAnchor.None; if (textAnchor == "middle") { anchor = WpfTextAnchor.Middle; } else if (textAnchor == "end") { anchor = WpfTextAnchor.End; } XmlNodeList nodeList = _svgElement.ChildNodes; // This is a very simply hack to change centered text to left align, since for // text containing spans, different font weights may be applied to the spans... if (anchor == WpfTextAnchor.Middle) { // Suspend the rendering... _isMeasuring = true; foreach (XmlNode child in nodeList) { nodeType = child.NodeType; if (nodeType == XmlNodeType.Text) { if (isVertical) { ctp.X -= shiftBy; RenderTextRunV(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderTextRunH(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.Y += shiftBy; } } else if (nodeType == XmlNodeType.Element) { string nodeName = child.Name; if (string.Equals(nodeName, "tref")) { AddTRefElementRun((SvgTRefElement)child, ref ctp, isVertical, false); } else if (string.Equals(nodeName, "tspan")) { AddTSpanElementRun((SvgTSpanElement)child, ref ctp, isVertical, false); } else if (string.Equals(nodeName, "textPath")) { RenderTextPath((SvgTextPathElement)child, ref ctp, rotate, placement); } } else if (nodeType == XmlNodeType.Whitespace) { if (isVertical) { ctp.X -= shiftBy; //RenderTextRunV(_textElement, ref ctp, GetText(_textElement, child)); RenderTextRunV(_textElement, ref ctp, Whitespace, rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; //RenderTextRunH(_textElement, ref ctp, GetText(_textElement, child)); RenderTextRunH(_textElement, ref ctp, Whitespace, rotate, placement); ctp.Y += shiftBy; } } } ctp.X -= (_textWidth / 2d); // Resume the rendering... _isMeasuring = false; } bool textRendered = false; for (int i = 0; i < nodeList.Count; i++) { XmlNode child = nodeList[i]; nodeType = child.NodeType; if (nodeType == XmlNodeType.Text) { if (isVertical) { ctp.X -= shiftBy; RenderTextRunV(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderTextRunH(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.Y += shiftBy; } textRendered = true; } else if (nodeType == XmlNodeType.Element) { string nodeName = child.Name; if (string.Equals(nodeName, "tref")) { AddTRefElementRun((SvgTRefElement)child, ref ctp, isVertical, false); textRendered = true; } else if (string.Equals(nodeName, "tspan")) { AddTSpanElementRun((SvgTSpanElement)child, ref ctp, isVertical, false); textRendered = true; } else if (string.Equals(nodeName, "textPath")) { RenderTextPath((SvgTextPathElement)child, ref ctp, rotate, placement); textRendered = false; } } else if (nodeType == XmlNodeType.Whitespace) { if (textRendered) { if (isVertical) { ctp.X -= shiftBy; //RenderTextRunV(_textElement, ref ctp, GetText(_textElement, child)); RenderTextRunV(_textElement, ref ctp, Whitespace, rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; //RenderTextRunH(_textElement, ref ctp, GetText(_textElement, child)); RenderTextRunH(_textElement, ref ctp, Whitespace, rotate, placement); ctp.Y += shiftBy; } textRendered = false; } } } } }
private void AddTSpanElementRun(SvgTSpanElement element, ref Point ctp, bool isVertical, bool isSingleLine, XmlNode spaceNode = null) { var nodeList = element.ChildNodes; int nodeCount = nodeList.Count; if (nodeCount == 0) { return; } _textContext.PositioningElement = element; _textContext.PositioningStart = new Point(ctp.X, ctp.Y); WpfTextPlacement placement = WpfTextPlacement.Create(element, ctp); ctp = placement.Location; double rotate = placement.Rotation; if (!placement.HasPositions) { placement = null; // render it useless } _textContext.PositioningEnd = new Point(ctp.X, ctp.Y); var comparer = StringComparison.OrdinalIgnoreCase; string sBaselineShift = element.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; if (sBaselineShift.Length > 0) { double textFontSize = WpfTextRenderer.GetComputedFontSize(_textElement); if (sBaselineShift.EndsWith("%", comparer)) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100f * textFontSize; } else if (string.Equals(sBaselineShift, "sub", comparer)) { shiftBy = -0.6F * textFontSize; } else if (string.Equals(sBaselineShift, "super", comparer)) { shiftBy = 0.6F * textFontSize; } else if (string.Equals(sBaselineShift, "baseline", comparer)) { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } for (int i = 0; i < nodeCount; i++) { XmlNode child = nodeList[i]; if (child.NodeType == XmlNodeType.Text) { if (isVertical) { ctp.X += shiftBy; if (isSingleLine) { if (i == (nodeCount - 1) && spaceNode != null) { RenderSingleLineTextV(element, ref ctp, WpfTextRenderer.GetText(element, child, spaceNode), rotate, placement); } else { RenderSingleLineTextV(element, ref ctp, WpfTextRenderer.GetText(element, child), rotate, placement); } } else { if (i == (nodeCount - 1) && spaceNode != null) { RenderTextRunV(element, ref ctp, WpfTextRenderer.GetText(element, child, spaceNode), rotate, placement); } else { RenderTextRunV(element, ref ctp, WpfTextRenderer.GetText(element, child), rotate, placement); } } ctp.X -= shiftBy; } else { ctp.Y -= shiftBy; if (isSingleLine) { if (i == (nodeCount - 1) && spaceNode != null) { RenderSingleLineTextH(element, ref ctp, WpfTextRenderer.GetText(element, child, spaceNode), rotate, placement); } else { RenderSingleLineTextH(element, ref ctp, WpfTextRenderer.GetText(element, child), rotate, placement); } } else { if (i == (nodeCount - 1) && spaceNode != null) { RenderTextRunH(element, ref ctp, WpfTextRenderer.GetText(element, child, spaceNode), rotate, placement); } else { RenderTextRunH(element, ref ctp, WpfTextRenderer.GetText(element, child), rotate, placement); } } ctp.Y += shiftBy; } } } }
public void RenderMarker2(WpfDrawingRenderer renderer, WpfDrawingContext gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgMarkerElement markerElm = (SvgMarkerElement)_svgElement; SvgPointF[] vertexPositions = markerHostElm.MarkerPositions; int start; int len; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } for (int i = start; i < start + len; i++) { SvgPointF point = vertexPositions[i]; //GdiGraphicsContainer gc = gr.BeginContainer(); this.BeforeRender(renderer); //Matrix matrix = Matrix.Identity; Matrix matrix = GetTransformMatrix(_svgElement); if (markerElm.OrientType.AnimVal.Equals((ushort)SvgMarkerOrient.Angle)) { matrix.Rotate(markerElm.OrientAngle.AnimVal.Value); } else { double angle = 0; switch (markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i + 1); break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i); break; } matrix.Rotate(angle); } if (markerElm.MarkerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { SvgLength strokeWidthLength = new SvgLength(refElement, "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, "1"); double strokeWidth = strokeWidthLength.Value; matrix.Scale(strokeWidth, strokeWidth); } SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)markerElm.PreserveAspectRatio.AnimVal; double[] translateAndScale = spar.FitToViewBox((SvgRect)markerElm.ViewBox.AnimVal, new SvgRect(0, 0, markerElm.MarkerWidth.AnimVal.Value, markerElm.MarkerHeight.AnimVal.Value)); matrix.Translate(-markerElm.RefX.AnimVal.Value * translateAndScale[2], -markerElm.RefY.AnimVal.Value * translateAndScale[3]); matrix.Scale(translateAndScale[2], translateAndScale[3]); matrix.Translate(point.X, point.Y); _matrix = matrix; this.Render(renderer); //Clip(gr); renderer.RenderChildren(markerElm); //gr.EndContainer(gc); this.AfterRender(renderer); } }
public override void Render(WpfDrawingRenderer renderer) { WpfDrawingContext context = renderer.Context; SvgImageElement imageElement = (SvgImageElement)_svgElement; double x = imageElement.X.AnimVal.Value; double y = imageElement.Y.AnimVal.Value; double width = imageElement.Width.AnimVal.Value; double height = imageElement.Height.AnimVal.Value; Rect destRect = new Rect(x, y, width, height); Rect clipRect = new Rect(x, y, width, height); ImageSource imageSource = null; if (imageElement.IsSvgImage) { if (imageElement.IsRootReferenced(imageElement.OwnerDocument.BaseURI)) { return; } SvgWindow wnd = GetSvgWindow(); if (wnd == null) { return; } //_embeddedRenderer.BackColor = Color.Empty; _embeddedRenderer.Render(wnd.Document); DrawingGroup imageGroup = _embeddedRenderer.Drawing as DrawingGroup; if (imageGroup != null && (imageGroup.Children != null && imageGroup.Children.Count == 1)) { DrawingGroup imageDrawing = imageGroup.Children[0] as DrawingGroup; if (imageDrawing != null) { imageDrawing.ClipGeometry = null; imageSource = new DrawingImage(imageDrawing); } else { imageGroup.ClipGeometry = null; imageSource = new DrawingImage(imageGroup); } } else { imageSource = new DrawingImage(_embeddedRenderer.Drawing); } if (_embeddedRenderer != null) { _embeddedRenderer.Dispose(); _embeddedRenderer = null; } } else { imageSource = GetBitmapSource(imageElement, context); } if (imageSource == null) { return; } //TODO--PAUL: Set the DecodePixelWidth/DecodePixelHeight? // Freeze the DrawingImage for performance benefits. //imageSource.Freeze(); DrawingGroup drawGroup = null; ISvgAnimatedPreserveAspectRatio animatedAspectRatio = imageElement.PreserveAspectRatio; if (animatedAspectRatio != null && animatedAspectRatio.AnimVal != null) { SvgPreserveAspectRatio aspectRatio = animatedAspectRatio.AnimVal as SvgPreserveAspectRatio; SvgPreserveAspectRatioType aspectRatioType = (aspectRatio != null) ? aspectRatio.Align : SvgPreserveAspectRatioType.Unknown; if (aspectRatio != null && aspectRatioType != SvgPreserveAspectRatioType.None && aspectRatioType != SvgPreserveAspectRatioType.Unknown) { double imageWidth = imageSource.Width; double imageHeight = imageSource.Height; double viewWidth = destRect.Width; double viewHeight = destRect.Height; SvgMeetOrSlice meetOrSlice = aspectRatio.MeetOrSlice; if (meetOrSlice == SvgMeetOrSlice.Meet) { if (imageWidth <= viewWidth && imageHeight <= viewHeight) { if (this.Transform == null) { if (!aspectRatio.IsDefaultAlign) // Cacxa { destRect = this.GetBounds(destRect, new Size(imageWidth, imageHeight), aspectRatioType); } else { Transform viewTransform = this.GetAspectRatioTransform(aspectRatio, new SvgRect(0, 0, imageWidth, imageHeight), new SvgRect(destRect.X, destRect.Y, destRect.Width, destRect.Height)); if (viewTransform != null) { drawGroup = new DrawingGroup(); drawGroup.Transform = viewTransform; DrawingGroup lastGroup = context.Peek(); Debug.Assert(lastGroup != null); if (lastGroup != null) { lastGroup.Children.Add(drawGroup); } destRect = this.GetBounds(destRect, new Size(imageWidth, imageHeight), aspectRatioType); // The origin is already handled by the view transform... destRect.X = 0; destRect.Y = 0; } } } else { destRect = new Rect(0, 0, viewWidth, viewHeight); } } else { if (this.Transform == null) { Transform viewTransform = this.GetAspectRatioTransform(aspectRatio, new SvgRect(0, 0, imageWidth, imageHeight), new SvgRect(destRect.X, destRect.Y, destRect.Width, destRect.Height)); if (viewTransform != null) { drawGroup = new DrawingGroup(); drawGroup.Transform = viewTransform; DrawingGroup lastGroup = context.Peek(); Debug.Assert(lastGroup != null); if (lastGroup != null) { lastGroup.Children.Add(drawGroup); } destRect = this.GetBounds(destRect, new Size(imageWidth, imageHeight), aspectRatioType); // The origin is already handled by the view transform... destRect.X = 0; destRect.Y = 0; } } } } else if (meetOrSlice == SvgMeetOrSlice.Slice) { var fScaleX = viewWidth / imageWidth; var fScaleY = viewHeight / imageHeight; Transform viewTransform = this.GetAspectRatioTransform(aspectRatio, new SvgRect(0, 0, imageWidth, imageHeight), new SvgRect(destRect.X, destRect.Y, destRect.Width, destRect.Height)); DrawingGroup sliceGroup = new DrawingGroup(); sliceGroup.ClipGeometry = new RectangleGeometry(clipRect); DrawingGroup lastGroup = context.Peek(); Debug.Assert(lastGroup != null); if (lastGroup != null) { lastGroup.Children.Add(sliceGroup); } if (viewTransform != null) { drawGroup = new DrawingGroup(); drawGroup.Transform = viewTransform; sliceGroup.Children.Add(drawGroup); destRect = this.GetBounds(destRect, new Size(imageWidth, imageHeight), aspectRatioType); // The origin is already handled by the view transform... destRect.X = 0; destRect.Y = 0; } else { drawGroup = sliceGroup; } } } } ImageDrawing drawing = new ImageDrawing(imageSource, destRect); float opacityValue = -1; string opacity = imageElement.GetAttribute("opacity"); if (string.IsNullOrWhiteSpace(opacity)) { opacity = imageElement.GetPropertyValue("opacity"); } if (!string.IsNullOrWhiteSpace(opacity)) { opacityValue = (float)SvgNumber.ParseNumber(opacity); opacityValue = Math.Min(opacityValue, 1); opacityValue = Math.Max(opacityValue, 0); } Geometry clipGeom = this.ClipGeometry; Transform transform = this.Transform; bool ownedGroup = true; if (drawGroup == null) { drawGroup = context.Peek(); ownedGroup = false; } Debug.Assert(drawGroup != null); if (drawGroup != null) { if ((opacityValue >= 0 && opacityValue < 1) || (clipGeom != null && !clipGeom.IsEmpty()) || (transform != null && !transform.Value.IsIdentity)) { DrawingGroup clipGroup = ownedGroup ? drawGroup : new DrawingGroup(); if (opacityValue >= 0 && opacityValue < 1) { clipGroup.Opacity = opacityValue; } if (clipGeom != null) { SvgUnitType clipUnits = this.ClipUnits; if (clipUnits == SvgUnitType.ObjectBoundingBox) { Rect drawingBounds = drawing.Bounds; TransformGroup transformGroup = new TransformGroup(); // Scale the clip region (at (0, 0)) and translate to the top-left corner of the target. transformGroup.Children.Add( new ScaleTransform(drawingBounds.Width, drawingBounds.Height)); transformGroup.Children.Add( new TranslateTransform(drawingBounds.X, drawingBounds.Y)); clipGeom.Transform = transformGroup; } clipGroup.ClipGeometry = clipGeom; } if (transform != null) { Transform curTransform = clipGroup.Transform; if (curTransform != null && curTransform.Value.IsIdentity == false) { TransformGroup transformGroup = new TransformGroup(); transformGroup.Children.Add(curTransform); transformGroup.Children.Add(transform); clipGroup.Transform = transformGroup; } else { clipGroup.Transform = transform; } } clipGroup.Children.Add(drawing); if (!ownedGroup) { drawGroup.Children.Add(clipGroup); } } else { drawGroup.Children.Add(drawing); } string elementId = this.GetElementName(); if (ownedGroup) { string sVisibility = imageElement.GetPropertyValue("visibility"); string sDisplay = imageElement.GetPropertyValue("display"); if (string.Equals(sVisibility, "hidden") || string.Equals(sDisplay, "none")) { drawGroup.Opacity = 0; } if (!_idAssigned && !string.IsNullOrWhiteSpace(elementId) && !context.IsRegisteredId(elementId)) { context.RegisterId(elementId); if (context.IncludeRuntime) { SvgObject.SetName(drawGroup, elementId); SvgObject.SetId(drawGroup, elementId); } } // Register this drawing with the Drawing-Document... this.Rendered(drawGroup); } else if (!_idAssigned) { if (!_idAssigned && !string.IsNullOrWhiteSpace(elementId) && !context.IsRegisteredId(elementId)) { context.RegisterId(elementId); if (context.IncludeRuntime) { SvgObject.SetName(imageSource, elementId); SvgObject.SetId(imageSource, elementId); } } // Register this drawing with the Drawing-Document... this.Rendered(drawing); } } }
public override void Render(WpfDrawingRenderer renderer) { if (_drawGroup == null || _drawContext == null) { return; } var comparer = StringComparison.OrdinalIgnoreCase; Point ctp = new Point(0, 0); // current text position WpfTextPlacement placement = WpfTextPlacement.Create(_textElement, ctp, _textContext.IsTextPath); ctp = placement.Location; double rotate = placement.Rotation; if (!placement.HasPositions) { placement = null; // render it useless } string sBaselineShift = _textElement.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; if (sBaselineShift.Length > 0) { double textFontSize = WpfTextRenderer.GetComputedFontSize(_textElement); if (sBaselineShift.EndsWith("%", comparer)) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100 * textFontSize; } else if (string.Equals(sBaselineShift, "sub", comparer)) { shiftBy = -0.6F * textFontSize; } else if (string.Equals(sBaselineShift, "super", comparer)) { shiftBy = 0.6F * textFontSize; } else if (string.Equals(sBaselineShift, "baseline", comparer)) { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } // For for fonts loading in the background... var svgDoc = _svgElement.OwnerDocument; if (svgDoc.IsFontsLoaded == false) { //TODO: Use of SpinUntil is known to CPU heavy, but will work for now... //SpinWait.SpinUntil(() => svgDoc.IsFontsLoaded == true); var svgWnd = svgDoc.Window as SvgWindow; if (svgWnd != null) { svgWnd.AwaitTasks("SvgDocument"); } } XmlNodeType nodeType = XmlNodeType.None; bool isVertical = false; string writingMode = _textElement.GetPropertyValue("writing-mode"); if (!string.IsNullOrWhiteSpace(writingMode) && string.Equals(writingMode, "tb", comparer)) { isVertical = true; } if (_svgElement.ChildNodes.Count == 1) { XmlNode child = _svgElement.ChildNodes[0]; nodeType = child.NodeType; if (nodeType == XmlNodeType.Text || nodeType == XmlNodeType.CDATA) { if (isVertical) { ctp.X -= shiftBy; RenderVertText(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderHorzText(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.Y += shiftBy; } } else if (nodeType == XmlNodeType.Element) { string nodeName = child.Name; if (string.Equals(nodeName, "tref", comparer)) { AddTRefElementRun((SvgTRefElement)child, ref ctp, isVertical, true); } else if (string.Equals(nodeName, "tspan", comparer)) { AddTSpanElementRun((SvgTSpanElement)child, ref ctp, isVertical, true); } else if (string.Equals(nodeName, "textPath", comparer)) { RenderTextPath((SvgTextPathElement)child, ref ctp, rotate, placement); } else if (string.Equals(nodeName, "altGlyph", comparer)) { AddAltGlyphElementRun((SvgAltGlyphElement)child, ref ctp, isVertical, true); } } else if (nodeType == XmlNodeType.Whitespace) { if (isVertical) { ctp.X -= shiftBy; RenderVertText(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderHorzText(_textElement, ref ctp, WpfTextRenderer.GetText(_textElement, child), rotate, placement); ctp.Y += shiftBy; } } } else { string textAnchor = _textElement.GetPropertyValue("text-anchor"); WpfTextAnchor anchor = WpfTextAnchor.None; if (string.Equals(textAnchor, "middle", comparer)) { anchor = WpfTextAnchor.Middle; } else if (string.Equals(textAnchor, "end", comparer)) { anchor = WpfTextAnchor.End; } XmlNodeList nodeList = _svgElement.ChildNodes; int nodeCount = nodeList.Count; // This is a very simply hack to change centered text to left align, since for // text containing spans, different font weights may be applied to the spans... if (anchor == WpfTextAnchor.Middle) { // Suspend the rendering... _isMeasuring = true; Point savedPt = new Point(ctp.X, ctp.Y); _textContext.BeginMeasure(nodeCount); for (int i = 0; i < nodeCount; i++) { XmlNode child = nodeList[i]; nodeType = child.NodeType; //if (i == 0 && nodeType == XmlNodeType.Whitespace) //{ // continue; //} if (nodeType == XmlNodeType.Text) { var nodeText = WpfTextRenderer.GetText(_textElement, child); if (i == (nodeCount - 1)) { // No need to render the last white space... nodeText = nodeText.TrimEnd(); } else if (i == 0) { nodeText = nodeText.Trim(); } if (isVertical) { ctp.X -= shiftBy; RenderVertTextRun(_textElement, ref ctp, nodeText, rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderHorzTextRun(_textElement, ref ctp, nodeText, rotate, placement); ctp.Y += shiftBy; } } else if (nodeType == XmlNodeType.Element) { string nodeName = child.Name; if (string.Equals(nodeName, "tref", comparer)) { AddTRefElementRun((SvgTRefElement)child, ref ctp, isVertical, false); } else if (string.Equals(nodeName, "tspan", comparer)) { bool isAdded = false; if ((i + 1) < nodeCount - 1) { XmlNode nextChild = nodeList[i + 1]; if (nextChild.NodeType == XmlNodeType.Whitespace) { isAdded = true; AddTSpanElementRun((SvgTSpanElement)child, ref ctp, isVertical, false, nextChild); i++; } } if (!isAdded) { AddTSpanElementRun((SvgTSpanElement)child, ref ctp, isVertical, false); } } else if (string.Equals(nodeName, "textPath", comparer)) { RenderTextPath((SvgTextPathElement)child, ref ctp, rotate, placement); } else if (string.Equals(nodeName, "altGlyph", comparer)) { AddAltGlyphElementRun((SvgAltGlyphElement)child, ref ctp, isVertical, false); } } else if (nodeType == XmlNodeType.Whitespace) { if (isVertical) { ctp.X -= shiftBy; RenderVertTextRun(_textElement, ref ctp, Whitespace, rotate, placement, true); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderHorzTextRun(_textElement, ref ctp, Whitespace, rotate, placement, true); ctp.Y += shiftBy; } } } _textContext.EndMeasure(); ctp = savedPt; ctp.X -= (_textWidth / 2d); // Resume the rendering... _isMeasuring = false; } bool textRendered = false; for (int i = 0; i < nodeCount; i++) { XmlNode child = nodeList[i]; nodeType = child.NodeType; //if (i == 0 && nodeType == XmlNodeType.Whitespace) //{ // continue; //} if (nodeType == XmlNodeType.Text) { var nodeText = WpfTextRenderer.GetText(_textElement, child); if (i == (nodeCount - 1)) { // No need to render the last white space... nodeText = nodeText.TrimEnd(); } else if (i == 0) { nodeText = nodeText.Trim(); } if (isVertical) { ctp.X -= shiftBy; RenderVertTextRun(_textElement, ref ctp, nodeText, rotate, placement); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderHorzTextRun(_textElement, ref ctp, nodeText, rotate, placement); ctp.Y += shiftBy; } textRendered = true; } else if (nodeType == XmlNodeType.Element) { string nodeName = child.Name; if (string.Equals(nodeName, "tref", comparer)) { AddTRefElementRun((SvgTRefElement)child, ref ctp, isVertical, false); textRendered = true; } else if (string.Equals(nodeName, "tspan", comparer)) { bool isAdded = false; if ((i + 1) < nodeCount - 1) { XmlNode nextChild = nodeList[i + 1]; if (nextChild.NodeType == XmlNodeType.Whitespace) { isAdded = true; AddTSpanElementRun((SvgTSpanElement)child, ref ctp, isVertical, false, nextChild); i++; } } if (!isAdded) { AddTSpanElementRun((SvgTSpanElement)child, ref ctp, isVertical, false); } textRendered = true; } else if (string.Equals(nodeName, "textPath", comparer)) { RenderTextPath((SvgTextPathElement)child, ref ctp, rotate, placement); textRendered = false; } else if (string.Equals(nodeName, "altGlyph", comparer)) { AddAltGlyphElementRun((SvgAltGlyphElement)child, ref ctp, isVertical, false); } } else if (nodeType == XmlNodeType.Whitespace) { if (textRendered) { if (isVertical) { ctp.X -= shiftBy; RenderVertTextRun(_textElement, ref ctp, Whitespace, rotate, placement, true); ctp.X += shiftBy; } else { ctp.Y -= shiftBy; RenderHorzTextRun(_textElement, ref ctp, Whitespace, rotate, placement, true); ctp.Y += shiftBy; } textRendered = false; } } } } // Register this drawing with the Drawing-Document... if (_drawGroup != null) { this.Rendered(_drawGroup); } }
public static Brush CreateViewportBrush(SvgStyleableElement svgElm) { string prop = svgElm.GetAttribute("viewport-fill"); string opacity = svgElm.GetAttribute("viewport-fill-opacity"); // no auto-inherit if (string.Equals(prop, "inherit", StringComparison.OrdinalIgnoreCase)) // if explicitly defined... { prop = svgElm.GetPropertyValue("viewport-fill"); } if (string.Equals(opacity, "inherit", StringComparison.OrdinalIgnoreCase)) // if explicitly defined... { opacity = svgElm.GetPropertyValue("viewport-fill-opacity"); } if (!string.IsNullOrWhiteSpace(prop)) { if (string.Equals(prop, "currentColor", StringComparison.OrdinalIgnoreCase)) { var svgParent = svgElm.ParentNode as SvgStyleableElement; if (svgParent != null) { prop = svgParent.GetPropertyValue(CssConstants.PropColor, "viewport-fill"); } } Color color = Colors.Transparent; // no auto-inherited... WpfSvgColor svgColor = new WpfSvgColor(svgElm, "viewport-fill"); color = svgColor.Color; if (color.A == 255) { double alpha = 255; if (!string.IsNullOrWhiteSpace(opacity)) { alpha *= SvgNumber.ParseNumber(opacity); } alpha = Math.Min(alpha, 255); alpha = Math.Max(alpha, 0); color = Color.FromArgb((byte)Convert.ToInt32(alpha), color.R, color.G, color.B); } var brush = new SolidColorBrush(color); double opacityValue = 1; if (!string.IsNullOrWhiteSpace(opacity) && double.TryParse(opacity, out opacityValue)) { brush.Opacity = opacityValue; } return(brush); } else { Color color = Colors.Black; // the default color... double alpha = 255; if (!string.IsNullOrWhiteSpace(opacity)) { alpha *= SvgNumber.ParseNumber(opacity); } alpha = Math.Min(alpha, 255); alpha = Math.Max(alpha, 0); color = Color.FromArgb((byte)Convert.ToInt32(alpha), color.R, color.G, color.B); return(new SolidColorBrush(color)); } }
public void RenderMarker0(WpfDrawingRenderer renderer, WpfDrawingContext gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { //PathGeometry g; //g.GetPointAtFractionLength( ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgMarkerElement markerElm = (SvgMarkerElement)_svgElement; SvgPointF[] vertexPositions = markerHostElm.MarkerPositions; int start; int len; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } for (int i = start; i < start + len; i++) { SvgPointF point = vertexPositions[i]; Matrix m = GetTransformMatrix(_svgElement); //GraphicsContainer gc = gr.BeginContainer(); this.BeforeRender(renderer); //gr.TranslateTransform(point.X, point.Y); //PAUL: //m.Translate(point.X, point.Y); if (markerElm.OrientType.AnimVal.Equals((ushort)SvgMarkerOrient.Angle)) { m.Rotate(markerElm.OrientAngle.AnimVal.Value); //gr.RotateTransform((double)markerElm.OrientAngle.AnimVal.Value); } else { double angle; switch (markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i + 1); break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i); break; } //gr.RotateTransform(angle); m.Rotate(angle); } if (markerElm.MarkerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { string propValue = refElement.GetPropertyValue("stroke-width"); if (propValue.Length == 0) { propValue = "1"; } SvgLength strokeWidthLength = new SvgLength("stroke-width", propValue, refElement, SvgLengthDirection.Viewport); double strokeWidth = strokeWidthLength.Value; //gr.ScaleTransform(strokeWidth, strokeWidth); m.Scale(strokeWidth, strokeWidth); } SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)markerElm.PreserveAspectRatio.AnimVal; double[] translateAndScale = spar.FitToViewBox( (SvgRect)markerElm.ViewBox.AnimVal, new SvgRect(0, 0, markerElm.MarkerWidth.AnimVal.Value, markerElm.MarkerHeight.AnimVal.Value)); //PAUL: //m.Translate(-(double)markerElm.RefX.AnimVal.Value * translateAndScale[2], -(double)markerElm.RefY.AnimVal.Value * translateAndScale[3]); //PAUL: m.Scale(translateAndScale[2], translateAndScale[3]); m.Translate(point.X, point.Y); //Matrix oldTransform = TransformMatrix; //TransformMatrix = m; //try //{ //newTransform.Append(m); //TransformGroup tg = new TransformGroup(); //renderer.Canvas.re //gr.TranslateTransform( // -(double)markerElm.RefX.AnimVal.Value * translateAndScale[2], // -(double)markerElm.RefY.AnimVal.Value * translateAndScale[3] // ); //gr.ScaleTransform(translateAndScale[2], translateAndScale[3]); renderer.RenderChildren(markerElm); // markerElm.RenderChildren(renderer); //} //finally //{ // TransformMatrix = oldTransform; //} // //gr.EndContainer(gc); _matrix = m; this.Render(renderer); //gr.EndContainer(gc); this.AfterRender(renderer); } }