Beispiel #1
0
        public virtual void OneRotateValuesTest()
        {
            AffineTransform expected = AffineTransform.GetRotateInstance(MathUtil.ToRadians(10));
            AffineTransform actual   = TransformUtils.ParseTransform("rotate(10)");

            NUnit.Framework.Assert.AreEqual(expected, actual);
        }
Beispiel #2
0
 private void ApplyRotation(SvgDrawContext context)
 {
     if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.ORIENT))
     {
         String orient   = this.attributesAndStyles.Get(SvgConstants.Attributes.ORIENT);
         double rotAngle = double.NaN;
         // If placed by marker-start, the marker is oriented 180° different from
         // the orientation that would be used if auto was specified.
         // For all other markers, auto-start-reverse means the same as auto.
         if (SvgConstants.Values.AUTO.Equals(orient) || (SvgConstants.Values.AUTO_START_REVERSE.Equals(orient) && !
                                                         SvgConstants.Attributes.MARKER_START.Equals(this.attributesAndStyles.Get(SvgConstants.Tags.MARKER))))
         {
             rotAngle = ((IMarkerCapable)GetParent()).GetAutoOrientAngle(this, false);
         }
         else
         {
             if (SvgConstants.Values.AUTO_START_REVERSE.Equals(orient) && SvgConstants.Attributes.MARKER_START.Equals(this
                                                                                                                      .attributesAndStyles.Get(SvgConstants.Tags.MARKER)))
             {
                 rotAngle = ((IMarkerCapable)GetParent()).GetAutoOrientAngle(this, true);
             }
             else
             {
                 if (CssUtils.IsAngleValue(orient) || CssUtils.IsNumericValue(orient))
                 {
                     rotAngle = CssUtils.ParseAngle(this.attributesAndStyles.Get(SvgConstants.Attributes.ORIENT));
                 }
             }
         }
         if (!double.IsNaN(rotAngle))
         {
             context.GetCurrentCanvas().ConcatMatrix(AffineTransform.GetRotateInstance(rotAngle));
         }
     }
 }
        /// <exception cref="System.Exception"/>
        private static byte[] CreatePdfWithRotatedText(String text1, String text2, float rotation, bool moveTextToNextLine
                                                       , float moveTextDelta)
        {
            MemoryStream byteStream = new MemoryStream();
            PdfDocument  document   = new PdfDocument(new PdfWriter(byteStream));

            document.SetDefaultPageSize(new PageSize(612, 792));
            PdfCanvas canvas = new PdfCanvas(document.AddNewPage());
            PdfFont   font   = PdfFontFactory.CreateFont(StandardFonts.HELVETICA);
            float     x      = document.GetDefaultPageSize().GetWidth() / 2;
            float     y      = document.GetDefaultPageSize().GetHeight() / 2;

            canvas.ConcatMatrix(AffineTransform.GetTranslateInstance(x, y));
            canvas.MoveTo(-10, 0).LineTo(10, 0).MoveTo(0, -10).LineTo(0, 10).Stroke();
            canvas.BeginText().SetFontAndSize(font, 12).ConcatMatrix(AffineTransform.GetRotateInstance((float)(rotation
                                                                                                               / 180f * Math.PI))).ShowText(text1);
            if (moveTextToNextLine)
            {
                canvas.MoveText(0, moveTextDelta);
            }
            else
            {
                canvas.ConcatMatrix(AffineTransform.GetTranslateInstance(moveTextDelta, 0));
            }
            canvas.ShowText(text2);
            canvas.EndText();
            document.Close();
            return(byteStream.ToArray());
        }
Beispiel #4
0
        protected void ManipulatePdf(String dest)
        {
            PdfDocument srcDoc = new PdfDocument(new PdfReader(SRC));
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));

            float    a4Width  = PageSize.A4.GetWidth();
            float    a4Height = PageSize.A4.GetHeight();
            PageSize pagesize = new PageSize(a4Width * 4, a4Height * 2);

            pdfDoc.SetDefaultPageSize(pagesize);

            int       numberOfPages = srcDoc.GetNumberOfPages();
            int       p             = 1;
            PdfCanvas canvas        = new PdfCanvas(pdfDoc.AddNewPage());

            while ((p - 1) <= numberOfPages)
            {
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 3, 0);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 12, a4Width);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 15, a4Width * 2);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p, a4Width * 3);
                canvas.SaveState();

                // Rotate on 180 degrees and copy pages to the top row.
                AffineTransform at = AffineTransform.GetRotateInstance((float)-Math.PI);
                at.Concatenate(AffineTransform.GetTranslateInstance(0, -a4Height * 2));
                canvas.ConcatMatrix(at);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 4, -a4Width);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 11, -a4Width * 2);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 8, -a4Width * 3);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 7, -a4Width * 4);
                canvas.RestoreState();

                canvas = new PdfCanvas(pdfDoc.AddNewPage());
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 1, 0);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 14, a4Width);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 13, a4Width * 2);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 2, a4Width * 3);
                canvas.SaveState();

                // Rotate on 180 degrees and copy pages to the top row.
                canvas.ConcatMatrix(at);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 6, -a4Width);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 9, -a4Width * 2);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 10, -a4Width * 3);
                CopyPageToDoc(canvas, srcDoc, pdfDoc, p + 5, -a4Width * 4);
                canvas.RestoreState();

                if ((p - 1) / 16 < numberOfPages / 16)
                {
                    canvas = new PdfCanvas(pdfDoc.AddNewPage());
                }

                p += 16;
            }

            pdfDoc.Close();
            srcDoc.Close();
        }
Beispiel #5
0
        private static Point[] BuildCentralRotationCoordinates(Rectangle targetBoundingBox, double angle)
        {
            double          xCenter        = targetBoundingBox.GetX() + targetBoundingBox.GetWidth() / 2;
            AffineTransform rotateInstance = AffineTransform.GetRotateInstance(angle, xCenter, targetBoundingBox.GetY(
                                                                                   ) + targetBoundingBox.GetHeight() / 2);

            return(BuildCoordinates(targetBoundingBox, rotateInstance));
        }
Beispiel #6
0
        public virtual void ThreeRotateValuesTest()
        {
            AffineTransform expected = AffineTransform.GetRotateInstance(MathUtil.ToRadians(23), CssUtils.ParseAbsoluteLength
                                                                             ("58"), CssUtils.ParseAbsoluteLength("57"));
            AffineTransform actual = TransformUtils.ParseTransform("rotate(23, 58, 57)");

            NUnit.Framework.Assert.AreEqual(expected, actual);
        }
Beispiel #7
0
        public virtual void NormalRotateTest()
        {
            AffineTransform expected = AffineTransform.GetRotateInstance(MathUtil.ToRadians(10), CssUtils.ParseAbsoluteLength
                                                                             ("5"), CssUtils.ParseAbsoluteLength("10"));
            AffineTransform actual = TransformUtils.ParseTransform("rotate(10, 5, 10)");

            NUnit.Framework.Assert.AreEqual(expected, actual);
        }
Beispiel #8
0
        protected internal virtual void ApplyRotationLayout(Rectangle layoutBox)
        {
            float angle  = (float)this.GetPropertyAsFloat(Property.ROTATION_ANGLE);
            float x      = occupiedArea.GetBBox().GetX();
            float y      = occupiedArea.GetBBox().GetY();
            float height = occupiedArea.GetBBox().GetHeight();
            float width  = occupiedArea.GetBBox().GetWidth();

            SetProperty(Property.ROTATION_INITIAL_WIDTH, width);
            SetProperty(Property.ROTATION_INITIAL_HEIGHT, height);
            AffineTransform rotationTransform = new AffineTransform();

            // here we calculate and set the actual occupied area of the rotated content
            if (IsPositioned())
            {
                float?rotationPointX = this.GetPropertyAsFloat(Property.ROTATION_POINT_X);
                float?rotationPointY = this.GetPropertyAsFloat(Property.ROTATION_POINT_Y);
                if (rotationPointX == null || rotationPointY == null)
                {
                    // if rotation point was not specified, the most bottom-left point is used
                    rotationPointX = x;
                    rotationPointY = y;
                }
                // transforms apply from bottom to top
                rotationTransform.Translate((float)rotationPointX, (float)rotationPointY);
                // move point back at place
                rotationTransform.Rotate(angle);
                // rotate
                rotationTransform.Translate((float)-rotationPointX, (float)-rotationPointY);
                // move rotation point to origin
                IList <Point> rotatedPoints = TransformPoints(RectangleToPointsList(occupiedArea.GetBBox()), rotationTransform
                                                              );
                Rectangle newBBox = CalculateBBox(rotatedPoints);
                // make occupied area be of size and position of actual content
                occupiedArea.GetBBox().SetWidth(newBBox.GetWidth());
                occupiedArea.GetBBox().SetHeight(newBBox.GetHeight());
                float occupiedAreaShiftX = newBBox.GetX() - x;
                float occupiedAreaShiftY = newBBox.GetY() - y;
                Move(occupiedAreaShiftX, occupiedAreaShiftY);
            }
            else
            {
                rotationTransform = AffineTransform.GetRotateInstance(angle);
                IList <Point> rotatedPoints = TransformPoints(RectangleToPointsList(occupiedArea.GetBBox()), rotationTransform
                                                              );
                float[] shift = CalculateShiftToPositionBBoxOfPointsAt(x, y + height, rotatedPoints);
                foreach (Point point in rotatedPoints)
                {
                    point.SetLocation(point.GetX() + shift[0], point.GetY() + shift[1]);
                }
                Rectangle newBBox = CalculateBBox(rotatedPoints);
                occupiedArea.GetBBox().SetWidth(newBBox.GetWidth());
                occupiedArea.GetBBox().SetHeight(newBBox.GetHeight());
                float heightDiff = height - newBBox.GetHeight();
                Move(0, heightDiff);
            }
        }
 private static Point[] GetRotatedSquareVertices(Point[] orthogonalSquareVertices, double angle, Point squareCenter
                                                 )
 {
     Point[] rotatedSquareVertices = new Point[orthogonalSquareVertices.Length];
     AffineTransform.GetRotateInstance((float)angle).Transform(orthogonalSquareVertices, 0, rotatedSquareVertices
                                                               , 0, rotatedSquareVertices.Length);
     AffineTransform.GetTranslateInstance((float)squareCenter.GetX(), (float)squareCenter.GetY()).Transform(rotatedSquareVertices
                                                                                                            , 0, rotatedSquareVertices, 0, orthogonalSquareVertices.Length);
     return(rotatedSquareVertices);
 }
        private void ApplyConcatMatrix(DrawContext drawContext, float?angle)
        {
            AffineTransform rotationTransform = AffineTransform.GetRotateInstance((float)angle);
            Rectangle       rect          = GetBorderAreaBBox();
            IList <Point>   rotatedPoints = TransformPoints(RectangleToPointsList(rect), rotationTransform);

            float[] shift = CalculateShiftToPositionBBoxOfPointsAt(rect.GetX(), rect.GetY() + rect.GetHeight(), rotatedPoints
                                                                   );
            double[] matrix = new double[6];
            rotationTransform.GetMatrix(matrix);
            drawContext.GetCanvas().ConcatMatrix(matrix[0], matrix[1], matrix[2], matrix[3], shift[0], shift[1]);
        }
        /// <exception cref="System.IO.IOException"/>
        private static TextRenderInfo InitTRI(String text, double angle)
        {
            CanvasGraphicsState gs = new CanvasGraphicsState();

            gs.SetFont(PdfFontFactory.CreateFont());
            gs.SetFontSize(12);
            float[]         matrix    = new float[6];
            AffineTransform transform = AffineTransform.GetRotateInstance(angle);

            transform.GetMatrix(matrix);
            return(new TextRenderInfo(new PdfString(text), gs, new Matrix(matrix[0], matrix[1], matrix[2], matrix[3],
                                                                          matrix[4], matrix[5]), new Stack <CanvasTag>()));
        }
Beispiel #12
0
        /// <summary>
        /// This method creates
        /// <see cref="iText.Kernel.Geom.AffineTransform"/>
        /// instance that could be used
        /// to rotate content inside the occupied area. Be aware that it should be used only after
        /// layout rendering is finished and correct occupied area for the rotated element is calculated.
        /// </summary>
        /// <returns>
        ///
        /// <see cref="iText.Kernel.Geom.AffineTransform"/>
        /// that rotates the content and places it inside occupied area.
        /// </returns>
        protected internal virtual AffineTransform CreateRotationTransformInsideOccupiedArea()
        {
            float?          angle                   = this.GetProperty <float?>(Property.ROTATION_ANGLE);
            AffineTransform rotationTransform       = AffineTransform.GetRotateInstance((float)angle);
            Rectangle       contentBox              = this.GetOccupiedAreaBBox();
            IList <Point>   rotatedContentBoxPoints = TransformPoints(RectangleToPointsList(contentBox), rotationTransform
                                                                      );

            // Occupied area for rotated elements is already calculated on layout in such way to enclose rotated content;
            // therefore we can simply rotate content as is and then shift it to the occupied area.
            float[] shift = CalculateShiftToPositionBBoxOfPointsAt(occupiedArea.GetBBox().GetLeft(), occupiedArea.GetBBox
                                                                       ().GetTop(), rotatedContentBoxPoints);
            rotationTransform.PreConcatenate(AffineTransform.GetTranslateInstance(shift[0], shift[1]));
            return(rotationTransform);
        }
Beispiel #13
0
        private static PdfCanvas AddBasicContent(PdfPage pdfPage, PdfFont font)
        {
            Rectangle lineAnnotRect = new Rectangle(0, 0, PageSize.A4.GetRight(), PageSize.A4.GetTop());

            pdfPage.AddAnnotation(new PdfLinkAnnotation(new Rectangle(100, 600, 100, 20)).SetAction(PdfAction.CreateURI
                                                                                                        ("http://itextpdf.com"))).AddAnnotation(new PdfLineAnnotation(lineAnnotRect, new float[] { lineAnnotRect
                                                                                                                                                                                                   .GetX(), lineAnnotRect.GetY(), lineAnnotRect.GetRight(), lineAnnotRect.GetTop() }).SetColor(ColorConstants
                                                                                                                                                                                                                                                                                               .BLACK));
            PdfCanvas canvas = new PdfCanvas(pdfPage);

            canvas.Rectangle(100, 100, 100, 100).Fill();
            canvas.SaveState().BeginText().SetTextMatrix(AffineTransform.GetRotateInstance(Math.PI / 4, 36, 350)).SetFontAndSize
                (font, 72).ShowText("Hello Helvetica!").EndText().RestoreState();
            return(canvas);
        }
        private static byte[] CreatePdfWithRotatedText(String text1, String text2, float rotation, bool moveTextToNextLine,
                                                       float moveTextDelta)
        {
            MemoryStream byteStream = new MemoryStream();

            Document  document = new Document();
            PdfWriter writer   = PdfWriter.GetInstance(document, byteStream);

            document.SetPageSize(PageSize.LETTER);

            document.Open();

            PdfContentByte cb = writer.DirectContent;

            BaseFont font = BaseFont.CreateFont();

            float x = document.PageSize.Width / 2;
            float y = document.PageSize.Height / 2;

            cb.Transform(AffineTransform.GetTranslateInstance(x, y));

            cb.MoveTo(-10, 0);
            cb.LineTo(10, 0);
            cb.MoveTo(0, -10);
            cb.LineTo(0, 10);
            cb.Stroke();

            cb.BeginText();
            cb.SetFontAndSize(font, 12);
            cb.Transform(AffineTransform.GetRotateInstance(rotation / 180f * Math.PI));
            cb.ShowText(text1);
            if (moveTextToNextLine)
            {
                cb.MoveText(0, moveTextDelta);
            }
            else
            {
                cb.Transform(AffineTransform.GetTranslateInstance(moveTextDelta, 0));
            }
            cb.ShowText(text2);
            cb.EndText();

            document.Close();

            byte[] pdfBytes = byteStream.ToArray();

            return(pdfBytes);
        }
        /// <summary>Creates a rotate transformation.</summary>
        /// <param name="values">values of the transformation</param>
        /// <returns>AffineTransform for the rotate operation</returns>
        private static AffineTransform CreateRotationTransformation(IList <String> values)
        {
            if (values.Count != 1 && values.Count != 3)
            {
                throw new SvgProcessingException(SvgLogMessageConstant.TRANSFORM_INCORRECT_NUMBER_OF_VALUES);
            }
            double angle = MathUtil.ToRadians((float)CssUtils.ParseFloat(values[0]));

            if (values.Count == 3)
            {
                float centerX = CssUtils.ParseAbsoluteLength(values[1]);
                float centerY = CssUtils.ParseAbsoluteLength(values[2]);
                return(AffineTransform.GetRotateInstance(angle, centerX, centerY));
            }
            return(AffineTransform.GetRotateInstance(angle));
        }
 /// <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);
 }
Beispiel #17
0
        private AffineTransform CreateTransform(PdfImportedPage page, int rotation, Rectangle initialPageSize, bool autoResize)
        {
            var docWidth  = _docContent.Right - _docContent.Left;
            var docHeight = _docContent.Top - _docContent.Bottom;

            AffineTransform rotate          = AffineTransform.GetRotateInstance((Math.PI * (360 - rotation)) / 180, 0, 0);
            AffineTransform scale           = AffineTransform.GetScaleInstance(docWidth / page.Width, docHeight / page.Height);
            AffineTransform translateMargin = AffineTransform.GetTranslateInstance(_docContent.LeftMargin - page.BoundingBox.Left + initialPageSize.Left,
                                                                                   _docContent.BottomMargin - page.BoundingBox.Bottom + initialPageSize.Bottom);

            AffineTransform translateRotate = AffineTransform.GetTranslateInstance(0, 0);

            if (rotation % 180 == 90)
            {
                scale = AffineTransform.GetScaleInstance(docWidth / page.Height, docHeight / page.Width);

                translateRotate = AffineTransform.GetTranslateInstance((rotation % 360 == 270) ? page.Height : 0,
                                                                       (rotation % 360 == 90) ? page.Width : 0);
            }
            else if (rotation % 360 == 180)
            {
                translateRotate = AffineTransform.GetTranslateInstance(page.Width, page.Height);;
            }


            AffineTransform transform = AffineTransform.GetTranslateInstance(0, 0);

            if (autoResize)
            {
                transform.preConcatenate(translateMargin);
            }
            transform.preConcatenate(rotate);
            transform.preConcatenate(translateRotate);
            if (autoResize)
            {
                transform.preConcatenate(scale);
            }

            return(transform);
        }
Beispiel #18
0
        private float AdjustPositionAfterRotation(float angle, float maxWidth, float maxHeight)
        {
            if (angle != 0)
            {
                AffineTransform t       = AffineTransform.GetRotateInstance(angle);
                Point           p00     = t.Transform(new Point(0, 0), new Point());
                Point           p01     = t.Transform(new Point(0, height), new Point());
                Point           p10     = t.Transform(new Point((float)width, 0), new Point());
                Point           p11     = t.Transform(new Point((float)width, height), new Point());
                double[]        xValues = new double[] { p01.GetX(), p10.GetX(), p11.GetX() };
                double[]        yValues = new double[] { p01.GetY(), p10.GetY(), p11.GetY() };
                double          minX    = p00.GetX();
                double          minY    = p00.GetY();
                double          maxX    = minX;
                double          maxY    = minY;
                foreach (double x in xValues)
                {
                    minX = Math.Min(minX, x);
                    maxX = Math.Max(maxX, x);
                }
                foreach (double y in yValues)
                {
                    minY = Math.Min(minY, y);
                    maxY = Math.Max(maxY, y);
                }
                height = (float)(maxY - minY);
                width  = (float)(maxX - minX);
                pivotY = (float)(p00.GetY() - minY);
                deltaX = -(float)minX;
            }
            // Rotating image can cause fitting into area problems.
            // So let's find scaling coefficient
            // TODO
            float scaleCoeff = 1;

            // hasProperty(Property) checks only properties field, cannot use it
            if (true.Equals(GetPropertyAsBoolean(Property.AUTO_SCALE)))
            {
                scaleCoeff = Math.Min(maxWidth / (float)width, maxHeight / height);
                height    *= scaleCoeff;
                width     *= scaleCoeff;
            }
            else
            {
                if (null != GetPropertyAsBoolean(Property.AUTO_SCALE_WIDTH) && (bool)GetPropertyAsBoolean(Property.AUTO_SCALE_WIDTH
                                                                                                          ))
                {
                    scaleCoeff = maxWidth / (float)width;
                    height    *= scaleCoeff;
                    width      = maxWidth;
                }
                else
                {
                    if (null != GetPropertyAsBoolean(Property.AUTO_SCALE_HEIGHT) && (bool)GetPropertyAsBoolean(Property.AUTO_SCALE_HEIGHT
                                                                                                               ))
                    {
                        scaleCoeff = maxHeight / height;
                        height     = maxHeight;
                        width     *= scaleCoeff;
                    }
                }
            }
            pivotY *= scaleCoeff;
            return(scaleCoeff);
        }
        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]);
                    }
                }
            }
        }