/// <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); }
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); }
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))); } }
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); }
/// <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)); }
/// <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)); } }
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(); }
/// <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 }); }
/// <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); }
/// <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)); }
public virtual void ConcetenateTransform(AffineTransform modTransform) { Usr2dev.Concatenate(modTransform); }