Пример #1
0
        /// <summary>
        /// Builds the
        /// <see cref="iText.Kernel.Colors.Color"/>
        /// object representing the linear gradient with specified configuration
        /// that fills the target bounding box.
        /// </summary>
        /// <param name="targetBoundingBox">the bounding box to be filled in current space</param>
        /// <param name="contextTransform">
        /// the transformation from the base coordinates space into
        /// the current space. The
        /// <see langword="null"/>
        /// value is valid and can be used
        /// if there is no transformation from base coordinates to current space
        /// specified, or it is equal to identity transformation.
        /// </param>
        /// <param name="document">
        /// the
        /// <see cref="iText.Kernel.Pdf.PdfDocument"/>
        /// for which the linear gradient would be built.
        /// </param>
        /// <returns>
        /// the constructed
        /// <see cref="iText.Kernel.Colors.Color"/>
        /// or
        /// <see langword="null"/>
        /// if no color to be applied
        /// or base gradient vector has been specified
        /// </returns>
        public virtual Color BuildColor(Rectangle targetBoundingBox, AffineTransform contextTransform, PdfDocument
                                        document)
        {
            // TODO: DEVSIX-4136 the document argument would be required for opaque gradients (as we would need to create a mask form xObject)
            Point[] baseCoordinatesVector = GetGradientVector(targetBoundingBox, contextTransform);
            if (baseCoordinatesVector == null || this.stops.IsEmpty())
            {
                // Can not create gradient color with 0 stops or null coordinates vector
                return(null);
            }
            // evaluate actual coordinates and transformation
            AffineTransform shadingTransform = new AffineTransform();

            if (contextTransform != null)
            {
                shadingTransform.Concatenate(contextTransform);
            }
            AffineTransform gradientTransformation = GetCurrentSpaceToGradientVectorSpaceTransformation(targetBoundingBox
                                                                                                        , contextTransform);

            if (gradientTransformation != null)
            {
                try {
                    if (targetBoundingBox != null)
                    {
                        targetBoundingBox = Rectangle.CalculateBBox(JavaUtil.ArraysAsList(gradientTransformation.InverseTransform(
                                                                                              new Point(targetBoundingBox.GetLeft(), targetBoundingBox.GetBottom()), null), gradientTransformation.InverseTransform
                                                                                              (new Point(targetBoundingBox.GetLeft(), targetBoundingBox.GetTop()), null), gradientTransformation.InverseTransform
                                                                                              (new Point(targetBoundingBox.GetRight(), targetBoundingBox.GetBottom()), null), gradientTransformation
                                                                                          .InverseTransform(new Point(targetBoundingBox.GetRight(), targetBoundingBox.GetTop()), null)));
                    }
                    shadingTransform.Concatenate(gradientTransformation);
                }
                catch (NoninvertibleTransformException) {
                    LogManager.GetLogger(GetType()).Error(iText.IO.LogMessageConstant.UNABLE_TO_INVERT_GRADIENT_TRANSFORMATION
                                                          );
                }
            }
            PdfShading.Axial axial = CreateAxialShading(baseCoordinatesVector, this.stops, this.spreadMethod, targetBoundingBox
                                                        );
            if (axial == null)
            {
                return(null);
            }
            PdfPattern.Shading shading = new PdfPattern.Shading(axial);
            if (!shadingTransform.IsIdentity())
            {
                double[] matrix = new double[6];
                shadingTransform.GetMatrix(matrix);
                shading.SetMatrix(new PdfArray(matrix));
            }
            return(new PatternColor(shading));
        }
        internal virtual AffineTransform CalculateTransformation(SvgDrawContext context)
        {
            Rectangle viewPort   = context.GetCurrentViewPort();
            float     horizontal = viewPort.GetX();
            float     vertical   = viewPort.GetY() + viewPort.GetHeight();
            // flip coordinate space vertically and translate on the y axis with the viewport height
            AffineTransform transform = AffineTransform.GetTranslateInstance(0, 0);

            //Identity-transform
            transform.Concatenate(AffineTransform.GetTranslateInstance(horizontal, vertical));
            transform.Concatenate(new AffineTransform(1, 0, 0, -1, 0, 0));
            return(transform);
        }
Пример #3
0
        private AffineTransform GetGradientTransformToUserSpaceOnUse(Rectangle objectBoundingBox, bool isObjectBoundingBox
                                                                     )
        {
            AffineTransform gradientTransform = new AffineTransform();

            if (isObjectBoundingBox)
            {
                gradientTransform.Translate(objectBoundingBox.GetX(), objectBoundingBox.GetY());
                // We need to scale with dividing the lengths by 0.75 as further we should
                // concatenate gradient transformation matrix which has no absolute parsing.
                // For example, if gradientTransform is set to translate(1, 1) and gradientUnits
                // is set to "objectBoundingBox" then the gradient should be shifted horizontally
                // and vertically exactly by the size of the element bounding box. So, again,
                // as we parse translate(1, 1) to translation(0.75, 0.75) the bounding box in
                // the gradient vector space should be 0.75x0.75 in order for such translation
                // to shift by the complete size of bounding box.
                gradientTransform.Scale(objectBoundingBox.GetWidth() / 0.75, objectBoundingBox.GetHeight() / 0.75);
            }
            AffineTransform svgGradientTransformation = GetGradientTransform();

            if (svgGradientTransformation != null)
            {
                gradientTransform.Concatenate(svgGradientTransformation);
            }
            return(gradientTransform);
        }
Пример #4
0
        public override void DrawBackground(DrawContext drawContext)
        {
            PdfCanvas canvas = drawContext.GetCanvas();
            Matrix    ctm    = canvas.GetGraphicsState().GetCtm();
            // Avoid rotation
            float?angle         = this.GetPropertyAsFloat(Property.ROTATION_ANGLE);
            bool  avoidRotation = null != angle && null != this.GetProperty <Background>(Property.BACKGROUND);

            if (avoidRotation)
            {
                AffineTransform transform = new AffineTransform(ctm.Get(0), ctm.Get(1), ctm.Get(3), ctm.Get(4), ctm.Get(6)
                                                                , ctm.Get(7));
                try {
                    transform = transform.CreateInverse();
                }
                catch (NoninvertibleTransformException e) {
                    throw new Exception(e.Message, e);
                }
                transform.Concatenate(new AffineTransform());
                canvas.ConcatMatrix(transform);
                DeleteProperty(Property.ROTATION_ANGLE);
            }
            base.DrawBackground(drawContext);
            // restore concat matrix and rotation angle
            if (avoidRotation)
            {
                SetProperty(Property.ROTATION_ANGLE, angle);
                canvas.ConcatMatrix(new AffineTransform(ctm.Get(0), ctm.Get(1), ctm.Get(3), ctm.Get(4), ctm.Get(6), ctm.Get
                                                            (7)));
            }
        }
Пример #5
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();
        }
        private static AffineTransform GetTextTransform(float[][] absolutePositions, SvgDrawContext context)
        {
            AffineTransform tf = new AffineTransform();

            //If x is not specified, but y is, we need to correct for preceding text.
            if (absolutePositions[0] == null && absolutePositions[1] != null)
            {
                absolutePositions[0] = new float[] { context.GetTextMove()[0] };
            }
            //If y is not present, we can replace it with a neutral transformation (0.0f)
            if (absolutePositions[1] == null)
            {
                absolutePositions[1] = new float[] { 0.0f };
            }
            tf.Concatenate(TEXTFLIP);
            tf.Concatenate(AffineTransform.GetTranslateInstance(absolutePositions[0][0], -absolutePositions[1][0]));
            return(tf);
        }
Пример #7
0
        /// <summary>
        /// Creates and returns a <seealso cref="PaintContext"/> used to
        /// generate a circular radial color gradient pattern.
        /// See the description of the <seealso cref="Paint#createContext createContext"/> method
        /// for information on null parameter handling.
        /// </summary>
        /// <param name="cm"> the preferred <seealso cref="ColorModel"/> which represents the most convenient
        ///           format for the caller to receive the pixel data, or {@code null}
        ///           if there is no preference. </param>
        /// <param name="deviceBounds"> the device space bounding box
        ///                     of the graphics primitive being rendered. </param>
        /// <param name="userBounds"> the user space bounding box
        ///                   of the graphics primitive being rendered. </param>
        /// <param name="transform"> the <seealso cref="AffineTransform"/> from user
        ///              space into device space. </param>
        /// <param name="hints"> the set of hints that the context object can use to
        ///              choose between rendering alternatives. </param>
        /// <returns> the {@code PaintContext} for
        ///         generating color patterns. </returns>
        /// <seealso cref= Paint </seealso>
        /// <seealso cref= PaintContext </seealso>
        /// <seealso cref= ColorModel </seealso>
        /// <seealso cref= Rectangle </seealso>
        /// <seealso cref= Rectangle2D </seealso>
        /// <seealso cref= AffineTransform </seealso>
        /// <seealso cref= RenderingHints </seealso>
        public override PaintContext CreateContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform transform, RenderingHints hints)
        {
            // avoid modifying the user's transform...
            transform = new AffineTransform(transform);
            // incorporate the gradient transform
            transform.Concatenate(GradientTransform);

            return(new RadialGradientPaintContext(this, cm, deviceBounds, userBounds, transform, hints, (float)Center.X, (float)Center.Y, Radius_Renamed, (float)Focus.X, (float)Focus.Y, Fractions_Renamed, Colors_Renamed, CycleMethod_Renamed, ColorSpace_Renamed));
        }
Пример #8
0
        /// <summary>
        /// Creates and returns a <seealso cref="PaintContext"/> used to
        /// generate a linear color gradient pattern.
        /// See the <seealso cref="Paint#createContext specification"/> of the
        /// method in the <seealso cref="Paint"/> interface for information
        /// on null parameter handling.
        /// </summary>
        /// <param name="cm"> the preferred <seealso cref="ColorModel"/> which represents the most convenient
        ///           format for the caller to receive the pixel data, or {@code null}
        ///           if there is no preference. </param>
        /// <param name="deviceBounds"> the device space bounding box
        ///                     of the graphics primitive being rendered. </param>
        /// <param name="userBounds"> the user space bounding box
        ///                   of the graphics primitive being rendered. </param>
        /// <param name="transform"> the <seealso cref="AffineTransform"/> from user
        ///              space into device space. </param>
        /// <param name="hints"> the set of hints that the context object can use to
        ///              choose between rendering alternatives. </param>
        /// <returns> the {@code PaintContext} for
        ///         generating color patterns. </returns>
        /// <seealso cref= Paint </seealso>
        /// <seealso cref= PaintContext </seealso>
        /// <seealso cref= ColorModel </seealso>
        /// <seealso cref= Rectangle </seealso>
        /// <seealso cref= Rectangle2D </seealso>
        /// <seealso cref= AffineTransform </seealso>
        /// <seealso cref= RenderingHints </seealso>
        public override PaintContext CreateContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform transform, RenderingHints hints)
        {
            // avoid modifying the user's transform...
            transform = new AffineTransform(transform);
            // incorporate the gradient transform
            transform.Concatenate(GradientTransform);

            if ((Fractions_Renamed.Length == 2) && (CycleMethod_Renamed != CycleMethod.REPEAT) && (ColorSpace_Renamed == ColorSpaceType.SRGB))
            {
                // faster to use the basic GradientPaintContext for this
                // common case
                bool cyclic = (CycleMethod_Renamed != CycleMethod.NO_CYCLE);
                return(new GradientPaintContext(cm, Start, End, transform, Colors_Renamed[0], Colors_Renamed[1], cyclic));
            }
            else
            {
                return(new LinearGradientPaintContext(this, cm, deviceBounds, userBounds, transform, hints, Start, End, Fractions_Renamed, Colors_Renamed, CycleMethod_Renamed, ColorSpace_Renamed));
            }
        }
Пример #9
0
        protected void ManipulatePdf(String dest)
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest));
            ImageData   image  = ImageDataFactory.Create(IMG);

            // Translation defines the position of the image on the page and scale transformation sets image dimensions
            // Please also note that image without scaling is drawn in 1x1 rectangle. And here we draw image on page using
            // its original size in pixels.
            AffineTransform affineTransform = AffineTransform.GetTranslateInstance(36, 300);

            // Make sure that the image is visible by concatenating a scale transformation
            affineTransform.Concatenate(AffineTransform.GetScaleInstance(image.GetWidth(), image.GetHeight()));

            PdfCanvas canvas = new PdfCanvas(pdfDoc.GetFirstPage());

            float[] matrix = new float[6];
            affineTransform.GetMatrix(matrix);
            canvas.AddImageWithTransformationMatrix(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
            pdfDoc.Close();
        }
Пример #10
0
        /// <summary>Evaluates the minimal domain that covers the box with vector normals.</summary>
        /// <remarks>
        /// Evaluates the minimal domain that covers the box with vector normals.
        /// The domain corresponding to the initial vector is [0, 1].
        /// </remarks>
        /// <param name="coords">
        /// the array of exactly two elements that describe
        /// the base vector (corresponding to [0,1] domain, that need to be adjusted
        /// to cover the box
        /// </param>
        /// <param name="toCover">the box that needs to be covered</param>
        /// <returns>
        /// the array of two elements in ascending order specifying the calculated covering
        /// domain
        /// </returns>
        protected internal static double[] EvaluateCoveringDomain(Point[] coords, Rectangle toCover)
        {
            if (toCover == null)
            {
                return(new double[] { 0d, 1d });
            }
            AffineTransform transform = new AffineTransform();
            double          scale     = 1d / (coords[0].Distance(coords[1]));
            double          sin       = -(coords[1].GetY() - coords[0].GetY()) * scale;
            double          cos       = (coords[1].GetX() - coords[0].GetX()) * scale;

            if (Math.Abs(cos) < ZERO_EPSILON)
            {
                cos = 0d;
                sin = sin > 0d ? 1d : -1d;
            }
            else
            {
                if (Math.Abs(sin) < ZERO_EPSILON)
                {
                    sin = 0d;
                    cos = cos > 0d ? 1d : -1d;
                }
            }
            transform.Concatenate(new AffineTransform(cos, sin, -sin, cos, 0, 0));
            transform.Scale(scale, scale);
            transform.Translate(-coords[0].GetX(), -coords[0].GetY());
            Point[] rectanglePoints = toCover.ToPointsArray();
            double  minX            = transform.Transform(rectanglePoints[0], null).GetX();
            double  maxX            = minX;

            for (int i = 1; i < rectanglePoints.Length; ++i)
            {
                double currentX = transform.Transform(rectanglePoints[i], null).GetX();
                minX = Math.Min(minX, currentX);
                maxX = Math.Max(maxX, currentX);
            }
            return(new double[] { minX, maxX });
        }
Пример #11
0
        /// <summary>Converts a string containing a transform declaration into an AffineTransform object.</summary>
        /// <remarks>
        /// Converts a string containing a transform declaration into an AffineTransform object.
        /// This class only supports the transformations as described in the SVG specification:
        /// - matrix
        /// - translate
        /// - skewx
        /// - skewy
        /// - rotate
        /// - scale
        /// </remarks>
        /// <param name="transform">value to be parsed</param>
        /// <returns>the AffineTransform object</returns>
        public static AffineTransform ParseTransform(String transform)
        {
            if (transform == null)
            {
                throw new SvgProcessingException(SvgLogMessageConstant.TRANSFORM_NULL);
            }
            if (String.IsNullOrEmpty(transform))
            {
                throw new SvgProcessingException(SvgLogMessageConstant.TRANSFORM_EMPTY);
            }
            AffineTransform matrix = new AffineTransform();
            IList <String>  listWithTransformations = SplitString(transform);

            foreach (String transformation in listWithTransformations)
            {
                AffineTransform newMatrix = TransformationStringToMatrix(transformation);
                if (newMatrix != null)
                {
                    matrix.Concatenate(newMatrix);
                }
            }
            return(matrix);
        }
Пример #12
0
        /// <summary>
        /// When in the svg element
        /// <c>overflow</c>
        /// is
        /// <c>visible</c>
        /// the corresponding formXObject
        /// should have a BBox (form XObject’s bounding box; see PDF 32000-1:2008 - 8.10.2 Form Dictionaries)
        /// that should cover the entire svg space (page in pdf) in order to be able to show parts of the element which are outside the current element viewPort.
        /// </summary>
        /// <remarks>
        /// When in the svg element
        /// <c>overflow</c>
        /// is
        /// <c>visible</c>
        /// the corresponding formXObject
        /// should have a BBox (form XObject’s bounding box; see PDF 32000-1:2008 - 8.10.2 Form Dictionaries)
        /// that should cover the entire svg space (page in pdf) in order to be able to show parts of the element which are outside the current element viewPort.
        /// To do this, we get the inverse matrix of all the current transformation matrix changes and apply it to the root viewPort.
        /// This allows you to get the root rectangle in the final coordinate system.
        /// </remarks>
        /// <param name="context">current context to get canvases and view ports</param>
        /// <param name="stream">stream to write a BBox</param>
        private static void WriteBBoxAccordingToVisibleOverflow(SvgDrawContext context, PdfStream stream)
        {
            IList <PdfCanvas> canvases = new List <PdfCanvas>();
            int canvasesSize           = context.Size();

            for (int i = 0; i < canvasesSize; i++)
            {
                canvases.Add(context.PopCanvas());
            }
            AffineTransform transform = new AffineTransform();

            for (int i = canvases.Count - 1; i >= 0; i--)
            {
                PdfCanvas canvas = canvases[i];
                Matrix    matrix = canvas.GetGraphicsState().GetCtm();
                transform.Concatenate(new AffineTransform(matrix.Get(0), matrix.Get(1), matrix.Get(3), matrix.Get(4), matrix
                                                          .Get(6), matrix.Get(7)));
                context.PushCanvas(canvas);
            }
            try {
                transform = transform.CreateInverse();
            }
            catch (NoninvertibleTransformException) {
                // Case with zero determiner (see PDF 32000-1:2008 - 8.3.4 Transformation Matrices - NOTE 3)
                // for example with a, b, c, d in cm equal to 0
                stream.Put(PdfName.BBox, new PdfArray(new Rectangle(0, 0, 0, 0)));
                ILog logger = LogManager.GetLogger(typeof(AbstractBranchSvgNodeRenderer));
                logger.Warn(SvgLogMessageConstant.UNABLE_TO_GET_INVERSE_MATRIX_DUE_TO_ZERO_DETERMINANT);
                return;
            }
            Point[] points = context.GetRootViewPort().ToPointsArray();
            transform.Transform(points, 0, points, 0, points.Length);
            Rectangle bbox = Rectangle.CalculateBBox(JavaUtil.ArraysAsList(points));

            stream.Put(PdfName.BBox, new PdfArray(bbox));
        }
Пример #13
0
 public virtual void ConcetenateTransform(AffineTransform modTransform)
 {
     Usr2dev.Concatenate(modTransform);
 }