I'm trying to design a footer, but the footer needs to be absolute on every single page.
Is there a function to grab the bottom of the page? afterward I could just subtract a few pixels and add my footer there.
int bottom = document.GetBottom():
ct.SetSimpleColumn(20, 20, 0, bottom - 20);
something along that line? Thats just pseudo code though.
the iTextSharp document provides document.Bottom which returns the bottom x value (atleast thats what worked for me)
using that I implemented a relative footer
PdfContentByte cb = wri.DirectContent;
ColumnText ct = new ColumnText(cb);
Phrase myText = new Phrase("footer data here", FontFactory.GetFont("Arial Bold", 10.0f, Font.BOLD, BaseColor.BLACK));
float textWidth = myText.Font.GetCalculatedBaseFont(false).GetWidthPoint("AASECT • 1444 I Street, NW • Suite 700 • Washington • DC • 20005 • (202) 449.1099 • info#aasect.org", 10.0f);
ct.SetSimpleColumn((doc.Right / 2) - (textWidth / 2), 1, (doc.Right / 2) + (textWidth / 2), doc.Bottom);
ct.AddText(myText);
ct.Go();
It creates the 'Phase' myText and then calculates the base font to gain access to the .GetWidthPoint to measure the size of the text. figures out the left most x coord by calculating the center of the document and subracting half of the width and repeats the reverse for the right most x coord by adding half of the width of the text
I hope this helps somebody, I found a lot of different 'Methods' of creating a footer and none of them worked, hopefully this meets someones needs.
Related
I have a radar chart in chart.js in which I want to draw the labels as rotated. As I could see inthe doc, it is not possible, so I am trying to do it myself using basic drawing in c#. Here is the code I use :
Bitmap objBmpImage = new Bitmap(1000, 1000);
System.Drawing.Font objFont = new System.Drawing.Font("Arial", 12,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);
Graphics objGraphics = Graphics.FromImage(objBmpImage);
objGraphics.Clear(Color.Transparent);
float angle = (float)360.0 / (float)competences.Count();
objGraphics.TranslateTransform(500, 450);
objGraphics.RotateTransform(-90 - (angle / 3));
foreach (T_Ref_Competence competence in competences)
{
byte r, g, b;
HexToInt(competence.T_Ref_CompetenceNiveau2.T_Ref_CompetenceNiveau1.Couleur,
out r, out g, out b);
Brush brush = new System.Drawing.SolidBrush(Color.FromArgb(255,r,g,b));
objGraphics.DrawString(competence.Nom,objFont, brush, 255,0);
objGraphics.RotateTransform(angle);
}
string filename = Server.MapPath("..\\TempImage\\") + NomUtilisateur + ".png";
objBmpImage.Save(filename,System.Drawing.Imaging.ImageFormat.Png);
HexToInt is just a simple function that takes a #FF0000 and convert it to 3 bytes variables (255,0 and 0 for this exemple).
Here is the result so far :
As you can see, I can get something quite nice. However, I have one last request, which I am pretty sure is possible, but I'm not certain how.
How can I rotate the text 180 degrees for label on the left section ? In this exemple, from "Organisation" to "Vérification qualité et inspection". Mind you, I know how to decide which one I have to turn around, I don't know how to do it.
Thanks.
Idea:
Add 180 degrees to the angle.
Now the labels appear on the wrong side but have the right orientation. Move them by the diameter + textLength to the left. You can do so by providing a negative X to the DrawString call. No need for another transformation.
You can calculate the text length with the Graphics.MeasureString Method.
I have some text in a pdf that has been OCR'ed.
The OCR returns the bounding boxes of the words to me.
I'm able to draw the bounding boxes (wordRect) on the pdf and everything seems correct.
But when i tell my fontsize to be the height of these bounding boxes,
it all goes wrong. The text appears way smaller than it should be and doesn't match the height.
There's some conversion i am missing. How can i make sure the text is as high as the bounding boxes?
pdftron.PDF.Font font = pdftron.PDF.Font.Create(convertedPdf.GetSDFDoc(), pdftron.PDF.Font.StandardType1Font.e_helvetica);
for (int j = 0; j < ocrStream.pr_WoordList.Count; j++)
{
wordRect = (Rectangle) ocrStream.pr_Rectangles[j];
Element textBegin = elementBuilder.CreateTextBegin();
gStateTextRun = textBegin.GetGState();
gStateTextRun.SetTextRenderMode(GState.TextRenderingMode.e_stroke_text);
elementWriter.WriteElement(textBegin);
fontSize = wordRect.Height;
double descent;
if (hasColorImg)
{
descent = (-1 * font.GetDescent() / 1000d) * fontSize;
textRun = elementBuilder.CreateTextRun((string)ocrStream.pr_WoordList[j], font, fontSize);
//translate the word to its correct position on the pdf
//the bottom line of the wordrectangle is the baseline for the font, that's why we need the descender
textRun.SetTextMatrix(1, 0, 0, 1, wordRect.Left, wordRect.Bottom + descent );
How can i make sure the text is as high as the bounding boxes?
The font_size is just a scaling factor, which in most cases does map to 1/72 inch (pt), but not always.
The transformations are:
GlyphSpace -> TextSpace -> UserSpace (where UserSpace is essentially the page space, and is 1/72 inch)
The glyphs in the font are defined in GlyphSpace, and there is a font matrix that maps to TextSpace. Typically, 1000 units maps to 1 unit in test space, but not always.
Then the text matrix (element.SetTextMatrix), the font size (variable in question here) and some additional parameters, transform TextSpace coordinates to UserSpace.
In the end though, the exact height, depends on the glyph also.
This forum post shows how to go from the glyph data, to UserSpace. See ProcessElements
https://groups.google.com/d/msg/pdfnet-sdk/eOATUHGFyqU/6tsUF0BHukkJ
transform pdf points to pixels, worked correctly:
point-to-pixel = 1/72*300(DPI)
getting each text chunk positions (X,Y) in PDF the Y is calculated from
bottom-to-top, not as in standard html or java Script.
to get the Y value from top-to-down , cause not accurate Y position as in
html style , or win Form style.
how to get the correct Y top-to-down using any Page height, or rect mediaBox
or cropBox or rect textMarging finder ?
the code I used is your example of :
public class LocationTextExtractionStrategyClass : LocationTextExtractionStrategy
{
//Hold each coordinate
public List<RectAndText> myPoints = new List<RectAndText>();
/*
//The string that we're searching for
public String TextToSearchFor { get; set; }
//How to compare strings
public System.Globalization.CompareOptions CompareOptions { get; set; }
public MyLocationTextExtractionStrategy(String textToSearchFor, System.Globalization.CompareOptions compareOptions = System.Globalization.CompareOptions.None)
{
this.TextToSearchFor = textToSearchFor;
this.CompareOptions = compareOptions;
}
*/
//Automatically called for each chunk of text in the PDF
public override void RenderText(TextRenderInfo renderInfo)
{
base.RenderText(renderInfo);
//See if the current chunk contains the text
var startPosition = 0;// System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(renderInfo.GetText(), this.TextToSearchFor, this.CompareOptions);
//If not found bail
if (startPosition < 0)
{
return;
}
//Grab the individual characters
var chars = renderInfo.GetCharacterRenderInfos().ToList();//.Skip(startPosition).Take(this.TextToSearchFor.Length)
var charsText = renderInfo.GetText();
//Grab the first and last character
var firstChar = chars.First();
var lastChar = chars.Last();
//Get the bounding box for the chunk of text
var bottomLeft = firstChar.GetDescentLine().GetStartPoint();
var topRight = lastChar.GetAscentLine().GetEndPoint();
//Create a rectangle from it
var rect = new iTextSharp.text.Rectangle(
bottomLeft[Vector.I1],
bottomLeft[Vector.I2],
topRight[Vector.I1],
topRight[Vector.I2]
);
BaseColor curColor = new BaseColor(0f, 0f, 0f);
if (renderInfo.GetFillColor() != null)
curColor = renderInfo.GetFillColor();
//Add this to our main collection
myPoints.Add(new RectAndText(rect, charsText, curColor));//this.TextToSearchFor));
}
}//end-of-txtLocation-class//
You are asking many different questions in one post.
First let's start with the coordinate system in the PDF standard. Observe that I am talking about a standard, more specifically about ISO 32000. The coordinate system on a PDF page is explained in my answer to the Stack Overflow question How should I interpret the coordinates of a rectangle in PDF?
As you can see, a rectangle drawn in a PDF using a coordinate (llx, lly) for the lower-left corner and a coordinate (urx, ury) for the upper-right corner, assumes that the X-axis points to the right, and the Y-axis points upwards.
As for the width and the height of a page, that's explained in my answer to the Stack Overflow question How to Get PDF page width and Height?
For instance: you could have a /MediaBox that is defined as [0 0 595 842], and therefore measures 595 x 842 points (an A4 page), but that has a /CropBox that is defined as [5 5 590 837], which means that the visible area is only 585 x 832 points.
You also shouldn't assume that the lower-left corner of a page coincides with the (0, 0) coordinate. See Where is the Origin (x,y) of a PDF page?
When you create a document from scratch, a default margin of half an inch is used if you don't define a margin yourself. If you want to change the default, see Fit content on pdf size with iTextSharp?
Now for the height of a Chunk or, if you're using iText 7 (which you should, but —for some reason unknown to me— don't) the height of a Text object, this depends on the font size. The font size is an average size of the different glyphs in a font. If you look at the letter g, and you compare it with the letter h, you see that g takes more space under the baseline of the text than h, whereas h takes more space above the baseline than g.
If you want to calculate the exact space that is taken, read my answer to the question How to calculate the height of an element?
If the text snippet is used in the context of lines in a paragraph, you also have to take the leading into account: Changing text line spacing (Maybe that's not relevant in the context of your question, but it's good to know.)
If you have Chunk objects in iText 5, and you want to do specific things with these Chunks, you might benefit from using page events. See How to draw a line every 25 words?
If you want to add a colored background to a Chunk, it's even easier: How to set the paragraph of itext pdf file as rectangle with background color in Java
Update 1: All of the above may be irrelevant if you are looking to convert HTML to PDF. In that case, it's easy: use iText 7 + pdfHTML as described in Converting HTML to PDF using iText and all the Math is done by the pdfHTML add-on.
Update 2: There seems to be some confusion regarding the measurement units. The differences between user units, points and pixels is explained in the FAQ page How do the measurement systems in HTML relate to the measurement system in PDF?
Summarized:
1 in. = 25.4 mm = 72 user units by default (but it can be changed).
1 in. = 25.4 mm = 72 pt.
1 in. = 25.4 mm = 96 px.
I am creating a round corner table into the footer of my PDF using iTextSharp.
I can do it by this code:
PdfPTable tabFot = new PdfPTable(new float[] { 1F });
tabFot.TotalWidth = 300F;
tabFot.DefaultCell.Border = PdfPCell.NO_BORDER;
tabFot.DefaultCell.CellEvent = new RoundedBorder();
tabFot.AddCell("Footer");
And this is the code of my RoundBorder class:
class RoundedBorder : IPdfPCellEvent
{
public void CellLayout(PdfPCell cell, iTextSharp.text.Rectangle rect, PdfContentByte[] canvas)
{
/* PdfContentByte is an object containing the user positioned text and graphic contents of a page.
* It knows how to apply the proper font encoding
*/
PdfContentByte cb = canvas[PdfPTable.BACKGROUNDCANVAS];
// Adds a round rectangle to the current path: roundRectangle(float x, float y, float w, float h, float r)
cb.RoundRectangle(
rect.Left + 1.5f, // x: x-coordinate of the starting point
rect.Bottom + 1.5f, // y: y-coordinate of the starting point
rect.Width - 3, // w: width
rect.Height - 3, // h: height
4 // r: radius of the arc corner
);
cb.Stroke();
}
}
This work fine and I obtain the following result:
As you can see I obtain that the string "Footer" appear on the left of the cell (as required by the common behavior)
My problem is that I want have something like the following example:
As you can see I want to have some information text on the left and some other text (the page number) on the right of my cell.
Can I do it in some way?
I was reasoning about the fact that I pass a PdfPCell object to my CellLayout() method and that maybe I can put text in this cell whene the CellLayout() is executed. But what can I do to put some text on the left of the cell and some other text on its right?
Alternatively can I put all the text in the center of my cell?
Tnx
These are two questions in one ;-)
First question: you want text to the left and text to the right. This can be done like this:
Phrase phrase = new Phrase();
phrase.add(new Chunk("Left"));
phrase.add(new Chunk(new VerticalPositionMark()));
phrase.add(new Chunk("Right"));
PdfPCell cell = new PdfPCell(phrase);
The trick is where we add a new Chunk(new VerticalPositionMark()).
Second question: you want to center content in a cell.
This is trickier because there are two different modes: text mode and composite mode.
In text mode, you set the alignment at the level of the cell:
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
In your case:
tabFot.DefaultCell.setHorizontalAlignment(Element.ALIGN_CENTER);
In composite mode, you set the alignment at the level of the content you're adding.
I created a PDF document with images, I am trying to add text under each image keep in mind that the template for the page is different depending on how many images the user wants on the page. My problem is I am having problems adding and position the text.
Code for adding images:
int count = 0;
imageStartX = (docSize.Width / 100) * marginSizeProcent;
float imageMaxHeight = 0;
float imageMaxWidth = 0;
iTextSharp.text.Image image = null;
switch (pageLayout)
{
case PageLayoutEnum.SingleImage:
imageMaxWidth = docSize.Width - ((docSize.Width/100) * (2 * (float)marginSizeProcent));
imageMaxHeight = imageStartY - ((docSize.Width/100) * (float)marginSizeProcent);
foreach (PDFObject o in pdfObjects)
{
if (count > 0)
AddPageWithHeader(false);
image = iTextSharp.text.Image.GetInstance(o.File);
image.ScaleToFit(imageMaxWidth, imageMaxHeight);
image.SetAbsolutePosition(imageStartX + (imageMaxWidth - image.ScaledWidth) / 2, imageStartY - image.ScaledHeight - (imageMaxHeight - image.ScaledHeight) / 2);
image.Border = Rectangle.BOX;
image.BorderWidth = 2f;
image.BorderColor = BaseColor.DARK_GRAY;
document.Add(image);
count++;
}
break;
case PageLayoutEnum.TwoImages:
code for adding text:
MemoryStream memoryStream = new MemoryStream();
PdfReader pdfReader = new PdfReader(documentStream.ToArray());
PdfStamper stamper = new PdfStamper(pdfReader, memoryStream);
PdfContentByte contentbyte = stamper.GetUnderContent(1);
ColumnText dispalyIdText = new ColumnText(contentbyte);
Paragraph idText;
int counter = 0;
switch (pageLayout)
{
case PageLayoutEnum.SingleImage:
foreach (PDFObject item in pdfObjects)
{
dispalyIdText.SetSimpleColumn(200, 200, 200, 200, 200, Element.ALIGN_LEFT);
idText = new Paragraph(new Chunk(item.DisplayId, FontFactory.GetFont("Arial", 20, Font.BOLD, BaseColor.RED)));
dispalyIdText.AddElement(idText);
}
break;
case PageLayoutEnum.TwoImages:
You don't say what your actual problems are, only that you're having them.
If I were to guess, one of your problems is that text isn't actually being displayed on your PDFs. There are three distinct reasons for this. The first is this line:
dispalyIdText.SetSimpleColumn(200, 200, 200, 200, 200, Element.ALIGN_LEFT);
The first four parameters to this method are the coordinates of the rectangle that you want to constrain your drawing to. The first parameter is the lower left x, the second is the lower left y, the third is the upper right x and the fourth is the upper right y. In your code you are saying to bind your text to a rectangle with lower left coordinates of 200,200 and upper right coordinates of 200,200. This means your rectangle has zero width and height. To fix this you need to give a rectangle that actually works. In a PDF, the lower left corner is 0,0 so to draw text in a rectangle in the lower left corner that's 20 pixels (not actually pixels but that's another story) high and 200 wide you'd do:
dispalyIdText.SetSimpleColumn(0, 0, 200, 20, 200, Element.ALIGN_LEFT);
Your second problem is that you are setting the leading (line-height) to 200. Depending on the object you are creating this may or may not blow text way out. You should set this to something more sane, possibly the font's height. This doesn't affect AddElement but it does affect SetText.
dispalyIdText.SetSimpleColumn(0, 0, 200, 20, 12, Element.ALIGN_LEFT);
The last problem is that when using ColumnText you are now in "text" mode and have to tell the system when you are ready to start processing. You do this by issuing the Go() command:
dispalyIdText.Go();