public virtual bool ContainsRelativeMove()
        {
            if (!moveResolved)
            {
                ResolveTextMove();
            }
            bool isNullMove = CssUtils.CompareFloats(0f, xMove) && CssUtils.CompareFloats(0f, yMove);

            // comparision to 0
            return(!isNullMove);
        }
Пример #2
0
 /// <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);
 }
Пример #3
0
        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();
             }
         }
     }
 }
Пример #5
0
        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]);
                    }
                }
            }
        }
Пример #6
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);
                 }
             }
         }
     }
 }
Пример #8
0
 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);
                     }
                 }
             }
         }
     }
 }
Пример #9
0
        /// <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);
            }
            }
        }
Пример #10
0
 /// <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);
                 }
             }
         }
     }
 }