private void ApplyUserSpaceScaling(SvgDrawContext context)
 {
     if (!this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.MARKER_UNITS) || SvgConstants.Values.STROKEWIDTH
         .Equals(this.attributesAndStyles.Get(SvgConstants.Attributes.MARKER_UNITS)))
     {
         String parentValue = this.GetParent().GetAttribute(SvgConstants.Attributes.STROKE_WIDTH);
         if (parentValue != null)
         {
             float strokeWidthScale;
             if (CssUtils.IsPercentageValue(parentValue))
             {
                 // If stroke width is a percentage value is always computed as a percentage of the normalized viewBox diagonal length.
                 double rootViewPortHeight    = context.GetRootViewPort().GetHeight();
                 double rootViewPortWidth     = context.GetRootViewPort().GetWidth();
                 double viewBoxDiagonalLength = Math.Sqrt(rootViewPortHeight * rootViewPortHeight + rootViewPortWidth * rootViewPortWidth
                                                          );
                 strokeWidthScale = CssUtils.ParseRelativeValue(parentValue, (float)viewBoxDiagonalLength);
             }
             else
             {
                 strokeWidthScale = SvgCssUtils.ConvertPtsToPx(ParseFontRelativeOrAbsoluteLengthOnMarker(parentValue));
             }
             context.GetCurrentCanvas().ConcatMatrix(AffineTransform.GetScaleInstance(strokeWidthScale, strokeWidthScale
                                                                                      ));
         }
     }
 }
        protected internal override void DoDraw(SvgDrawContext context)
        {
            if (this.attributesAndStyles != null && this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.TEXT_CONTENT
                                                                                         ))
            {
                PdfCanvas      currentCanvas    = context.GetCurrentCanvas();
                String         xRawValue        = this.attributesAndStyles.Get(SvgConstants.Attributes.X);
                String         yRawValue        = this.attributesAndStyles.Get(SvgConstants.Attributes.Y);
                String         fontSizeRawValue = this.attributesAndStyles.Get(SvgConstants.Attributes.FONT_SIZE);
                IList <String> xValuesList      = SvgCssUtils.SplitValueList(xRawValue);
                IList <String> yValuesList      = SvgCssUtils.SplitValueList(yRawValue);
                float          x        = 0f;
                float          y        = 0f;
                float          fontSize = 0f;
                if (fontSizeRawValue != null && !String.IsNullOrEmpty(fontSizeRawValue))
                {
                    fontSize = CssUtils.ParseAbsoluteLength(fontSizeRawValue, CommonCssConstants.PT);
                }
                if (!xValuesList.IsEmpty())
                {
                    x = CssUtils.ParseAbsoluteLength(xValuesList[0]);
                }
                if (!yValuesList.IsEmpty())
                {
                    y = CssUtils.ParseAbsoluteLength(yValuesList[0]);
                }
                currentCanvas.BeginText();
                FontProvider provider  = context.GetFontProvider();
                FontSet      tempFonts = context.GetTempFonts();
                PdfFont      font      = null;
                if (!provider.GetFontSet().IsEmpty() || (tempFonts != null && !tempFonts.IsEmpty()))
                {
                    String fontFamily = this.attributesAndStyles.Get(SvgConstants.Attributes.FONT_FAMILY);
                    String fontWeight = this.attributesAndStyles.Get(SvgConstants.Attributes.FONT_WEIGHT);
                    String fontStyle  = this.attributesAndStyles.Get(SvgConstants.Attributes.FONT_STYLE);
                    fontFamily = fontFamily != null?fontFamily.Trim() : "";

                    FontInfo fontInfo = ResolveFontName(fontFamily, fontWeight, fontStyle, provider, tempFonts);
                    font = provider.GetPdfFont(fontInfo, tempFonts);
                }
                if (font == null)
                {
                    try {
                        // TODO (DEVSIX-2057)
                        // TODO each call of createFont() create a new instance of PdfFont.
                        // TODO FontProvider shall be used instead.
                        font = PdfFontFactory.CreateFont();
                    }
                    catch (System.IO.IOException e) {
                        throw new SvgProcessingException(SvgLogMessageConstant.FONT_NOT_FOUND, e);
                    }
                }
                currentCanvas.SetFontAndSize(font, fontSize);
                //Current transformation matrix results in the character glyphs being mirrored, correct with inverse tf
                currentCanvas.SetTextMatrix(1, 0, 0, -1, x, y);
                currentCanvas.SetColor(ColorConstants.BLACK, true);
                currentCanvas.ShowText(this.attributesAndStyles.Get(SvgConstants.Attributes.TEXT_CONTENT));
                currentCanvas.EndText();
            }
        }
示例#3
0
        internal virtual String[] RetrieveAlignAndMeet()
        {
            String meetOrSlice = SvgConstants.Values.MEET;
            String align       = SvgConstants.Values.DEFAULT_ASPECT_RATIO;

            if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.PRESERVE_ASPECT_RATIO))
            {
                String preserveAspectRatioValue = this.attributesAndStyles.Get(SvgConstants.Attributes.PRESERVE_ASPECT_RATIO
                                                                               );
                IList <String> aspectRatioValuesSplitValues = SvgCssUtils.SplitValueList(preserveAspectRatioValue);
                align = aspectRatioValuesSplitValues[0].ToLowerInvariant();
                if (aspectRatioValuesSplitValues.Count > 1)
                {
                    meetOrSlice = aspectRatioValuesSplitValues[1].ToLowerInvariant();
                }
            }
            if (this is MarkerSvgNodeRenderer && !SvgConstants.Values.NONE.Equals(align) && SvgConstants.Values.MEET.Equals
                    (meetOrSlice))
            {
                // Browsers do not correctly display markers with 'meet' option in the preserveAspectRatio attribute.
                // The Chrome, IE, and Firefox browsers set the align value to 'xMinYMin' regardless of the actual align.
                align = SvgConstants.Values.XMIN_YMIN;
            }
            return(new String[] { align, meetOrSlice });
        }
 public override void SetCoordinates(String[] inputCoordinates, Point startPoint)
 {
     String[] normalizedCoords = new String[LineTo.ARGUMENT_SIZE];
     // An H or h command is equivalent to an L or l command with 0 specified for the y coordinate.
     normalizedCoords[0] = inputCoordinates[0];
     normalizedCoords[1] = IsRelative() ? "0" : SvgCssUtils.ConvertDoubleToString(startPoint.GetY());
     base.SetCoordinates(normalizedCoords, startPoint);
 }
示例#5
0
 public override void SetCoordinates(String[] coordinates, Point startPoint)
 {
     String[] normalizedCoords = new String[coordinates.Length * 2];
     // An H or h command is equivalent to an L or l command with 0 specified for the y coordinate.
     for (int i = 0; i < coordinates.Length; i++)
     {
         normalizedCoords[i * 2]     = coordinates[i];
         normalizedCoords[i * 2 + 1] = IsRelative() ? "0" : SvgCssUtils.ConvertDoubleToString(startPoint.GetY());
     }
     base.SetCoordinates(normalizedCoords, startPoint);
 }
示例#6
0
 // transformation already happened in AbstractSvgNodeRenderer, so no need to do a transformation here
 /// <summary>Applies a transformation based on a viewBox for a given branch node.</summary>
 /// <param name="context">current svg draw context</param>
 internal virtual void ApplyViewBox(SvgDrawContext context)
 {
     if (this.attributesAndStyles != null && this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.VIEWBOX
                                                                                  ))
     {
         //Parse aspect ratio related stuff
         String         viewBoxValues = attributesAndStyles.Get(SvgConstants.Attributes.VIEWBOX);
         IList <String> valueStrings  = SvgCssUtils.SplitValueList(viewBoxValues);
         float[]        values        = new float[valueStrings.Count];
         for (int i = 0; i < values.Length; i++)
         {
             values[i] = CssUtils.ParseAbsoluteLength(valueStrings[i]);
         }
         Rectangle currentViewPort     = context.GetCurrentViewPort();
         String[]  alignAndMeet        = RetrieveAlignAndMeet();
         String    align               = alignAndMeet[0];
         String    meetOrSlice         = alignAndMeet[1];
         float     scaleWidth          = currentViewPort.GetWidth() / values[2];
         float     scaleHeight         = currentViewPort.GetHeight() / values[3];
         bool      forceUniformScaling = !(SvgConstants.Values.NONE.Equals(align));
         if (forceUniformScaling)
         {
             //Scaling should preserve aspect ratio
             if (SvgConstants.Values.MEET.Equals(meetOrSlice))
             {
                 scaleWidth = Math.Min(scaleWidth, scaleHeight);
             }
             else
             {
                 scaleWidth = Math.Max(scaleWidth, scaleHeight);
             }
             scaleHeight = scaleWidth;
         }
         AffineTransform scale = AffineTransform.GetScaleInstance(scaleWidth, scaleHeight);
         float[]         scaledViewBoxValues = ScaleViewBoxValues(values, scaleWidth, scaleHeight);
         AffineTransform transform           = ProcessAspectRatioPosition(context, scaledViewBoxValues, align, scaleWidth, scaleHeight
                                                                          );
         if (!scale.IsIdentity())
         {
             context.GetCurrentCanvas().ConcatMatrix(scale);
             //Inverse scaling needs to be applied to viewport dimensions
             context.GetCurrentViewPort().SetWidth(currentViewPort.GetWidth() / scaleWidth).SetX(currentViewPort.GetX()
                                                                                                 / scaleWidth).SetHeight(currentViewPort.GetHeight() / scaleHeight).SetY(currentViewPort.GetY() / scaleHeight
                                                                                                                                                                         );
         }
         if (!transform.IsIdentity())
         {
             context.GetCurrentCanvas().ConcatMatrix(transform);
             //Apply inverse translation to viewport to make it line up nicely
             context.GetCurrentViewPort().SetX(currentViewPort.GetX() + -1 * (float)transform.GetTranslateX()).SetY(currentViewPort
                                                                                                                    .GetY() + -1 * (float)transform.GetTranslateY());
         }
     }
 }
示例#7
0
        internal virtual float[] GetViewBoxValues()
        {
            String         viewBoxValues = attributesAndStyles.Get(SvgConstants.Attributes.VIEWBOX);
            IList <String> valueStrings  = SvgCssUtils.SplitValueList(viewBoxValues);

            float[] values = new float[valueStrings.Count];
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = CssUtils.ParseAbsoluteLength(valueStrings[i]);
            }
            return(values);
        }
        private void ApplyCoordinatesTranslation(SvgDrawContext context)
        {
            float xScale = 1;
            float yScale = 1;

            if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.VIEWBOX))
            {
                //Parse viewbox parameters stuff
                String         viewBoxValues = attributesAndStyles.Get(SvgConstants.Attributes.VIEWBOX);
                IList <String> valueStrings  = SvgCssUtils.SplitValueList(viewBoxValues);
                float[]        viewBox       = GetViewBoxValues();
                xScale = context.GetCurrentViewPort().GetWidth() / viewBox[2];
                yScale = context.GetCurrentViewPort().GetHeight() / viewBox[3];
            }
            float moveX = DEFAULT_REF_X;

            if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.REFX))
            {
                String refX = this.attributesAndStyles.Get(SvgConstants.Attributes.REFX);
                if (CssUtils.IsPercentageValue(refX))
                {
                    moveX = CssUtils.ParseRelativeValue(refX, context.GetRootViewPort().GetWidth());
                }
                else
                {
                    moveX = ParseFontRelativeOrAbsoluteLengthOnMarker(refX);
                }
                //Apply scale
                moveX *= -1 * xScale;
            }
            float moveY = DEFAULT_REF_Y;

            if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.REFY))
            {
                String refY = this.attributesAndStyles.Get(SvgConstants.Attributes.REFY);
                if (CssUtils.IsPercentageValue(refY))
                {
                    moveY = CssUtils.ParseRelativeValue(refY, context.GetRootViewPort().GetHeight());
                }
                else
                {
                    moveY = ParseFontRelativeOrAbsoluteLengthOnMarker(refY);
                }
                moveY *= -1 * yScale;
            }
            AffineTransform translation = AffineTransform.GetTranslateInstance(moveX, moveY);

            if (!translation.IsIdentity())
            {
                context.GetCurrentCanvas().ConcatMatrix(translation);
            }
        }
        private static float[] GetPositionsFromString(String rawValuesString)
        {
            float[]        result     = null;
            IList <String> valuesList = SvgCssUtils.SplitValueList(rawValuesString);

            if (!valuesList.IsEmpty())
            {
                result = new float[valuesList.Count];
                for (int i = 0; i < valuesList.Count; i++)
                {
                    result[i] = CssUtils.ParseAbsoluteLength(valuesList[i]);
                }
            }
            return(result);
        }
示例#10
0
        internal virtual String[] RetrieveAlignAndMeet()
        {
            String meetOrSlice = SvgConstants.Values.MEET;
            String align       = SvgConstants.Values.DEFAULT_ASPECT_RATIO;

            if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.PRESERVE_ASPECT_RATIO))
            {
                String preserveAspectRatioValue = this.attributesAndStyles.Get(SvgConstants.Attributes.PRESERVE_ASPECT_RATIO
                                                                               );
                IList <String> aspectRatioValuesSplitValues = SvgCssUtils.SplitValueList(preserveAspectRatioValue);
                align = aspectRatioValuesSplitValues[0].ToLowerInvariant();
                if (aspectRatioValuesSplitValues.Count > 1)
                {
                    meetOrSlice = aspectRatioValuesSplitValues[1].ToLowerInvariant();
                }
            }
            return(new String[] { align, meetOrSlice });
        }
 /// <summary>
 /// Gets the coordinates that shall be passed to
 /// <see cref="iText.Svg.Renderers.Path.IPathShape.SetCoordinates(System.String[], iText.Kernel.Geom.Point)"/>
 /// for the current shape.
 /// </summary>
 /// <param name="shape">The current shape.</param>
 /// <param name="previousShape">The previous shape which can affect the coordinates of the current shape.</param>
 /// <param name="pathProperties">
 /// The operator and all arguments as a
 /// <see>String[]</see>
 /// </param>
 /// <returns>
 /// a
 /// <see>String[]</see>
 /// of coordinates that shall be passed to
 /// <see cref="iText.Svg.Renderers.Path.IPathShape.SetCoordinates(System.String[], iText.Kernel.Geom.Point)"/>
 /// </returns>
 private String[] GetShapeCoordinates(IPathShape shape, IPathShape previousShape, String[] pathProperties)
 {
     if (shape is ClosePath)
     {
         return(null);
     }
     String[] shapeCoordinates = null;
     String[] operatorArgs     = JavaUtil.ArraysCopyOfRange(pathProperties, 1, pathProperties.Length);
     if (shape is SmoothSCurveTo)
     {
         String[] startingControlPoint = new String[2];
         if (previousShape != null)
         {
             Point previousEndPoint = previousShape.GetEndingPoint();
             //if the previous command was a C or S use its last control point
             if (((previousShape is CurveTo)))
             {
                 Point lastControlPoint = ((CurveTo)previousShape).GetLastControlPoint();
                 float reflectedX       = (float)(2 * previousEndPoint.GetX() - lastControlPoint.GetX());
                 float reflectedY       = (float)(2 * previousEndPoint.GetY() - lastControlPoint.GetY());
                 startingControlPoint[0] = SvgCssUtils.ConvertFloatToString(reflectedX);
                 startingControlPoint[1] = SvgCssUtils.ConvertFloatToString(reflectedY);
             }
             else
             {
                 startingControlPoint[0] = SvgCssUtils.ConvertDoubleToString(previousEndPoint.GetX());
                 startingControlPoint[1] = SvgCssUtils.ConvertDoubleToString(previousEndPoint.GetY());
             }
         }
         else
         {
             // TODO RND-951
             startingControlPoint[0] = pathProperties[1];
             startingControlPoint[1] = pathProperties[2];
         }
         shapeCoordinates = Concatenate(startingControlPoint, operatorArgs);
     }
     if (shapeCoordinates == null)
     {
         shapeCoordinates = operatorArgs;
     }
     return(shapeCoordinates);
 }
示例#12
0
 /// <summary>
 /// Gets the coordinates that shall be passed to
 /// <see cref="iText.Svg.Renderers.Path.IPathShape.SetCoordinates(System.String[], iText.Kernel.Geom.Point)"/>
 /// for the current shape.
 /// </summary>
 /// <param name="shape">The current shape.</param>
 /// <param name="previousShape">The previous shape which can affect the coordinates of the current shape.</param>
 /// <param name="pathProperties">
 /// The operator and all arguments as a
 /// <see>String[]</see>
 /// </param>
 /// <returns>
 /// a
 /// <see>String[]</see>
 /// of coordinates that shall be passed to
 /// <see cref="iText.Svg.Renderers.Path.IPathShape.SetCoordinates(System.String[], iText.Kernel.Geom.Point)"/>
 /// </returns>
 private String[] GetShapeCoordinates(IPathShape shape, IPathShape previousShape, String[] pathProperties)
 {
     if (shape is ClosePath)
     {
         return(null);
     }
     String[] shapeCoordinates = null;
     if (shape is SmoothSCurveTo || shape is QuadraticSmoothCurveTo)
     {
         String[] startingControlPoint = new String[2];
         if (previousShape != null)
         {
             Point previousEndPoint = previousShape.GetEndingPoint();
             //if the previous command was a Bezier curve, use its last control point
             if (previousShape is IControlPointCurve)
             {
                 Point lastControlPoint = ((IControlPointCurve)previousShape).GetLastControlPoint();
                 float reflectedX       = (float)(2 * previousEndPoint.GetX() - lastControlPoint.GetX());
                 float reflectedY       = (float)(2 * previousEndPoint.GetY() - lastControlPoint.GetY());
                 startingControlPoint[0] = SvgCssUtils.ConvertFloatToString(reflectedX);
                 startingControlPoint[1] = SvgCssUtils.ConvertFloatToString(reflectedY);
             }
             else
             {
                 startingControlPoint[0] = SvgCssUtils.ConvertDoubleToString(previousEndPoint.GetX());
                 startingControlPoint[1] = SvgCssUtils.ConvertDoubleToString(previousEndPoint.GetY());
             }
         }
         else
         {
             // TODO RND-951
             startingControlPoint[0] = pathProperties[0];
             startingControlPoint[1] = pathProperties[1];
         }
         shapeCoordinates = Concatenate(startingControlPoint, pathProperties);
     }
     if (shapeCoordinates == null)
     {
         shapeCoordinates = pathProperties;
     }
     return(shapeCoordinates);
 }
 private void ResolveTextMove()
 {
     if (this.attributesAndStyles != null)
     {
         String         xRawValue   = this.attributesAndStyles.Get(SvgConstants.Attributes.DX);
         String         yRawValue   = this.attributesAndStyles.Get(SvgConstants.Attributes.DY);
         IList <String> xValuesList = SvgCssUtils.SplitValueList(xRawValue);
         IList <String> yValuesList = SvgCssUtils.SplitValueList(yRawValue);
         xMove = 0f;
         yMove = 0f;
         if (!xValuesList.IsEmpty())
         {
             xMove = CssUtils.ParseAbsoluteLength(xValuesList[0]);
         }
         if (!yValuesList.IsEmpty())
         {
             yMove = CssUtils.ParseAbsoluteLength(yValuesList[0]);
         }
         moveResolved = true;
     }
 }
        public virtual void DrawMarker(SvgDrawContext context, MarkerVertexType markerVertexType)
        {
            Point point = null;

            if (MarkerVertexType.MARKER_START.Equals(markerVertexType))
            {
                point = points[0];
            }
            else
            {
                if (MarkerVertexType.MARKER_END.Equals(markerVertexType))
                {
                    point = points[points.Count - 1];
                }
            }
            if (point != null)
            {
                String moveX = SvgCssUtils.ConvertDoubleToString(CssUtils.ConvertPtsToPx(point.x));
                String moveY = SvgCssUtils.ConvertDoubleToString(CssUtils.ConvertPtsToPx(point.y));
                MarkerSvgNodeRenderer.DrawMarker(context, moveX, moveY, markerVertexType, this);
            }
        }
示例#15
0
        /// <summary>
        /// Parses a string of space separated x,y pairs into individual
        /// <see cref="iText.Kernel.Geom.Point"/>
        /// objects and appends them to
        /// <see cref="points"/>
        /// .
        /// Throws an
        /// <see cref="iText.Svg.Exceptions.SvgProcessingException"/>
        /// if pointsAttribute does not have a valid list of numerical x,y pairs.
        /// </summary>
        /// <param name="pointsAttribute">A string of space separated x,y value pairs</param>
        protected internal virtual void SetPoints(String pointsAttribute)
        {
            if (pointsAttribute == null)
            {
                return;
            }
            IList <String> points = SvgCssUtils.SplitValueList(pointsAttribute);

            if (points.Count % 2 != 0)
            {
                throw new SvgProcessingException(SvgLogMessageConstant.POINTS_ATTRIBUTE_INVALID_LIST).SetMessageParams(pointsAttribute
                                                                                                                       );
            }
            float x;
            float y;

            for (int i = 0; i < points.Count; i = i + 2)
            {
                x = CssUtils.ParseAbsoluteLength(points[i]);
                y = CssUtils.ParseAbsoluteLength(points[i + 1]);
                this.points.Add(new Point(x, y));
            }
        }
        public virtual void DrawMarker(SvgDrawContext context, MarkerVertexType markerVertexType)
        {
            Object[] allShapesOrdered = GetShapes().ToArray();
            Point    point            = null;

            if (MarkerVertexType.MARKER_START.Equals(markerVertexType))
            {
                point = ((AbstractPathShape)allShapesOrdered[0]).GetEndingPoint();
            }
            else
            {
                if (MarkerVertexType.MARKER_END.Equals(markerVertexType))
                {
                    point = ((AbstractPathShape)allShapesOrdered[allShapesOrdered.Length - 1]).GetEndingPoint();
                }
            }
            if (point != null)
            {
                String moveX = SvgCssUtils.ConvertDoubleToString(point.x);
                String moveY = SvgCssUtils.ConvertDoubleToString(point.y);
                MarkerSvgNodeRenderer.DrawMarker(context, moveX, moveY, markerVertexType, this);
            }
        }
 // transformation already happened in AbstractSvgNodeRenderer, so no need to do a transformation here
 /// <summary>Applies a transformation based on a viewBox for a given branch node.</summary>
 /// <param name="context">current svg draw context</param>
 private void ApplyViewBox(SvgDrawContext context)
 {
     if (this.attributesAndStyles != null)
     {
         if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.VIEWBOX))
         {
             //Parse aspect ratio related stuff
             String         viewBoxValues = attributesAndStyles.Get(SvgConstants.Attributes.VIEWBOX);
             IList <String> valueStrings  = SvgCssUtils.SplitValueList(viewBoxValues);
             float[]        values        = new float[valueStrings.Count];
             for (int i = 0; i < values.Length; i++)
             {
                 values[i] = CssUtils.ParseAbsoluteLength(valueStrings[i]);
             }
             Rectangle       currentViewPort = context.GetCurrentViewPort();
             float           scaleWidth      = currentViewPort.GetWidth() / values[2];
             float           scaleHeight     = currentViewPort.GetHeight() / values[3];
             AffineTransform scale           = AffineTransform.GetScaleInstance(scaleWidth, scaleHeight);
             if (!scale.IsIdentity())
             {
                 context.GetCurrentCanvas().ConcatMatrix(scale);
                 //Inverse scaling needs to be applied to viewport dimensions
                 context.GetCurrentViewPort().SetWidth(currentViewPort.GetWidth() / scaleWidth);
                 context.GetCurrentViewPort().SetX(currentViewPort.GetX() / scaleWidth);
                 context.GetCurrentViewPort().SetHeight(currentViewPort.GetHeight() / scaleHeight);
                 context.GetCurrentViewPort().SetY(currentViewPort.GetY() / scaleHeight);
             }
             AffineTransform transform = ProcessAspectRatio(context, values);
             if (!transform.IsIdentity())
             {
                 //TODO (RND-876)
                 context.GetCurrentCanvas().WriteLiteral("% applying viewbox aspect ratio correction (not correct) \n");
             }
         }
     }
 }
示例#18
0
        private void CollectCssDeclarations(INode rootNode, ResourceResolver resourceResolver)
        {
            this.css = new CssStyleSheet();
            LinkedList <INode> q = new LinkedList <INode>();

            if (rootNode != null)
            {
                q.Add(rootNode);
            }
            while (!q.IsEmpty())
            {
                INode currentNode = q.JRemoveFirst();
                if (currentNode is IElementNode)
                {
                    IElementNode headChildElement = (IElementNode)currentNode;
                    if (SvgConstants.Tags.STYLE.Equals(headChildElement.Name()))
                    {
                        //XML parser will parse style tag contents as text nodes
                        if (!currentNode.ChildNodes().IsEmpty() && (currentNode.ChildNodes()[0] is IDataNode || currentNode.ChildNodes
                                                                        ()[0] is ITextNode))
                        {
                            String styleData;
                            if (currentNode.ChildNodes()[0] is IDataNode)
                            {
                                styleData = ((IDataNode)currentNode.ChildNodes()[0]).GetWholeData();
                            }
                            else
                            {
                                styleData = ((ITextNode)currentNode.ChildNodes()[0]).WholeText();
                            }
                            CssStyleSheet styleSheet = CssStyleSheetParser.Parse(styleData);
                            //TODO (DEVSIX-2263): media query wrap
                            //styleSheet = wrapStyleSheetInMediaQueryIfNecessary(headChildElement, styleSheet);
                            this.css.AppendCssStyleSheet(styleSheet);
                        }
                    }
                    else
                    {
                        if (SvgCssUtils.IsStyleSheetLink(headChildElement))
                        {
                            String styleSheetUri = headChildElement.GetAttribute(SvgConstants.Attributes.HREF);
                            try {
                                Stream        stream     = resourceResolver.RetrieveStyleSheet(styleSheetUri);
                                byte[]        bytes      = StreamUtil.InputStreamToArray(stream);
                                CssStyleSheet styleSheet = CssStyleSheetParser.Parse(new MemoryStream(bytes), resourceResolver.ResolveAgainstBaseUri
                                                                                         (styleSheetUri).ToExternalForm());
                                this.css.AppendCssStyleSheet(styleSheet);
                            }
                            catch (System.IO.IOException exc) {
                                ILog logger = LogManager.GetLogger(typeof(iText.Svg.Css.Impl.SvgStyleResolver));
                                logger.Error(iText.StyledXmlParser.LogMessageConstant.UNABLE_TO_PROCESS_EXTERNAL_CSS_FILE, exc);
                            }
                        }
                    }
                }
                foreach (INode child in currentNode.ChildNodes())
                {
                    if (child is IElementNode)
                    {
                        q.Add(child);
                    }
                }
            }
        }
        /// <summary>If present, process the preserveAspectRatio.</summary>
        /// <param name="context">the svg draw context</param>
        /// <param name="viewBoxValues">the four values depicting the viewbox [min-x min-y width height]</param>
        /// <returns>the transformation based on the preserveAspectRatio value</returns>
        private AffineTransform ProcessAspectRatio(SvgDrawContext context, float[] viewBoxValues)
        {
            AffineTransform transform = new AffineTransform();

            if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.PRESERVE_ASPECT_RATIO))
            {
                Rectangle currentViewPort          = context.GetCurrentViewPort();
                String    preserveAspectRatioValue = this.attributesAndStyles.Get(SvgConstants.Attributes.PRESERVE_ASPECT_RATIO
                                                                                  );
                IList <String> values = SvgCssUtils.SplitValueList(preserveAspectRatioValue);
                if (SvgConstants.Values.DEFER.EqualsIgnoreCase(values[0]))
                {
                    values.JRemoveAt(0);
                }
                String align    = values[0];
                float  x        = 0f;
                float  y        = 0f;
                float  midXBox  = viewBoxValues[0] + (viewBoxValues[2] / 2);
                float  midYBox  = viewBoxValues[1] + (viewBoxValues[3] / 2);
                float  midXPort = currentViewPort.GetX() + (currentViewPort.GetWidth() / 2);
                float  midYPort = currentViewPort.GetY() + (currentViewPort.GetHeight() / 2);
                switch (align.ToLowerInvariant())
                {
                case SvgConstants.Values.NONE: {
                    break;
                }

                case SvgConstants.Values.XMIN_YMIN: {
                    x = -viewBoxValues[0];
                    y = -viewBoxValues[1];
                    break;
                }

                case SvgConstants.Values.XMIN_YMID: {
                    x = -viewBoxValues[0];
                    y = midYPort - midYBox;
                    break;
                }

                case SvgConstants.Values.XMIN_YMAX: {
                    x = -viewBoxValues[0];
                    y = currentViewPort.GetHeight() - viewBoxValues[3];
                    break;
                }

                case SvgConstants.Values.XMID_YMIN: {
                    x = midXPort - midXBox;
                    y = -viewBoxValues[1];
                    break;
                }

                case SvgConstants.Values.XMID_YMAX: {
                    x = midXPort - midXBox;
                    y = currentViewPort.GetHeight() - viewBoxValues[3];
                    break;
                }

                case SvgConstants.Values.XMAX_YMIN: {
                    x = currentViewPort.GetWidth() - viewBoxValues[2];
                    y = -viewBoxValues[1];
                    break;
                }

                case SvgConstants.Values.XMAX_YMID: {
                    x = currentViewPort.GetWidth() - viewBoxValues[2];
                    y = midYPort - midYBox;
                    break;
                }

                case SvgConstants.Values.XMAX_YMAX: {
                    x = currentViewPort.GetWidth() - viewBoxValues[2];
                    y = currentViewPort.GetHeight() - viewBoxValues[3];
                    break;
                }

                case SvgConstants.Values.DEFAULT_ASPECT_RATIO:
                default: {
                    x = midXPort - midXBox;
                    y = midYPort - midYBox;
                    break;
                }
                }
                transform.Translate(x, y);
            }
            return(transform);
        }