public virtual bool ContainsRelativeMove() { if (!moveResolved) { ResolveTextMove(); } bool isNullMove = CssUtils.CompareFloats(0f, xMove) && CssUtils.CompareFloats(0f, yMove); // comparision to 0 return(!isNullMove); }
/// <summary>This convenience method rotates a given set of points around a given point</summary> /// <param name="list">the input list</param> /// <param name="rotation">the rotation angle, in radians</param> /// <param name="rotator">the point to rotate around</param> /// <returns>the list of rotated points</returns> internal static Point[][] Rotate(Point[][] list, double rotation, Point rotator) { if (!CssUtils.CompareFloats(rotation, 0)) { Point[][] result = new Point[list.Length][]; AffineTransform transRotTrans = AffineTransform.GetRotateInstance(rotation, rotator.x, rotator.y); for (int i = 0; i < list.Length; i++) { Point[] input = list[i]; Point[] row = new Point[input.Length]; for (int j = 0; j < input.Length; j++) { row[j] = transRotTrans.Transform(input[j], null); } result[i] = row; } return(result); } return(list); }
private float[] CalculateDistribution(float argA, float argC, float flexA, float flexC, float sum, float availableDimension ) { float flexRatioA; float flexRatioC; float flexSpace; if (CssUtils.CompareFloats(sum, 0f)) { flexRatioA = 1; flexRatioC = 1; } else { flexRatioA = flexA / sum; flexRatioC = flexC / sum; } flexSpace = availableDimension - (argA + argC); return(new float[] { argA + flexRatioA * flexSpace, argC + flexRatioC * flexSpace }); }
/// <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(); } } } }
public override void Draw(PdfCanvas canvas) { Point start = new Point(startPoint.x * .75, startPoint.y * .75); // pixels to points double rx = Math.Abs(CssUtils.ParseAbsoluteLength(coordinates[0])); double ry = Math.Abs(CssUtils.ParseAbsoluteLength(coordinates[1])); // φ is taken mod 360 degrees. double rotation = Double.Parse(coordinates[2], System.Globalization.CultureInfo.InvariantCulture) % 360.0; // rotation argument is given in degrees, but we need radians for easier trigonometric calculations rotation = MathUtil.ToRadians(rotation); // binary flags (Value correction: any nonzero value for either of the flags fA or fS is taken to mean the value 1.) bool largeArc = !CssUtils.CompareFloats((float)CssUtils.ParseFloat(coordinates[3]), 0); bool sweep = !CssUtils.CompareFloats((float)CssUtils.ParseFloat(coordinates[4]), 0); Point end = new Point(CssUtils.ParseAbsoluteLength(coordinates[5]), CssUtils.ParseAbsoluteLength(coordinates [6])); if (CssUtils.CompareFloats(start.x, end.x) && CssUtils.CompareFloats(start.y, end.y)) { /* edge case: If the endpoints (x1, y1) and (x2, y2) are identical, * then this is equivalent to omitting the elliptical arc segment entirely. */ return; } if (CssUtils.CompareFloats(rx, 0) || CssUtils.CompareFloats(ry, 0)) { /* edge case: If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a "lineto") * joining the endpoints. */ canvas.LineTo(end.x, end.y); } else { /* This is the first step of calculating a rotated elliptical path. * We must simulate a transformation on the end-point in order to calculate appropriate EllipseArc angles; * if we don't do this, then the EllipseArc class will calculate the correct bounding rectangle, * but an incorrect starting angle and/or extent. */ EllipticalCurveTo.EllipseArc arc; if (CssUtils.CompareFloats(rotation, 0)) { arc = EllipticalCurveTo.EllipseArc.GetEllipse(start, end, rx, ry, sweep, largeArc); } else { AffineTransform normalizer = AffineTransform.GetRotateInstance(-rotation); normalizer.Translate(-start.x, -start.y); Point newArcEnd = normalizer.Transform(end, null); newArcEnd.Translate(start.x, start.y); arc = EllipticalCurveTo.EllipseArc.GetEllipse(start, newArcEnd, rx, ry, sweep, largeArc); } Point[][] points = MakePoints(PdfCanvas.BezierArc(arc.ll.x, arc.ll.y, arc.ur.x, arc.ur.y, arc.startAng, arc .extent)); if (sweep) { points = Rotate(points, rotation, points[0][0]); for (int i = 0; i < points.Length; i++) { DrawCurve(canvas, points[i][1], points[i][2], points[i][3]); } } else { points = Rotate(points, rotation, points[points.Length - 1][3]); for (int i = points.Length - 1; i >= 0; i--) { DrawCurve(canvas, points[i][2], points[i][1], points[i][0]); } } } }
internal static EllipticalCurveTo.EllipseArc CalculatePossibleMiddle(Point start, Point end, double a, double b, double startToCenterAngle, bool sweep, bool largeArc) { double x0 = start.x - a * Math.Cos(startToCenterAngle); double y0 = start.y - b * Math.Sin(startToCenterAngle); Point center = new Point(x0, y0); double check = Math.Pow(((end.x - center.x) / a), 2) + Math.Pow(((end.y - center.y) / b), 2); /* If center is an actual candidate for a middle point, then the value of check will be very close to 1.0. * Otherwise it is always larger than 1. * Due to floating point math, we need to introduce an epsilon value. */ if (CssUtils.CompareFloats(check, 1.0)) { double theta1 = CalculateAngle(start, center, a, b); double theta2 = CalculateAngle(end, center, a, b); double startAngl = 0; double extent = 0; // round the difference, to catch edge cases with floating point math around the value 180 long deltaTheta = (long)Math.Abs(Math.Round(theta2 - theta1)); //both points are on the ellipse, but is this the middle, looked for? if (largeArc) { //turn more than 180 degrees if (sweep) { if ((theta2 > theta1) && (deltaTheta >= 180)) { startAngl = theta1; extent = theta2 - theta1; } if ((theta1 > theta2) && (deltaTheta <= 180)) { startAngl = theta1; extent = 360 - theta1 + theta2; } } else { if ((theta2 > theta1) && (deltaTheta <= 180)) { startAngl = theta2; extent = 360 - theta2 + theta1; } //or the same extent but negative and start at p1 if ((theta1 > theta2) && (deltaTheta >= 180)) { startAngl = theta2; extent = theta1 - theta2; } } } else { if (sweep) { if ((theta2 > theta1) && (deltaTheta <= 180)) { startAngl = theta1; extent = theta2 - theta1; } if ((theta1 > theta2) && (deltaTheta >= 180)) { startAngl = theta1; extent = 360 - theta1 + theta2; } } else { if ((theta2 > theta1) && (deltaTheta >= 180)) { startAngl = theta2; extent = 360 - theta2 + theta1; } //or the same extent but negative and start at p1 if ((theta1 > theta2) && (deltaTheta <= 180)) { startAngl = theta2; extent = theta1 - theta2; } } } if (startAngl >= 0 && extent > 0) { return(new EllipticalCurveTo.EllipseArc(center, a, b, startAngl, extent)); } } return(null); }
/// <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 = GetAttributeOrDefault(SvgConstants.Attributes.FILL, "black"); this.doFill = !SvgConstants.Values.NONE.EqualsIgnoreCase(fillRawValue); if (doFill && CanElementFill()) { float fillOpacity = GetOpacityByAttributeName(SvgConstants.Attributes.FILL_OPACITY, generalOpacity); Color fillColor = null; TransparentColor transparentColor = GetColorFromAttributeValue(context, fillRawValue, 0, fillOpacity); if (transparentColor != null) { fillColor = transparentColor.GetColor(); fillOpacity = transparentColor.GetOpacity(); } if (!CssUtils.CompareFloats(fillOpacity, 1f)) { opacityGraphicsState.SetFillOpacity(fillOpacity); } // set default if no color has been parsed if (fillColor == null) { fillColor = ColorConstants.BLACK; } currentCanvas.SetFillColor(fillColor); } } { // stroke String strokeRawValue = GetAttributeOrDefault(SvgConstants.Attributes.STROKE, SvgConstants.Values.NONE); if (!SvgConstants.Values.NONE.EqualsIgnoreCase(strokeRawValue)) { String strokeWidthRawValue = GetAttribute(SvgConstants.Attributes.STROKE_WIDTH); // 1 px = 0,75 pt float strokeWidth = 0.75f; if (strokeWidthRawValue != null) { strokeWidth = CssUtils.ParseAbsoluteLength(strokeWidthRawValue); } float strokeOpacity = GetOpacityByAttributeName(SvgConstants.Attributes.STROKE_OPACITY, generalOpacity); Color strokeColor = null; TransparentColor transparentColor = GetColorFromAttributeValue(context, strokeRawValue, strokeWidth / 2, strokeOpacity ); if (transparentColor != null) { strokeColor = transparentColor.GetColor(); strokeOpacity = transparentColor.GetOpacity(); } if (!CssUtils.CompareFloats(strokeOpacity, 1f)) { opacityGraphicsState.SetStrokeOpacity(strokeOpacity); } // as default value for stroke is 'none' we should not set // it in case when value obtaining fails if (strokeColor != null) { currentCanvas.SetStrokeColor(strokeColor); } currentCanvas.SetLineWidth(strokeWidth); doStroke = true; } } { // opacity if (!opacityGraphicsState.GetPdfObject().IsEmpty()) { currentCanvas.SetExtGState(opacityGraphicsState); } } } } }
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 = SvgTextUtil.FilterReferenceValue(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 (!CssUtils.CompareFloats(x, 0) || !CssUtils.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); } } } } } }
/// <summary> /// Tries to match a /// <see cref="MediaDeviceDescription"/>. /// </summary> /// <param name="deviceDescription">the device description</param> /// <returns>true, if successful</returns> public virtual bool Matches(MediaDeviceDescription deviceDescription) { switch (feature) { case MediaFeature.COLOR: { int?val = CssUtils.ParseInteger(value); if (minPrefix) { return(val != null && deviceDescription.GetBitsPerComponent() >= val); } else { if (maxPrefix) { return(val != null && deviceDescription.GetBitsPerComponent() <= val); } else { return(val == null?deviceDescription.GetBitsPerComponent() != 0 : val == deviceDescription.GetBitsPerComponent ()); } } goto case MediaFeature.COLOR_INDEX; } case MediaFeature.COLOR_INDEX: { int?val = CssUtils.ParseInteger(value); if (minPrefix) { return(val != null && deviceDescription.GetColorIndex() >= val); } else { if (maxPrefix) { return(val != null && deviceDescription.GetColorIndex() <= val); } else { return(val == null?deviceDescription.GetColorIndex() != 0 : val == deviceDescription.GetColorIndex()); } } goto case MediaFeature.ASPECT_RATIO; } case MediaFeature.ASPECT_RATIO: { int[] aspectRatio = CssUtils.ParseAspectRatio(value); if (minPrefix) { return(aspectRatio != null && aspectRatio[0] * deviceDescription.GetHeight() >= aspectRatio[1] * deviceDescription .GetWidth()); } else { if (maxPrefix) { return(aspectRatio != null && aspectRatio[0] * deviceDescription.GetHeight() <= aspectRatio[1] * deviceDescription .GetWidth()); } else { return(aspectRatio != null && CssUtils.CompareFloats(aspectRatio[0] * deviceDescription.GetHeight(), aspectRatio [1] * deviceDescription.GetWidth())); } } goto case MediaFeature.GRID; } case MediaFeature.GRID: { int?val = CssUtils.ParseInteger(value); return(val != null && val == 0 && !deviceDescription.IsGrid() || deviceDescription.IsGrid()); } case MediaFeature.SCAN: { return(Object.Equals(value, deviceDescription.GetScan())); } case MediaFeature.ORIENTATION: { return(Object.Equals(value, deviceDescription.GetOrientation())); } case MediaFeature.MONOCHROME: { int?val = CssUtils.ParseInteger(value); if (minPrefix) { return(val != null && deviceDescription.GetMonochrome() >= val); } else { if (maxPrefix) { return(val != null && deviceDescription.GetMonochrome() <= val); } else { return(val == null?deviceDescription.GetMonochrome() > 0 : val == deviceDescription.GetMonochrome()); } } goto case MediaFeature.HEIGHT; } case MediaFeature.HEIGHT: { float val = ParseAbsoluteLength(value); if (minPrefix) { return(deviceDescription.GetHeight() >= val); } else { if (maxPrefix) { return(deviceDescription.GetHeight() <= val); } else { return(deviceDescription.GetHeight() > 0); } } goto case MediaFeature.WIDTH; } case MediaFeature.WIDTH: { float val = ParseAbsoluteLength(value); if (minPrefix) { return(deviceDescription.GetWidth() >= val); } else { if (maxPrefix) { return(deviceDescription.GetWidth() <= val); } else { return(deviceDescription.GetWidth() > 0); } } goto case MediaFeature.RESOLUTION; } case MediaFeature.RESOLUTION: { float val = CssUtils.ParseResolution(value); if (minPrefix) { return(deviceDescription.GetResolution() >= val); } else { if (maxPrefix) { return(deviceDescription.GetResolution() <= val); } else { return(deviceDescription.GetResolution() > 0); } } goto default; } default: { return(false); } } }
/// <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); } } } } }