private void DrawText(PdfWriter writer, string text, int fontSize, BaseColor color, double x, double y, bool vertical) { AffineTransform textTransform = AffineTransform.GetTranslateInstance(x, y); if (vertical) { textTransform.Rotate(Math.PI / 2); } //writer.DirectContent.Transform(rotate90); PdfContentByte cb = writer.DirectContent; cb.BeginText(); ////BaseFont textFont = BaseFont.CreateFont("Arial", BaseFont.CP1252, true); cb.SetColorStroke(color); cb.SetColorFill(color); cb.SetFontAndSize(SearchTextFont.GetCalculatedBaseFont(false), fontSize); cb.SetTextMatrix(textTransform); //(xPos, yPos) cb.ShowText(text); cb.EndText(); }
public override void SetTransformation(double translateX, double translateY, double rotate, double scaleX, double scaleY) { translateX *= MmToPt; translateY *= MmToPt; _canvas.RestoreState(); _lastStrokingColor = 0; _lastNonStrokingColor = 0; _lastLineWidth = 1; _lastFont = null; _lastFontSize = 0; _canvas.SaveState(); AffineTransform matrix = new AffineTransform(); matrix.Translate(translateX, translateY); if (rotate != 0) { matrix.Rotate(rotate); } if (scaleX != 1 || scaleY != 1) { matrix.Scale(scaleX, scaleY); } _canvas.ConcatMatrix(matrix); }
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 byte[] CreatePdfWithRotatedXObject(String xobjectText) { MemoryStream baos = new MemoryStream(); Document doc = new Document(); PdfWriter writer = PdfWriter.GetInstance(doc, baos); writer.CompressionLevel = 0; doc.Open(); doc.Add(new Paragraph("A")); doc.Add(new Paragraph("B")); bool rotate = true; PdfTemplate template = writer.DirectContent.CreateTemplate(20, 100); template.SetColorStroke(BaseColor.GREEN); template.Rectangle(0, 0, template.Width, template.Height); template.Stroke(); AffineTransform tx = new AffineTransform(); if (rotate) { tx.Translate(0, template.Height); tx.Rotate(-90 / 180f * Math.PI); } template.Transform(tx); template.BeginText(); template.SetFontAndSize(BaseFont.CreateFont(), 12); if (rotate) { template.MoveText(0, template.Width - 12); } else { template.MoveText(0, template.Height - 12); } template.ShowText(xobjectText); template.EndText(); Image xobjectImage = Image.GetInstance(template); if (rotate) { xobjectImage.RotationDegrees = 90; } doc.Add(xobjectImage); doc.Add(new Paragraph("C")); doc.Close(); return(baos.ToArray()); }
public virtual void BuilderWithNoneSpreadingAndCanvasTransformTest() { AbstractLinearGradientBuilder gradientBuilder = new StrategyBasedLinearGradientBuilder().SetGradientDirectionAsStrategy (StrategyBasedLinearGradientBuilder.GradientStrategy.TO_RIGHT).SetSpreadMethod(GradientSpreadMethod.NONE ).AddColorStop(new GradientColorStop(ColorConstants.RED.GetColorValue(), 0d, GradientColorStop.OffsetType .RELATIVE)).AddColorStop(new GradientColorStop(ColorConstants.GREEN.GetColorValue(), 0.5, GradientColorStop.OffsetType .RELATIVE)).AddColorStop(new GradientColorStop(ColorConstants.BLUE.GetColorValue(), 1d, GradientColorStop.OffsetType .RELATIVE)); AffineTransform canvasTransform = AffineTransform.GetTranslateInstance(50, -50); canvasTransform.Scale(0.8, 1.1); canvasTransform.Rotate(Math.PI / 3, 400f, 550f); GenerateAndComparePdfs("builderWithNoneSpreadingAndCanvasTransformTest.pdf", canvasTransform, gradientBuilder ); }
private void AddLinearGradientITextAPIApproach(PdfDocument pdfDoc) { AbstractLinearGradientBuilder gradientBuilder = new StrategyBasedLinearGradientBuilder() .SetGradientDirectionAsStrategy(StrategyBasedLinearGradientBuilder.GradientStrategy.TO_TOP_RIGHT) .SetSpreadMethod(GradientSpreadMethod.PAD) .AddColorStop(new GradientColorStop(ColorConstants.CYAN.GetColorValue())) .AddColorStop(new GradientColorStop(ColorConstants.GREEN.GetColorValue())) .AddColorStop(new GradientColorStop(new float[] { 1f, 0f, 0f }, 0.5f, GradientColorStop.OffsetType.RELATIVE)); AffineTransform canvasTransform = AffineTransform.GetTranslateInstance(50, -50); canvasTransform.Scale(0.8, 1.1); canvasTransform.Rotate(Math.PI / 3, 400f, 550f); Rectangle rectangleToDraw = new Rectangle(50f, 450f, 500f, 300f); GeneratePdf(pdfDoc, canvasTransform, gradientBuilder, rectangleToDraw); }
protected internal virtual float[] ApplyRotation() { float dx = 0; float dy = 0; if (!IsPositioned()) { Point shift = GetLayoutShiftAndRotatedPoints(new List <Point>(), 0, 0); dy = (float)shift.GetY(); dx = (float)shift.GetX(); } float? angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); AffineTransform transform = new AffineTransform(); transform.Rotate((float)angle); float[] ctm = new float[6]; transform.GetMatrix(ctm); ctm[4] = (float)this.GetPropertyAsFloat(Property.ROTATION_POINT_X) + dx; ctm[5] = (float)this.GetPropertyAsFloat(Property.ROTATION_POINT_Y) + dy; return(ctm); }
/// <exception cref="System.Exception"/> private byte[] CreatePdfWithRotatedXObject(String xobjectText) { MemoryStream baos = new MemoryStream(); PdfDocument pdfDocument = new PdfDocument(new PdfWriter(baos).SetCompressionLevel(0)); Document document = new Document(pdfDocument); document.Add(new Paragraph("A")); document.Add(new Paragraph("B")); PdfFormXObject template = new PdfFormXObject(new Rectangle(20, 100)); PdfCanvas canvas = new PdfCanvas(template, pdfDocument); canvas.SetStrokeColor(Color.GREEN).Rectangle(0, 0, template.GetWidth(), template.GetHeight()).Stroke(); AffineTransform tx = new AffineTransform(); tx.Translate(0, template.GetHeight()); tx.Rotate((float)(-90 / 180f * Math.PI)); canvas.ConcatMatrix(tx).BeginText().SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA), 12) .MoveText(0, template.GetWidth() - 12).ShowText(xobjectText).EndText(); document.Add(new Image(template).SetRotationAngle(Math.PI / 2)).Add(new Paragraph("C")); document.Close(); return(baos.ToArray()); }
private Point GetLayoutShiftAndRotatedPoints(IList <Point> rotatedPoints, float shiftX, float shiftY) { float angle = (float)this.GetPropertyAsFloat(Property.ROTATION_ANGLE); float width = (float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_WIDTH); float height = (float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_HEIGHT); float left = occupiedArea.GetBBox().GetX() - shiftX; float bottom = occupiedArea.GetBBox().GetY() - shiftY; float right = left + width; float top = bottom + height; AffineTransform rotateTransform = new AffineTransform(); rotateTransform.Rotate(angle); TransformBBox(left, bottom, right, top, rotateTransform, rotatedPoints); double minX = double.MaxValue; double maxY = -double.MaxValue; foreach (Point point in rotatedPoints) { if (point.GetX() < minX) { minX = point.GetX(); } if (point.GetY() > maxY) { maxY = point.GetY(); } } float dx = (float)(left - minX); float dy = (float)(top - maxY); foreach (Point point_1 in rotatedPoints) { point_1.SetLocation(point_1.GetX() + dx + shiftX, point_1.GetY() + dy + shiftY); } return(new Point(dx, dy)); }
public override LayoutResult Layout(LayoutContext layoutContext) { LayoutArea area = layoutContext.GetArea().Clone(); Rectangle layoutBox = area.GetBBox(); ApplyMargins(layoutBox, false); occupiedArea = new LayoutArea(area.GetPageNumber(), new Rectangle(layoutBox.GetX(), layoutBox.GetY() + layoutBox .GetHeight(), 0, 0)); width = RetrieveWidth(layoutBox.GetWidth()); float? angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); PdfXObject xObject = ((Image)(GetModelElement())).GetXObject(); imageWidth = xObject.GetWidth(); imageHeight = xObject.GetHeight(); width = width == null ? imageWidth : width; height = (float)width / imageWidth * imageHeight; fixedXPosition = this.GetPropertyAsFloat(Property.X); fixedYPosition = this.GetPropertyAsFloat(Property.Y); float? horizontalScaling = this.GetPropertyAsFloat(Property.HORIZONTAL_SCALING, 1f); float? verticalScaling = this.GetPropertyAsFloat(Property.VERTICAL_SCALING, 1f); AffineTransform t = new AffineTransform(); if (xObject is PdfFormXObject && width != imageWidth) { horizontalScaling *= width / imageWidth; verticalScaling *= height / imageHeight; } if (horizontalScaling != 1) { if (xObject is PdfFormXObject) { t.Scale((float)horizontalScaling, 1); } width *= (float)horizontalScaling; } if (verticalScaling != 1) { if (xObject is PdfFormXObject) { t.Scale(1, (float)verticalScaling); } height *= (float)verticalScaling; } float imageItselfScaledWidth = (float)width; float imageItselfScaledHeight = (float)height; // See in adjustPositionAfterRotation why angle = 0 is necessary if (null == angle) { angle = 0f; } t.Rotate((float)angle); float scaleCoef = AdjustPositionAfterRotation((float)angle, layoutBox.GetWidth(), layoutBox.GetHeight()); imageItselfScaledHeight *= scaleCoef; imageItselfScaledWidth *= scaleCoef; if (xObject is PdfFormXObject) { t.Scale(scaleCoef, scaleCoef); } GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); // indicates whether the placement is forced bool isPlacingForced = false; if (width > layoutBox.GetWidth() || height > layoutBox.GetHeight()) { if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { isPlacingForced = true; } else { return(new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this)); } } occupiedArea.GetBBox().MoveDown(height); occupiedArea.GetBBox().SetHeight(height); occupiedArea.GetBBox().SetWidth((float)width); float leftMargin = (float)this.GetPropertyAsFloat(Property.MARGIN_LEFT); float topMargin = (float)this.GetPropertyAsFloat(Property.MARGIN_TOP); if (leftMargin != 0 || topMargin != 0) { TranslateImage(leftMargin, topMargin, t); GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); } ApplyMargins(occupiedArea.GetBBox(), true); return(new LayoutResult(LayoutResult.FULL, occupiedArea, null, null, isPlacingForced ? this : null)); }
public bool AddWaterMarkerToPdf(string pdfFile, string destFile, string text, string fontFamily, string fontColor, int fontSize = 50) { if (File.Exists(pdfFile)) { try { using (var pr = new PdfReader(pdfFile)) { var rgbColor = System.Drawing.ColorTranslator.FromHtml(fontColor); PdfFont font = fontFamily.Contains("STSong") ? PdfFontFactory.CreateFont(fontFamily, "UniGB-UCS2-H", true) : PdfFontFactory.CreateFont(fontFamily);//PdfFontFactory.CreateFont(fontFamily, "UniGB-UCS2-H", true); if (font != null) { var textLength = font.GetWidth(text, fontSize); var pw = new PdfWriter(destFile); var pdfDoc = new PdfDocument(pr, pw); Rectangle ps; PdfCanvas canvas; var pageCount = pdfDoc.GetNumberOfPages(); for (var i = 1; i < pageCount + 1; i++) { var page = pdfDoc.GetPage(i); ps = page.GetPageSize(); float watermarkTrimmingRectangleWidth = textLength; //Math.Min(ps.GetWidth(), ps.GetHeight()); float watermarkTrimmingRectangleHeight = watermarkTrimmingRectangleWidth; var rotationInRads = MathF.Atan2(ps.GetHeight(), ps.GetWidth()); //var angle = rotationInRads * 180f / MathF.PI; float formWidth = ps.GetWidth(); //watermarkTrimmingRectangleWidth; float formHeight = ps.GetHeight(); //watermarkTrimmingRectangleWidth; float formXOffset = 0; float formYOffset = 0; float xTranslation = (formWidth - watermarkTrimmingRectangleWidth * MathF.Cos(rotationInRads)) / 2; float yTranslation = (formHeight - watermarkTrimmingRectangleWidth * MathF.Sin(rotationInRads)) / 2; //Center the annotation Rectangle watermarkTrimmingRectangle = new Rectangle(0, 0, formWidth, formHeight);//watermarkTrimmingRectangleWidth, watermarkTrimmingRectangleWidth); PdfWatermarkAnnotation watermark = new PdfWatermarkAnnotation(watermarkTrimmingRectangle); //Apply linear algebra rotation math //Create identity matrix AffineTransform transform = new AffineTransform(); //No-args constructor creates the identity transform //Apply translation //transform.Translate(xTranslation, yTranslation); //Apply rotation transform.Translate(xTranslation, yTranslation); transform.Rotate(rotationInRads); PdfFixedPrint fixedPrint = new PdfFixedPrint(); watermark.SetFixedPrint(fixedPrint); //Create appearance Rectangle formRectangle = new Rectangle(formXOffset, formYOffset, formWidth, formHeight); //Observation: font XObject will be resized to fit inside the watermark rectangle PdfFormXObject form = new PdfFormXObject(formRectangle); PdfExtGState gs1 = new PdfExtGState().SetFillOpacity(rgbColor.A / 255f); canvas = new PdfCanvas(form, pdfDoc); float[] transformValues = new float[6]; transform.GetMatrix(transformValues); canvas.SaveState() .BeginText().SetFillColorRgb(rgbColor.R / 225f, rgbColor.G / 225f, rgbColor.B / 255f).SetExtGState(gs1) .SetTextMatrix(transformValues[0], transformValues[1], transformValues[2], transformValues[3], transformValues[4], transformValues[5]) .SetFontAndSize(font, fontSize) .ShowText(text) .EndText() .RestoreState(); canvas.Release(); watermark.SetAppearance(PdfName.N, new PdfAnnotationAppearance(form.GetPdfObject())); watermark.SetFlags(PdfAnnotation.PRINT); page.AddAnnotation(watermark); } pdfDoc.Close(); } else { App.Current.Dispatcher.Invoke(() => { MessageBoxX.Show($"没有找到字体{fontFamily},请确认已安装", "字体错误"); }); return(false); } return(true); } } catch (Exception ex) { Analytics.TrackEvent("PDFError", new Dictionary <string, string> { ["message"] = ex.ToString() }); } finally { File.Delete(pdfFile); } } return(false); }
public override LayoutResult Layout(LayoutContext layoutContext) { LayoutArea area = layoutContext.GetArea().Clone(); Rectangle layoutBox = area.GetBBox().Clone(); AffineTransform t = new AffineTransform(); Image modelElement = (Image)(GetModelElement()); PdfXObject xObject = modelElement.GetXObject(); imageWidth = modelElement.GetImageWidth(); imageHeight = modelElement.GetImageHeight(); CalculateImageDimensions(layoutBox, t, xObject); OverflowPropertyValue?overflowX = null != parent?parent.GetProperty <OverflowPropertyValue?>(Property.OVERFLOW_X ) : OverflowPropertyValue.FIT; bool nowrap = false; if (parent is LineRenderer) { nowrap = true.Equals(this.parent.GetOwnProperty <bool?>(Property.NO_SOFT_WRAP_INLINE)); } IList <Rectangle> floatRendererAreas = layoutContext.GetFloatRendererAreas(); float clearHeightCorrection = FloatingHelper.CalculateClearHeightCorrection(this, floatRendererAreas, layoutBox ); FloatPropertyValue?floatPropertyValue = this.GetProperty <FloatPropertyValue?>(Property.FLOAT); if (FloatingHelper.IsRendererFloating(this, floatPropertyValue)) { layoutBox.DecreaseHeight(clearHeightCorrection); FloatingHelper.AdjustFloatedBlockLayoutBox(this, layoutBox, width, floatRendererAreas, floatPropertyValue, overflowX); } else { clearHeightCorrection = FloatingHelper.AdjustLayoutBoxAccordingToFloats(floatRendererAreas, layoutBox, width , clearHeightCorrection, null); } ApplyMargins(layoutBox, false); Border[] borders = GetBorders(); ApplyBorderBox(layoutBox, borders, false); float?declaredMaxHeight = RetrieveMaxHeight(); OverflowPropertyValue?overflowY = null == parent || ((null == declaredMaxHeight || declaredMaxHeight > layoutBox .GetHeight()) && !layoutContext.IsClippedHeight()) ? OverflowPropertyValue.FIT : parent.GetProperty <OverflowPropertyValue? >(Property.OVERFLOW_Y); bool processOverflowX = !IsOverflowFit(overflowX) || nowrap; bool processOverflowY = !IsOverflowFit(overflowY); if (IsAbsolutePosition()) { ApplyAbsolutePosition(layoutBox); } occupiedArea = new LayoutArea(area.GetPageNumber(), new Rectangle(layoutBox.GetX(), layoutBox.GetY() + layoutBox .GetHeight(), 0, 0)); float imageItselfScaledWidth = (float)width; float imageItselfScaledHeight = (float)height; if (IsFixedLayout()) { fixedXPosition = this.GetPropertyAsFloat(Property.LEFT); fixedYPosition = this.GetPropertyAsFloat(Property.BOTTOM); } float?angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); // See in adjustPositionAfterRotation why angle = 0 is necessary if (null == angle) { angle = 0f; } t.Rotate((float)angle); initialOccupiedAreaBBox = GetOccupiedAreaBBox().Clone(); float scaleCoef = AdjustPositionAfterRotation((float)angle, layoutBox.GetWidth(), layoutBox.GetHeight()); imageItselfScaledHeight *= scaleCoef; imageItselfScaledWidth *= scaleCoef; initialOccupiedAreaBBox.MoveDown(imageItselfScaledHeight); initialOccupiedAreaBBox.SetHeight(imageItselfScaledHeight); initialOccupiedAreaBBox.SetWidth(imageItselfScaledWidth); if (xObject is PdfFormXObject) { t.Scale(scaleCoef, scaleCoef); } GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); // indicates whether the placement is forced bool isPlacingForced = false; if (width > layoutBox.GetWidth() || height > layoutBox.GetHeight()) { if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) || (width > layoutBox.GetWidth() && processOverflowX ) || (height > layoutBox.GetHeight() && processOverflowY)) { isPlacingForced = true; } else { ApplyMargins(initialOccupiedAreaBBox, true); ApplyBorderBox(initialOccupiedAreaBBox, true); occupiedArea.GetBBox().SetHeight(initialOccupiedAreaBBox.GetHeight()); return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this)); } } occupiedArea.GetBBox().MoveDown((float)height); if (borders[3] != null) { height += (float)Math.Sin((float)angle) * borders[3].GetWidth(); } occupiedArea.GetBBox().SetHeight((float)height); occupiedArea.GetBBox().SetWidth((float)width); UnitValue leftMargin = this.GetPropertyAsUnitValue(Property.MARGIN_LEFT); if (!leftMargin.IsPointValue()) { ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ImageRenderer)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property .MARGIN_LEFT)); } UnitValue topMargin = this.GetPropertyAsUnitValue(Property.MARGIN_TOP); if (!topMargin.IsPointValue()) { ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ImageRenderer)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property .MARGIN_TOP)); } if (0 != leftMargin.GetValue() || 0 != topMargin.GetValue()) { TranslateImage(leftMargin.GetValue(), topMargin.GetValue(), t); GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); } ApplyBorderBox(occupiedArea.GetBBox(), borders, true); ApplyMargins(occupiedArea.GetBBox(), true); if (angle != 0) { ApplyRotationLayout((float)angle); } float unscaledWidth = occupiedArea.GetBBox().GetWidth() / scaleCoef; MinMaxWidth minMaxWidth = new MinMaxWidth(unscaledWidth, unscaledWidth, 0); UnitValue rendererWidth = this.GetProperty <UnitValue>(Property.WIDTH); if (rendererWidth != null && rendererWidth.IsPercentValue()) { minMaxWidth.SetChildrenMinWidth(0); float coeff = imageWidth / (float)RetrieveWidth(area.GetBBox().GetWidth()); minMaxWidth.SetChildrenMaxWidth(unscaledWidth * coeff); } else { bool autoScale = HasProperty(Property.AUTO_SCALE) && (bool)this.GetProperty <bool?>(Property.AUTO_SCALE); bool autoScaleWidth = HasProperty(Property.AUTO_SCALE_WIDTH) && (bool)this.GetProperty <bool?>(Property.AUTO_SCALE_WIDTH ); if (autoScale || autoScaleWidth) { minMaxWidth.SetChildrenMinWidth(0); } } FloatingHelper.RemoveFloatsAboveRendererBottom(floatRendererAreas, this); LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, floatRendererAreas, layoutContext.GetArea().GetBBox(), clearHeightCorrection, false); ApplyAbsolutePositionIfNeeded(layoutContext); return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea, null, null, isPlacingForced ? this : null ).SetMinMaxWidth(minMaxWidth)); }
static int borderThickness = 1; // It's just 1. Won't really change, but whatever. If you change it, things will get fucky. public static bool MakePDF(Ragecomic comic, string pdffile) { using (System.IO.FileStream fs = new FileStream(pdffile, FileMode.Create)) { int rows = (int)Math.Ceiling((double)comic.panels / 2); int width = rowWidth * 2 + borderThickness * 3; int height = rowHeight * rows + borderThickness * rows + borderThickness; // 239 per row, plus 1 pixel border per row, plus 1 pixel extra border ZipFile drawImageZip = new ZipFile(); bool hasDrawImages = comic.items.getDrawImageCount() > 0; if (hasDrawImages) { drawImageZip.Dispose(); string addition = ""; int nr = 1; while (File.Exists(pdffile + ".drawimages" + addition + ".zip")) { addition = "_" + (nr++).ToString(); } drawImageZip = new ZipFile(pdffile + ".drawimages" + addition + ".zip"); } // Create an instance of the document class which represents the PDF document itself. Rectangle pageSize = new Rectangle(width, height); Document document = new Document(pageSize, 0, 0, 0, 0); // Create an instance to the PDF file by creating an instance of the PDF // Writer class using the document and the filestrem in the constructor. PdfWriter writer = PdfWriter.GetInstance(document, fs); document.AddAuthor("Derp"); document.AddCreator("RagemakerToPDF"); document.AddKeywords("rage, comic"); document.AddSubject("A rage comic"); document.AddTitle("A rage comic"); // Open the document to enable you to write to the document document.Open(); PdfContentByte cb = writer.DirectContent; // Fill background with white Rectangle rect = new iTextSharp.text.Rectangle(0, 0, width, height); rect.BackgroundColor = new BaseColor(255, 255, 255); cb.Rectangle(rect); // Draw grid on bottom if it isn't set to be on top. if (!comic.gridAboveAll && comic.showGrid) { DrawGrid(cb, width, height, rows, comic); } //List<MyMedia.FontFamily> families = MyMedia.Fonts.SystemFontFamilies.ToList(); // This was a neat idea, but it's much too slow //List<string> files = FontFinder.GetFilesForFont("Courier New").ToList(); //string filename = FontFinder.GetSystemFontFileName(families[0].) //Draw.Font testFont = new Draw.Font(new Draw.FontFamily("Courier New"),12f,Draw.FontStyle.Regular | Draw.FontStyle.Bold); string courierPath = FontFinder.GetSystemFontFileName("Courier New", true); string courierBoldPath = FontFinder.GetSystemFontFileName("Courier New", true, Draw.FontStyle.Bold); string tahomaPath = FontFinder.GetSystemFontFileName("Tahoma", true, Draw.FontStyle.Bold); // Define base fonts Font[] fonts = new Font[3]; fonts[0] = new Font(BaseFont.CreateFont(courierPath, BaseFont.CP1252, BaseFont.EMBEDDED)); fonts[1] = new Font(BaseFont.CreateFont(courierBoldPath, BaseFont.CP1252, BaseFont.EMBEDDED)); fonts[2] = new Font(BaseFont.CreateFont(tahomaPath, BaseFont.CP1252, BaseFont.EMBEDDED)); /*fonts[0] = BaseFont.CreateFont("fonts/TRCourierNew.ttf", BaseFont.CP1252, BaseFont.EMBEDDED); * fonts[1] = BaseFont.CreateFont("fonts/TRCourierNewBold.ttf", BaseFont.CP1252, BaseFont.EMBEDDED); * fonts[2] = new Font(BaseFont.CreateFont("fonts/Tahoma-Bold.ttf", BaseFont.CP1252, BaseFont.EMBEDDED));*/ int drawimageindex = 0; int index = 0; foreach (var item in comic.items) { if (item is Face) { Face face = (Face)item; Image pdfImage; System.Drawing.Image faceImage; // If mirroring is necessary, we have to read the image via C# and use RotateFlip, as iTextSharp doesn't support mirroring. if (face.mirrored) { // If it's a JPEG, open it with Flux.JPEG.Core, because the internal JPEG decoder (and also LibJpeg.NET) creates weird dithering artifacts with greyscale JPGs, which some of the rage faces are. if (Path.GetExtension(face.file).ToLower() == ".jpeg" || Path.GetExtension(face.file).ToLower() == ".jpg") { FileStream jpegstream = File.OpenRead("images/" + face.file); FluxJpeg.Core.DecodedJpeg myJpeg = new JpegDecoder(jpegstream).Decode(); // Only use this JPEG decoder if the colorspace is Gray. Otherwise the normal one is just fine. if (myJpeg.Image.ColorModel.colorspace == FluxJpeg.Core.ColorSpace.Gray) { myJpeg.Image.ChangeColorSpace(FluxJpeg.Core.ColorSpace.YCbCr); faceImage = myJpeg.Image.ToBitmap(); } else { faceImage = System.Drawing.Image.FromFile("images/" + face.file); } } else { faceImage = System.Drawing.Image.FromFile("images/" + face.file); } // Apply mirroring faceImage.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipX); pdfImage = Image.GetInstance(faceImage, System.Drawing.Imaging.ImageFormat.Png); } else { // Just let iTextSharp handle it if no mirroring is required. Will also save space (presumably) pdfImage = Image.GetInstance("images/" + face.file); } pdfImage.ScalePercent(face.scalex * 100, face.scaley * 100); pdfImage.Rotation = -(float)Math.PI * face.rotation / 180.0f; pdfImage.SetAbsolutePosition(item.x, (height - item.y) - pdfImage.ScaledHeight); // Set opacity to proper value if (face.opacity < 1) { PdfGState graphicsState = new PdfGState(); graphicsState.FillOpacity = face.opacity; cb.SetGState(graphicsState); } cb.AddImage(pdfImage); // Set back to normal if (face.opacity < 1) { PdfGState graphicsState = new PdfGState(); graphicsState.FillOpacity = 1f; cb.SetGState(graphicsState); } } else if (item is DrawImage) { DrawImage drawimage = (DrawImage)item; drawImageZip.AddEntry("drawimage_" + (drawimageindex++).ToString() + ".png", drawimage.imagedata); System.Drawing.Image pngImage = System.Drawing.Image.FromStream(new MemoryStream(drawimage.imagedata)); Image pdfImage = Image.GetInstance(pngImage, System.Drawing.Imaging.ImageFormat.Png); // Rotation is NOT to be applied. Ragemaker actually has a bug that causes it to save rotated images in their rotated form, but save the rotation value anyway // Thus rotating the image by the rotation value will actually rotate them double compared to what they originally looked like // The irony is that ragemaker *itself* cannot properly load an xml it created with this rotation value, as it will also apply the rotation // As such, this tool is currently the only way to correctly display that .xml file as it was originally meant to look, not even ragemaker itself can properly load it again. //pdfImage.Rotation = -(float)Math.PI * item.rotation / 180.0f; pdfImage.SetAbsolutePosition(item.x, (height - item.y) - pdfImage.ScaledHeight); // Opacity likewise seems to be baked in, and in fact the opacity value doesn't even exist. // Implementing it anyway, in case it ever becomes a thing. if (drawimage.opacity < 1) { PdfGState graphicsState = new PdfGState(); graphicsState.FillOpacity = drawimage.opacity; cb.SetGState(graphicsState); } cb.AddImage(pdfImage); // Set back to normal if (drawimage.opacity < 1) { PdfGState graphicsState = new PdfGState(); graphicsState.FillOpacity = 1f; cb.SetGState(graphicsState); } } else if (item is Text) { int padding = 4; Text text = (Text)item; // Create template PdfTemplate xobject = cb.CreateTemplate(text.width, text.height); // Background color (if set) if (text.bgOn) { Rectangle bgRectangle = new Rectangle(0, 0, text.width, text.height); System.Drawing.Color bgColor = System.Drawing.ColorTranslator.FromHtml(text.bgColor); rect.BackgroundColor = new BaseColor(bgColor.R, bgColor.G, bgColor.B, (int)Math.Floor(text.opacity * 255)); xobject.Rectangle(rect); } // Create text Rectangle textangle = new Rectangle(padding, 0, text.width - padding, text.height); ColumnText ct = new ColumnText(xobject); ct.SetSimpleColumn(textangle); Paragraph paragraph = new Paragraph(text.text); Font myFont = fonts[text.style]; // More specific treatment if it's an AnyFont element which allows the user to select any font and styles, not just the normal 3 presets // This isn't perfect, as the current FontFinder doesn't indicate whether he actually found an Italic/Bold typeface, hence it's not possible // to determine whether faux-italic/faux-bold should be applied. Currently it will only work correctly if each used font has a specific typeface // for the needed styles (bold or italic), otherwise incorrect results. // TODO Fix, for example let FontFinder return array of strings, one of which is indicating the suffix that was found. if (text is AnyFontText) { AnyFontText anyfont = (AnyFontText)text; string fontname = anyfont.font; string fontfile = ""; if (anyfont.bold) { fontfile = FontFinder.GetSystemFontFileName(fontname, true, Draw.FontStyle.Bold); int fontStyle = 0; if (anyfont.italic) { fontStyle |= Font.ITALIC; } if (anyfont.underline) { fontStyle |= Font.UNDERLINE; } myFont = new Font(BaseFont.CreateFont(fontfile, BaseFont.CP1252, BaseFont.EMBEDDED), 100f, fontStyle); } else if (anyfont.italic) { fontfile = FontFinder.GetSystemFontFileName(fontname, true, Draw.FontStyle.Italic); int fontStyle = 0; if (anyfont.underline) { fontStyle |= Font.UNDERLINE; } myFont = new Font(BaseFont.CreateFont(fontfile, BaseFont.CP1252, BaseFont.EMBEDDED), 100f, fontStyle); } else { fontfile = FontFinder.GetSystemFontFileName(fontname, true, Draw.FontStyle.Regular); int fontStyle = 0; if (anyfont.underline) { fontStyle |= Font.UNDERLINE; } myFont = new Font(BaseFont.CreateFont(fontfile, BaseFont.CP1252, BaseFont.EMBEDDED), 100f, fontStyle); } } myFont.Size = text.size; System.Drawing.Color color = (System.Drawing.Color)(new System.Drawing.ColorConverter()).ConvertFromString(text.color); myFont.Color = new BaseColor(color.R, color.G, color.B, (int)Math.Floor(text.opacity * 255)); paragraph.Font = myFont; paragraph.Alignment = text.align == Text.ALIGN.LEFT ? PdfContentByte.ALIGN_LEFT : (text.align == Text.ALIGN.RIGHT ? PdfContentByte.ALIGN_RIGHT : PdfContentByte.ALIGN_CENTER); paragraph.SetLeading(0, 1.12f); ct.AddElement(paragraph); ct.Go(); // Angle to radians float angle = (float)Math.PI * text.rotation / 180.0f; // Calculate Bounding Box size for correct placement later GraphicsPath gp = new GraphicsPath(); gp.AddRectangle(new System.Drawing.Rectangle(0, 0, (int)Math.Round(text.width), (int)Math.Round(text.height))); Matrix translateMatrix = new Matrix(); translateMatrix.RotateAt(text.rotation, new System.Drawing.PointF(text.width / 2, text.height / 2)); gp.Transform(translateMatrix); var gbp = gp.GetBounds(); float newWidth = gbp.Width, newHeight = gbp.Height; // Create correct placement // Background info: I rotate around the center of the text box, thus the center of the text box is what I attempt to place correctly with the initial .Translate() AffineTransform transform = new AffineTransform(); transform.Translate(item.x + newWidth / 2 - text.width / 2, height - (item.y + newHeight / 2 - text.height / 2) - text.height); transform.Rotate(-angle, text.width / 2, text.height / 2); cb.AddTemplate(xobject, transform); } index++; } if (comic.gridAboveAll && comic.showGrid) { DrawGrid(cb, width, height, rows, comic); } //document.Add(new Paragraph("Hello World!")); // Close the document document.Close(); // Close the writer instance writer.Close(); // Always close open filehandles explicity fs.Close(); if (hasDrawImages) { drawImageZip.Save(); } drawImageZip.Dispose(); } return(false); }
public void writePage(Page pPage) { // page size is given per <fotobook/page>. iTextSharp needs it set before adding page or opening document. _doc.SetPageSize(new Rectangle(0f, 0f, pPage.bundleSize.X, pPage.bundleSize.Y)); // handle first page case try { if (!_doc.IsOpen()) { _doc.Open(); } else { _doc.NewPage(); } } catch (Exception e) { Log.Error("Creating pdf page failed with error: '" + e.Message + "'."); return; } PdfContentByte canvas = _writer.DirectContent; // TOOD: de-duplicate // draw left part of background if (pPage.backgroundLeft != null) { canvas.Rectangle(0, 0, pPage.bundleSize.X / 2, pPage.bundleSize.Y); #if DEBUG || _DEBUG canvas.SetColorFill(BaseColor.CYAN); #else canvas.SetColorFill(BaseColor.WHITE); #endif canvas.Fill(); string id = pPage.backgroundLeft; System.Drawing.Image sysImg = DesignIdConverter.getImageFromID(id); if (sysImg == null) { Log.Error("Background image for id '" + id + "' was null."); #if DEBUG || _DEBUG canvas.SetColorFill(BaseColor.MAGENTA); #else canvas.SetColorFill(BaseColor.WHITE); #endif canvas.Fill(); } else { Image img = sysImageToITextImage(sysImg); float facY = pPage.bundleSize.Y / img.PlainHeight; float facX = pPage.bundleSize.X / img.PlainWidth; float fac = Math.Max(facX, facY); img.ScalePercent(fac * 100f); float yoffset = (img.ScaledHeight - pPage.bundleSize.Y) * -0.5f; float xoffset = (img.ScaledWidth - pPage.bundleSize.X) * -0.5f; img.SetAbsolutePosition(xoffset, yoffset); float width = -xoffset + ((pPage.type == Page.Type.Fullcover) ? pPage.bundleSize.X : pPage.bundleSize.X / 2f); Image imgCropped = cropImage(img, _writer, 0, 0, width, img.ScaledHeight); imgCropped.SetAbsolutePosition(xoffset, yoffset); canvas.AddImage(imgCropped); } } // draw right background if (pPage.backgroundRight != null) { canvas.Rectangle(pPage.bundleSize.X / 2, 0, pPage.bundleSize.X / 2, pPage.bundleSize.Y); #if DEBUG || _DEBUG canvas.SetColorFill(BaseColor.CYAN); canvas.SetColorFill(BaseColor.WHITE); #endif canvas.Fill(); string id = pPage.backgroundRight; System.Drawing.Image sysImg = DesignIdConverter.getImageFromID(id); if (sysImg == null) { Log.Error("Background image for id '" + id + "' was null."); #if DEBUG || _DEBUG canvas.SetColorFill(BaseColor.MAGENTA); #else canvas.SetColorFill(BaseColor.WHITE); #endif canvas.Fill(); canvas.Fill(); } else { Image img = sysImageToITextImage(sysImg); float facY = pPage.bundleSize.Y / img.PlainHeight; float facX = pPage.bundleSize.X / img.PlainWidth; float fac = Math.Max(facX, facY); img.ScalePercent(fac * 100f); float yoffset = (img.ScaledHeight - pPage.bundleSize.Y) * -0.5f; float xoffset = (img.ScaledWidth - pPage.bundleSize.X) * -0.5f; img.SetAbsolutePosition(xoffset, yoffset); Image imgCropped = cropImage(img, _writer, pPage.bundleSize.X / 2f, 0, img.ScaledWidth, img.ScaledHeight); imgCropped.SetAbsolutePosition(xoffset + pPage.bundleSize.X / 2, yoffset); canvas.AddImage(imgCropped); } } // draw all supported content areas stored in this page foreach (Area area in pPage.areas) { // calculate rect dimensions // TODO: de-duplicate? float pX = area.rect.X; float pY = pPage.bundleSize.Y - area.rect.Y - area.rect.Height; // handle rotation canvas.SaveState(); AffineTransform tf = new AffineTransform(); double angle = area.rotation * Math.PI / 180.0; tf.Rotate(-angle, pX + area.rect.Width / 2f, pY + area.rect.Height / 2f); // rotate around center ccw canvas.Transform(tf); if (area is ImageArea || area is ImageBackgroundArea) { // TODO: This is somewhat hacky - there is probably a better way to do this. if (area is ImageBackgroundArea) { ImageBackgroundArea bgArea = (ImageBackgroundArea)area; if (bgArea.type == ImageBackgroundArea.ImageBackgroundType.Right) { bgArea.rect.X += pPage.bundleSize.X / 2f + pPage.spineSize / 2f; } } ImageArea imgArea = (ImageArea)area; // if image path was not valid draw magenta outline and print error if (imgArea.path == "NULL") { #if DEBUG || _DEBUG // calculate rect dimensions Rectangle nullRect = new Rectangle(pX, pY, pX + imgArea.rect.Width, pY + imgArea.rect.Height); // configure border nullRect.Border = 1 | 2 | 4 | 8; nullRect.BorderColor = BaseColor.MAGENTA; nullRect.BorderWidth = 4.0f; // draw to document canvas.Rectangle(nullRect); Log.Error("Image path was null. Probably caused by an empty image area."); canvas.RestoreState(); #endif continue; } // load image file. System.Drawing.Image sysImg; try { sysImg = System.Drawing.Image.FromFile(imgArea.path); } catch (System.Exception e) { if (e is System.IO.FileNotFoundException) { Log.Error("Loading image failed. Image at '" + imgArea.path + "' not found."); } else { Log.Error("Loading image failed wit error: '" + e.Message + "'"); } canvas.RestoreState(); continue; } // fix exif orientation ExifRotate(sysImg); // calculate resizing factor, results in equal pixel density for all images. float scale = 1f / imgArea.scale * Config.ImgScale; // the higher this value, the lower pixel density is. 0.0f = original resolution scale = scale < 1.0f ? 1.0f : scale; // never scale image up System.Drawing.Size newSize = new System.Drawing.Size((int)(sysImg.Width / scale), (int)(sysImg.Height / scale)); // resize image sysImg = (System.Drawing.Image)(new System.Drawing.Bitmap(sysImg, newSize)); Image img = sysImageToITextImage(sysImg); // apply scale as defined in .mcf img.ScalePercent(imgArea.scale * 100.0f * scale); // calculate image position in pdf page float posX = imgArea.rect.X + imgArea.cutout.X; float posY = pPage.bundleSize.Y - imgArea.rect.Y - imgArea.rect.Height; // pdf origin is in lower left, mcf origin is in upper left // yaaaaa... whatever. This way everything fits float cropBottom = img.ScaledHeight - imgArea.rect.Height + imgArea.cutout.Y; // crop image to mcf specified rect Image cropped = cropImage(img, _writer, -imgArea.cutout.X, cropBottom, imgArea.rect.Width, imgArea.rect.Height); // move to mcf specified position cropped.SetAbsolutePosition(imgArea.rect.X, posY); string imgType = area is ImageBackgroundArea ? "ImageBackground" : "Image"; Log.Info("Rendering " + imgType + " (." + imgArea.path.Split(".").Last() + "): " + "original: " + sysImg.Width + "x" + sysImg.Height + "; " + "scaled: " + newSize.Width + "x" + newSize.Height + "; " + "cropped: " + (int)cropped.Width + "x" + (int)cropped.Height + "; " + "at: " + (int)cropped.AbsoluteX + ", " + (int)cropped.AbsoluteY); // draw the image canvas.AddImage(cropped); // draw image border if specified in .mcf if (imgArea.border) { // TODO mcf as an outside property that is currently not taken into account. // seems like all borders are 'outside' in photobook. // iTextSharp draws Borders centered (BorderWidth/2 pixels overlap image) // this should be corrected. // calc border rect Rectangle rect = new Rectangle(pX, pY, pX + imgArea.rect.Width, pY + imgArea.rect.Height); // convert .mcf's html style color hex code to Color, based on: https://stackoverflow.com/a/2109904 int argb = Int32.Parse(imgArea.borderColor.Replace("#", ""), System.Globalization.NumberStyles.HexNumber); System.Drawing.Color clr = System.Drawing.Color.FromArgb(argb); // configure border rect.Border = 1 | 2 | 4 | 8; rect.BorderColor = new BaseColor(clr); rect.BorderWidth = imgArea.borderWidth; // draw border canvas.Rectangle(rect); } } else if (area is TextArea) { TextArea textArea = (TextArea)area; // Render text background if not transparent if (!textArea.backgroundcolor.EndsWith("00")) { Log.Info("Rendering Text background: color=" + textArea.backgroundcolor); canvas.Rectangle(pX, pY, textArea.rect.Width, textArea.rect.Height); canvas.SetColorFill(argb2BaseColor(textArea.backgroundcolor)); canvas.Fill(); } // just in case something went wrong if (String.IsNullOrWhiteSpace(textArea.text)) { Log.Error("Text was empty."); canvas.RestoreState(); continue; } else { Log.Info("Rendering Text: font=" + textArea.font + "; size=" + textArea.fontsize + "; align=" + textArea.align + "; valign=" + textArea.valign); } // iTextSharp textbox ColumnText colText = new ColumnText(canvas); // calculate rect float llx = textArea.rect.X; float lly = pPage.bundleSize.Y - textArea.rect.Y - textArea.rect.Height; float urx = llx + textArea.rect.Width; float ury = lly + textArea.rect.Height; Rectangle textRect = new Rectangle(llx, lly, urx, ury); // apply rect to textbox colText.SetSimpleColumn(textRect); // The actual text object Paragraph par = new Paragraph(); // magic number that closely matches photobook // TODO there is probably more information in the .mcf's css part par.SetLeading(0, 1.3f); // apply corrent alignment if (textArea.align == "ALIGNHCENTER") { par.Alignment = Element.ALIGN_CENTER; } else if (textArea.align == "ALIGNLEFT") { par.Alignment = Element.ALIGN_LEFT; } else if (textArea.align == "ALIGNRIGHT") { par.Alignment = Element.ALIGN_RIGHT; } else if (textArea.align == "ALIGNJUSTIFY") { par.Alignment = Element.ALIGN_JUSTIFIED; } else { Log.Warning("Unhandled text align: '" + textArea.align + "'."); } // add text chunks foreach (TextElement elem in textArea.textElements) { int style = 0; style += elem.bold ? Font.BOLD : 0; style += elem.italic ? Font.ITALIC : 0; style += elem.underlined ? Font.UNDERLINE : 0; Font fnt = FontFactory.GetFont(elem.family, elem.size, style, argb2BaseColor(elem.color)); par.Add(new Chunk(elem.text + (elem.newline ? "\n" : " "), fnt)); } int valign = 0; if (textArea.valign == "ALIGNVCENTER") { valign = Element.ALIGN_MIDDLE; } else if (textArea.valign == "ALIGNVTOP") { valign = Element.ALIGN_TOP; } else if (textArea.valign == "ALIGNVBOTTOM") { valign = Element.ALIGN_BOTTOM; } else { Log.Warning("Unhandled text vertical align: '" + textArea.valign + "'."); } // v align needs a table... PdfPTable table = new PdfPTable(1); table.SetWidths(new int[] { 1 }); table.WidthPercentage = 100; table.AddCell(new PdfPCell(par) { HorizontalAlignment = par.Alignment, VerticalAlignment = valign, FixedHeight = textArea.rect.Height, Border = 0, }); // add paragraph to textbox colText.AddElement(table); // draw textbox colText.Go(); } // restore canvas transform before rotation canvas.RestoreState(); } // draw pagenumbers // TODO remove magic numbers, at least comment const float PAGE_NR_Y_OFFSET = -4.0f; const float PAGE_NR_X_OFFSET = 0.0f; float PAGE_NR_FONT_SIZE = Page.pageNoFontSize * 1.1f; float PAGE_NR_HEIGHT = PAGE_NR_FONT_SIZE + 12.0f; // add some extra space... this is needed. float PAGE_Y_POS = Page.pageNoMargin.Y + PAGE_NR_Y_OFFSET; // TODO de-duplicate all these conversions and move to helper method // convert .mcf's html style color hex code to Color, based on: https://stackoverflow.com/a/2109904 int argb_ = Int32.Parse(Page.pageNoColor.Replace("#", ""), System.Globalization.NumberStyles.HexNumber); System.Drawing.Color clr_ = System.Drawing.Color.FromArgb(argb_); // left Paragraph pageNoLeft = new Paragraph(pPage.pageNoLeft, FontFactory.GetFont(Page.pageNoFont, PAGE_NR_FONT_SIZE, new BaseColor(clr_))); pageNoLeft.Alignment = Element.ALIGN_LEFT + Element.ALIGN_BOTTOM; ColumnText leftNo = new ColumnText(_writer.DirectContent); Rectangle leftNoRect = new Rectangle(Page.pageNoMargin.X + PAGE_NR_X_OFFSET, PAGE_Y_POS, 500, PAGE_Y_POS + PAGE_NR_HEIGHT); leftNo.SetSimpleColumn(leftNoRect); leftNo.AddElement(pageNoLeft); leftNo.Go(); //leftNoRect.Border = 1 | 2 | 4 | 8; //leftNoRect.BorderColor = BaseColor.GREEN; //leftNoRect.BorderWidth = 1.0f; //_writer.DirectContent.Rectangle(leftNoRect); // right Paragraph pageNoRight = new Paragraph(pPage.pageNoRight, FontFactory.GetFont(Page.pageNoFont, PAGE_NR_FONT_SIZE, new BaseColor(clr_))); pageNoRight.Alignment = Element.ALIGN_RIGHT; ColumnText rightNo = new ColumnText(_writer.DirectContent); Rectangle rightNoRect = new Rectangle(pPage.bundleSize.X - Page.pageNoMargin.X - PAGE_NR_X_OFFSET - 500, PAGE_Y_POS, pPage.bundleSize.X - Page.pageNoMargin.X - PAGE_NR_X_OFFSET, PAGE_Y_POS + PAGE_NR_HEIGHT); rightNo.SetSimpleColumn(rightNoRect); rightNo.AddElement(pageNoRight); rightNo.Go(); //rightNoRect.Border = 1 | 2 | 4 | 8; //rightNoRect.BorderColor = BaseColor.YELLOW; //rightNoRect.BorderWidth = 1.0f; //_writer.DirectContent.Rectangle(rightNoRect); //Console.WriteLine("Page drawn: " + pPage.type.ToString() + " left: " + pPage.pageNoLeft + "; right: " + pPage.pageNoRight + "!"); }
/// <summary> /// Watermarks a PDF file. /// </summary> /// <paramref name="fileName"/> private void WatermarkPdf(string fileName) { var watermarkText = _operation.WatermarkText; var sourceFile = $"{_operation.SourcePath}\\{fileName}"; var destinationPath = $"{_operation.DestinationPath}\\{PathWatermarked}"; var destinationFile = $"{destinationPath}\\{fileName}"; ValidatePath(destinationPath); const float watermarkTrimmingRectangleWidth = 600; const float watermarkTrimmingRectangleHeight = 600; const float formWidth = 300; const float formHeight = 300; const float formXOffset = 0; const float formYOffset = 0; const float xTranslation = 50; const float yTranslation = 25; const double rotationInRads = Math.PI / 3; try { FontCache.ClearSavedFonts(); } catch (Exception exception) { Log.Error(exception.Message); } var font = PdfFontFactory.CreateFont(StandardFonts.COURIER); const float fontSize = 119; using var reader = new PdfReader(new MemoryStream(File.ReadAllBytes(sourceFile))); using var pdfDoc = new PdfDocument(reader, new PdfWriter(destinationFile)); var numberOfPages = pdfDoc.GetNumberOfPages(); PdfPage page = null; for (var i = 1; i <= numberOfPages; i++) { page = pdfDoc.GetPage(i); var ps = page.GetPageSize(); //Center the annotation var bottomLeftX = ps.GetWidth() / 2 - watermarkTrimmingRectangleWidth / 2; var bottomLeftY = ps.GetHeight() / 2 - watermarkTrimmingRectangleHeight / 2; var watermarkTrimmingRectangle = new Rectangle(bottomLeftX, bottomLeftY, watermarkTrimmingRectangleWidth, watermarkTrimmingRectangleHeight); var watermark = new PdfWatermarkAnnotation(watermarkTrimmingRectangle); //Apply linear algebra rotation math //Create identity matrix var transform = new AffineTransform(); //No-args constructor creates the identity transform //Apply translation transform.Translate(xTranslation, yTranslation); //Apply rotation transform.Rotate(rotationInRads); var fixedPrint = new PdfFixedPrint(); watermark.SetFixedPrint(fixedPrint); //Create appearance var formRectangle = new Rectangle(formXOffset, formYOffset, formWidth, formHeight); //Observation: font XObject will be resized to fit inside the watermark rectangle var form = new PdfFormXObject(formRectangle); var gs1 = new PdfExtGState().SetFillOpacity(0.6f); var canvas = new PdfCanvas(form, pdfDoc); var transformValues = new float[6]; transform.GetMatrix(transformValues); canvas.SaveState() .BeginText().SetColor(ColorConstants.GRAY, true).SetExtGState(gs1) .SetTextMatrix(transformValues[0], transformValues[1], transformValues[2], transformValues[3], transformValues[4], transformValues[5]) .SetFontAndSize(font, fontSize) .ShowText(watermarkText) .EndText() .RestoreState(); canvas.Release(); watermark.SetAppearance(PdfName.N, new PdfAnnotationAppearance(form.GetPdfObject())); watermark.SetFlags(PdfAnnotation.PRINT); page.AddAnnotation(watermark); } page?.Flush(); pdfDoc.Close(); }
public void TranslateAndRotate(double xT, double yT, double rad) { _transform.Translate(xT, yT); _transform.Rotate(rad); }