protected internal override void DoDraw(SvgDrawContext context) { PdfCanvas cv = context.GetCurrentCanvas(); cv.WriteLiteral("% rect\n"); float x = 0.0f; float y = 0.0f; if (GetAttribute(SvgConstants.Attributes.X) != null) { x = CssUtils.ParseAbsoluteLength(GetAttribute(SvgConstants.Attributes.X)); } if (GetAttribute(SvgConstants.Attributes.Y) != null) { y = CssUtils.ParseAbsoluteLength(GetAttribute(SvgConstants.Attributes.Y)); } float width = CssUtils.ParseAbsoluteLength(GetAttribute(SvgConstants.Attributes.WIDTH)); float height = CssUtils.ParseAbsoluteLength(GetAttribute(SvgConstants.Attributes.HEIGHT)); bool rxPresent = false; bool ryPresent = false; float rx = 0f; float ry = 0f; if (attributesAndStyles.ContainsKey(SvgConstants.Attributes.RX)) { rx = CssUtils.ParseAbsoluteLength(GetAttribute(SvgConstants.Attributes.RX)); rxPresent = true; } if (attributesAndStyles.ContainsKey(SvgConstants.Attributes.RY)) { ry = CssUtils.ParseAbsoluteLength(GetAttribute(SvgConstants.Attributes.RY)); ryPresent = true; } bool singleValuePresent = (rxPresent && !ryPresent) || (!rxPresent && ryPresent); // these checks should happen in all cases rx = CheckRadius(rx, width); ry = CheckRadius(ry, height); if (!rxPresent && !ryPresent) { cv.Rectangle(x, y, width, height); } else { if (singleValuePresent) { cv.WriteLiteral("% circle rounded rect\n"); // only look for radius in case of circular rounding float radius = FindCircularRadius(rx, ry, width, height); cv.RoundRectangle(x, y, width, height, radius); } else { cv.WriteLiteral("% ellipse rounded rect\n"); // TODO (DEVSIX-1878): this should actually be refactored into PdfCanvas.roundRectangle() /* * * y+h -> ____________________________ * / \ * / \ * y+h-ry -> / \ | | | | | | | | | y+ry -> \ / \ / \ y -> \____________________________/ \ ^ ^ ^ ^ \ x x+rx x+w-rx x+w \ */ cv.MoveTo(x + rx, y); cv.LineTo(x + width - rx, y); Arc(x + width - 2 * rx, y, x + width, y + 2 * ry, -90, 90, cv); cv.LineTo(x + width, y + height - ry); Arc(x + width, y + height - 2 * ry, x + width - 2 * rx, y + height, 0, 90, cv); cv.LineTo(x + rx, y + height); Arc(x + 2 * rx, y + height, x, y + height - 2 * ry, 90, 90, cv); cv.LineTo(x, y + ry); Arc(x, y + 2 * ry, x + 2 * rx, y, 180, 90, cv); cv.ClosePath(); } } }
/// <summary> /// Method that will set properties to be inherited by this branch renderer's /// children and will iterate over all children in order to draw them. /// </summary> /// <param name="context"> /// the object that knows the place to draw this element and /// maintains its state /// </param> protected internal override void DoDraw(SvgDrawContext context) { if (GetChildren().Count > 0) { // if branch has no children, don't do anything PdfCanvas currentCanvas = context.GetCurrentCanvas(); if (performRootTransformations) { currentCanvas.BeginText(); //Current transformation matrix results in the character glyphs being mirrored, correct with inverse tf AffineTransform rootTf; if (this.ContainsAbsolutePositionChange()) { rootTf = GetTextTransform(this.GetAbsolutePositionChanges(), context); } else { rootTf = new AffineTransform(TEXTFLIP); } currentCanvas.SetTextMatrix(rootTf); //Reset context of text move context.ResetTextMove(); //Apply relative move if (this.ContainsRelativeMove()) { float[] rootMove = this.GetRelativeTranslation(); context.AddTextMove(rootMove[0], -rootMove[1]); } //-y to account for the text-matrix transform we do in the text root to account for the coordinates //handle white-spaces if (!whiteSpaceProcessed) { SvgTextUtil.ProcessWhiteSpace(this, true); } } ApplyTextRenderingMode(currentCanvas); if (this.attributesAndStyles != null) { ResolveFontSize(); ResolveFont(context); currentCanvas.SetFontAndSize(font, fontSize); foreach (ISvgTextNodeRenderer c in children) { float childLength = c.GetTextContentLength(fontSize, font); if (c.ContainsAbsolutePositionChange()) { //TODO(DEVSIX-2507) support rotate and other attributes float[][] absolutePositions = c.GetAbsolutePositionChanges(); AffineTransform newTransform = GetTextTransform(absolutePositions, context); //overwrite the last transformation stored in the context context.SetLastTextTransform(newTransform); //Apply transformation currentCanvas.SetTextMatrix(newTransform); //Absolute position changes requires resetting the current text move in the context context.ResetTextMove(); } //Handle Text-Anchor declarations float textAnchorCorrection = GetTextAnchorAlignmentCorrection(childLength); if (!CssUtils.CompareFloats(0f, textAnchorCorrection)) { context.AddTextMove(textAnchorCorrection, 0); } //Move needs to happen before the saving of the state in order for it to cascade beyond if (c.ContainsRelativeMove()) { float[] childMove = c.GetRelativeTranslation(); context.AddTextMove(childMove[0], -childMove[1]); } //-y to account for the text-matrix transform we do in the text root to account for the coordinates currentCanvas.SaveState(); c.Draw(context); context.AddTextMove(childLength, 0); currentCanvas.RestoreState(); //Restore transformation matrix if (!context.GetLastTextTransform().IsIdentity()) { currentCanvas.SetTextMatrix(context.GetLastTextTransform()); } } if (performRootTransformations) { currentCanvas.EndText(); } } } }
protected internal override void DoDraw(SvgDrawContext context) { ResourceResolver resourceResolver = context.GetResourceResolver(); if (resourceResolver == null || this.attributesAndStyles == null) { return; } String uri = this.attributesAndStyles.Get(SvgConstants.Attributes.XLINK_HREF); PdfXObject xObject = resourceResolver.RetrieveImageExtended(uri); if (xObject == null) { return; } PdfCanvas currentCanvas = context.GetCurrentCanvas(); float x = 0; if (attributesAndStyles.ContainsKey(SvgConstants.Attributes.X)) { x = CssUtils.ParseAbsoluteLength(attributesAndStyles.Get(SvgConstants.Attributes.X)); } float y = 0; if (attributesAndStyles.ContainsKey(SvgConstants.Attributes.Y)) { y = CssUtils.ParseAbsoluteLength(attributesAndStyles.Get(SvgConstants.Attributes.Y)); } float width = 0; if (attributesAndStyles.ContainsKey(SvgConstants.Attributes.WIDTH)) { width = CssUtils.ParseAbsoluteLength(attributesAndStyles.Get(SvgConstants.Attributes.WIDTH)); } float height = 0; if (attributesAndStyles.ContainsKey(SvgConstants.Attributes.HEIGHT)) { height = CssUtils.ParseAbsoluteLength(attributesAndStyles.Get(SvgConstants.Attributes.HEIGHT)); } String preserveAspectRatio = ""; if (attributesAndStyles.ContainsKey(SvgConstants.Attributes.PRESERVE_ASPECT_RATIO)) { preserveAspectRatio = attributesAndStyles.Get(SvgConstants.Attributes.PRESERVE_ASPECT_RATIO); } preserveAspectRatio = preserveAspectRatio.ToLowerInvariant(); if (!SvgConstants.Values.NONE.Equals(preserveAspectRatio) && !(width == 0 || height == 0)) { float normalizedWidth; float normalizedHeight; if (xObject.GetWidth() / width > xObject.GetHeight() / height) { normalizedWidth = width; normalizedHeight = xObject.GetHeight() / xObject.GetWidth() * width; } else { normalizedWidth = xObject.GetWidth() / xObject.GetHeight() * height; normalizedHeight = height; } switch (preserveAspectRatio.ToLowerInvariant()) { case SvgConstants.Values.XMIN_YMIN: { break; } case SvgConstants.Values.XMIN_YMID: { y += Math.Abs(normalizedHeight - height) / 2; break; } case SvgConstants.Values.XMIN_YMAX: { y += Math.Abs(normalizedHeight - height); break; } case SvgConstants.Values.XMID_YMIN: { x += Math.Abs(normalizedWidth - width) / 2; break; } case SvgConstants.Values.XMID_YMAX: { x += Math.Abs(normalizedWidth - width) / 2; y += Math.Abs(normalizedHeight - height); break; } case SvgConstants.Values.XMAX_YMIN: { x += Math.Abs(normalizedWidth - width); break; } case SvgConstants.Values.XMAX_YMID: { x += Math.Abs(normalizedWidth - width); y += Math.Abs(normalizedHeight - height) / 2; break; } case SvgConstants.Values.XMAX_YMAX: { x += Math.Abs(normalizedWidth - width); y += Math.Abs(normalizedHeight - height); break; } case SvgConstants.Values.DEFAULT_ASPECT_RATIO: default: { x += Math.Abs(normalizedWidth - width) / 2; y += Math.Abs(normalizedHeight - height) / 2; break; } } width = normalizedWidth; height = normalizedHeight; } float v = y + height; currentCanvas.AddXObject(xObject, width, 0, 0, -height, x, v); }
public override Color CreateColor(SvgDrawContext context, Rectangle objectBoundingBox, float objectBoundingBoxMargin , float parentOpacity) { if (objectBoundingBox == null) { return(null); } LinearGradientBuilder builder = new LinearGradientBuilder(); foreach (GradientColorStop stopColor in ParseStops(parentOpacity)) { builder.AddColorStop(stopColor); } builder.SetSpreadMethod(ParseSpreadMethod()); bool isObjectBoundingBox = IsObjectBoundingBoxUnits(); Point[] coordinates = GetCoordinates(context, isObjectBoundingBox); builder.SetGradientVector(coordinates[0].GetX(), coordinates[0].GetY(), coordinates[1].GetX(), coordinates [1].GetY()); AffineTransform gradientTransform = GetGradientTransformToUserSpaceOnUse(objectBoundingBox, isObjectBoundingBox ); builder.SetCurrentSpaceToGradientVectorSpaceTransformation(gradientTransform); return(builder.BuildColor(objectBoundingBox.ApplyMargins(objectBoundingBoxMargin, objectBoundingBoxMargin, objectBoundingBoxMargin, objectBoundingBoxMargin, true), context.GetCurrentCanvasTransform(), context. GetCurrentCanvas().GetDocument())); }
/// <summary>Operations to perform before drawing an element.</summary> /// <remarks> /// Operations to perform before drawing an element. /// This includes setting stroke color and width, fill color. /// </remarks> /// <param name="context">the svg draw context</param> internal virtual void PreDraw(SvgDrawContext context) { if (this.attributesAndStyles != null) { PdfCanvas currentCanvas = context.GetCurrentCanvas(); PdfExtGState opacityGraphicsState = new PdfExtGState(); if (!partOfClipPath) { float generalOpacity = GetOpacity(); { // fill String fillRawValue = GetAttribute(SvgConstants.Attributes.FILL); this.doFill = !SvgConstants.Values.NONE.EqualsIgnoreCase(fillRawValue); if (doFill && CanElementFill()) { Color rgbColor = ColorConstants.BLACK; float fillOpacity = generalOpacity; String opacityValue = GetAttribute(SvgConstants.Attributes.FILL_OPACITY); if (opacityValue != null && !SvgConstants.Values.NONE.EqualsIgnoreCase(opacityValue)) { fillOpacity *= float.Parse(opacityValue, System.Globalization.CultureInfo.InvariantCulture); } if (fillRawValue != null) { fillOpacity *= GetAlphaFromRGBA(fillRawValue); rgbColor = WebColors.GetRGBColor(fillRawValue); } if (!CssUtils.CompareFloats(fillOpacity, 1f)) { opacityGraphicsState.SetFillOpacity(fillOpacity); } currentCanvas.SetFillColor(rgbColor); } } { // stroke String strokeRawValue = GetAttribute(SvgConstants.Attributes.STROKE); if (!SvgConstants.Values.NONE.EqualsIgnoreCase(strokeRawValue)) { if (strokeRawValue != null) { Color rgbColor = WebColors.GetRGBColor(strokeRawValue); float strokeOpacity = generalOpacity; String opacityValue = GetAttribute(SvgConstants.Attributes.STROKE_OPACITY); if (opacityValue != null && !SvgConstants.Values.NONE.EqualsIgnoreCase(opacityValue)) { strokeOpacity *= float.Parse(opacityValue, System.Globalization.CultureInfo.InvariantCulture); } strokeOpacity *= GetAlphaFromRGBA(strokeRawValue); if (!CssUtils.CompareFloats(strokeOpacity, 1f)) { opacityGraphicsState.SetStrokeOpacity(strokeOpacity); } currentCanvas.SetStrokeColor(rgbColor); String strokeWidthRawValue = GetAttribute(SvgConstants.Attributes.STROKE_WIDTH); // 1 px = 0,75 pt float strokeWidth = 0.75f; if (strokeWidthRawValue != null) { strokeWidth = CssUtils.ParseAbsoluteLength(strokeWidthRawValue); } currentCanvas.SetLineWidth(strokeWidth); doStroke = true; } } } { // opacity if (!opacityGraphicsState.GetPdfObject().IsEmpty()) { currentCanvas.SetExtGState(opacityGraphicsState); } } } } }
/// <summary>Operations to be performed after drawing the element.</summary> /// <remarks> /// Operations to be performed after drawing the element. /// This includes filling, stroking. /// </remarks> /// <param name="context">the svg draw context</param> internal virtual void PostDraw(SvgDrawContext context) { if (this.attributesAndStyles != null) { PdfCanvas currentCanvas = context.GetCurrentCanvas(); // fill-rule if (partOfClipPath) { if (SvgConstants.Values.FILL_RULE_EVEN_ODD.EqualsIgnoreCase(this.GetAttribute(SvgConstants.Attributes.CLIP_RULE ))) { currentCanvas.EoClip(); } else { currentCanvas.Clip(); } currentCanvas.EndPath(); } else { if (doFill && CanElementFill()) { String fillRuleRawValue = GetAttribute(SvgConstants.Attributes.FILL_RULE); if (SvgConstants.Values.FILL_RULE_EVEN_ODD.EqualsIgnoreCase(fillRuleRawValue)) { if (doStroke) { currentCanvas.EoFillStroke(); } else { currentCanvas.EoFill(); } } else { if (doStroke) { currentCanvas.FillStroke(); } else { currentCanvas.Fill(); } } } else { if (doStroke) { currentCanvas.Stroke(); } else { if (!typeof(TextSvgBranchRenderer).IsInstanceOfType(this)) { currentCanvas.EndPath(); } } } } // Marker drawing if (this is IMarkerCapable) { // TODO (DEVSIX-3397) add processing of 'marker' property (shorthand for a joint using of all other properties) foreach (MarkerVertexType markerVertexType in MARKER_VERTEX_TYPES) { if (attributesAndStyles.ContainsKey(markerVertexType.ToString())) { currentCanvas.SaveState(); ((IMarkerCapable)this).DrawMarker(context, markerVertexType); currentCanvas.RestoreState(); } } } } }
/// <summary>Operations to be performed after drawing the element.</summary> /// <remarks> /// Operations to be performed after drawing the element. /// This includes filling, stroking. /// </remarks> /// <param name="context">the svg draw context</param> internal virtual void PostDraw(SvgDrawContext context) { if (this.attributesAndStyles != null) { PdfCanvas currentCanvas = context.GetCurrentCanvas(); // fill-rule if (partOfClipPath) { if (SvgConstants.Values.FILL_RULE_EVEN_ODD.EqualsIgnoreCase(this.GetAttribute(SvgConstants.Attributes.CLIP_RULE ))) { currentCanvas.EoClip(); } else { currentCanvas.Clip(); } currentCanvas.EndPath(); } else { if (doFill && CanElementFill()) { String fillRuleRawValue = GetAttribute(SvgConstants.Attributes.FILL_RULE); if (SvgConstants.Values.FILL_RULE_EVEN_ODD.EqualsIgnoreCase(fillRuleRawValue)) { if (doStroke) { currentCanvas.EoFillStroke(); } else { currentCanvas.EoFill(); } } else { if (doStroke) { currentCanvas.FillStroke(); } else { currentCanvas.Fill(); } } } else { if (doStroke) { currentCanvas.Stroke(); } else { if (!typeof(TextSvgBranchRenderer).IsInstanceOfType(this)) { currentCanvas.EndPath(); } } } } } }
protected internal override void DoDraw(SvgDrawContext context) { if (this.attributesAndStyles != null) { String elementToReUse = this.attributesAndStyles.Get(SvgConstants.Attributes.XLINK_HREF); if (elementToReUse == null) { elementToReUse = this.attributesAndStyles.Get(SvgConstants.Attributes.HREF); } if (elementToReUse != null && !String.IsNullOrEmpty(elementToReUse) && IsValidHref(elementToReUse)) { String normalizedName = NormalizeName(elementToReUse); if (!context.IsIdUsedByUseTagBefore(normalizedName)) { ISvgNodeRenderer template = context.GetNamedObject(normalizedName); //Clone template ISvgNodeRenderer namedObject = template == null ? null : template.CreateDeepCopy(); //Resolve parent inheritance SvgNodeRendererInheritanceResolver iresolver = new SvgNodeRendererInheritanceResolver(); iresolver.ApplyInheritanceToSubTree(this, namedObject); if (namedObject != null) { if (namedObject is AbstractSvgNodeRenderer) { ((AbstractSvgNodeRenderer)namedObject).SetPartOfClipPath(partOfClipPath); } PdfCanvas currentCanvas = context.GetCurrentCanvas(); float x = 0f; float y = 0f; if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.X)) { x = CssUtils.ParseAbsoluteLength(this.attributesAndStyles.Get(SvgConstants.Attributes.X)); } if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.Y)) { y = CssUtils.ParseAbsoluteLength(this.attributesAndStyles.Get(SvgConstants.Attributes.Y)); } AffineTransform inverseMatrix = null; if (!SvgMathUtils.CompareFloats(x, 0) || !SvgMathUtils.CompareFloats(y, 0)) { AffineTransform translation = AffineTransform.GetTranslateInstance(x, y); currentCanvas.ConcatMatrix(translation); if (partOfClipPath) { try { inverseMatrix = translation.CreateInverse(); } catch (NoninvertibleTransformException ex) { LogManager.GetLogger(typeof(UseSvgNodeRenderer)).Warn(SvgLogMessageConstant.NONINVERTIBLE_TRANSFORMATION_MATRIX_USED_IN_CLIP_PATH , ex); } } } // setting the parent of the referenced element to this instance namedObject.SetParent(this); namedObject.Draw(context); // unsetting the parent of the referenced element namedObject.SetParent(null); if (inverseMatrix != null) { currentCanvas.ConcatMatrix(inverseMatrix); } } } } } }