iTextSharp - draw rectangle - border width issue - c#

here's a simple code:
var w = Utilities.MillimetersToPoints(420);
var h = Utilities.MillimetersToPoints(210);
var doc1 = new Document(new Rectangle(w, h));
PdfWriter writer = PdfWriter.GetInstance(doc1, new FileStream("Doc1.pdf", FileMode.Create));
doc1.Open();
PdfContentByte cb = writer.DirectContent;
var rect = new Rectangle(200, 200, 100, 100);
and now, if I do the following:
cb.Rectangle(200, 200, 100, 100);
cb.Stroke();
then I see the rectangle. But I need to set its border width, so I do
rect.BorderWidth = 5;
rect.BorderColor = new BaseColor(0,0,0);
cb.Rectangle(rect);
cb.Stroke();
and now the rectangle is not visible. Why ?

The Rectangle() method on PdfContentByte has a couple of overloads and they behave quite differently depending on what you pass in.
Your first example is using the very simple overload that just takes 4 floats. If you look at the source for that you'll see that beyond some sanity checking it just writes those coordinates directly to the PDF stream and no actual Rectangle objects are created in the process. Later when you call Stroke() iText writes the stroke command to the stream and that's it. When a PDF renderer (like Adobe's) actually parses the stroke command it looks backwards in the buffer and sees the coordinates that it needs to stroke and performs the action.
Your second example uses the much more complex overload that you can see here which takes an actual Rectangle object. Besides representing four points in space a Rectangle has concepts like background colors and borders and, most importantly for you, these borders can be drawn per side and you need to tell it which sides to draw on.
For instance, for just left and right you'd do:
var rect = new iTextSharp.text.Rectangle(200, 200, 100, 100);
rect.Border = iTextSharp.text.Rectangle.LEFT_BORDER | iTextSharp.text.Rectangle.RIGHT_BORDER;
rect.BorderWidth = 5;
rect.BorderColor = new BaseColor(0, 0, 0);
cb.Rectangle(rect);
And for all borders you'd change it to:
rect.Border = iTextSharp.text.Rectangle.BOX;
Also, when calling this overload it is actually incorrect to call Stroke() immediately after because this overload takes care of that for you (and might have done it more than once, actually.)

(an Addendum to #Chris' answer)
If you want to implement your task (to set its border width) using the simple means of the first example, you can explicitly set the width of lines to stroke:
cb.SetLineWidth(5);
cb.Rectangle(200, 200, 100, 100);
cb.Stroke();
You may want to envelope these lines in cb.SaveState() ... cb.RestoreState() to prevent the changed line width to influence later operations.

Document document = new Document(PageSize.A4, 25, 25, 30, 30);
PdfContentByte cb = writer.DirectContent;
cb.Rectangle(30,660, 280,80);
cb.Stroke();
the function writer is start to write in pdf and rectangle function is create rectangle and stroke is to draw above rectangle specification. so you have to write the stroke() function.

PdfContentByte cb = pdfwrite.DirectContent;
var Rectangular = new Rectangle(55, 620, 540,375);
Rectangular.BorderWidthLeft = 0.1f;
Rectangular.BorderWidthRight = 0.1f;
Rectangular.BorderWidthTop = 0.1f;
Rectangular.BorderWidthBottom = 0.1f;
cb.Rectangle(Rectangular);
cb.Stroke();

Related

itex7: Add link to PDF without border or underline

I want to add a link to a document without underline or border.
Based on the documentation I expected the first example below to result in no border around the link. That did not work so I found this post which I adapted to the second example. Using this method I am able to replace the border with an underline, but not to get rid of both.
PdfDocument pdfDoc = new PdfDocument(new PdfWriter("links.pdf"));
Document d = new Document(pdfDoc);
// example 1
Paragraph p = new Paragraph()
.Add(new Link("Link with border", PdfAction.CreateURI("http://www.google.com")).SetBorder(Border.NO_BORDER))
.SetBorder(Border.NO_BORDER); // no border on the paragraph
d.Add(p);
// example 2
PdfLinkAnnotation linkA = new PdfLinkAnnotation(new Rectangle(0, 0, 0, 0));
linkA.SetHighlightMode(PdfLinkAnnotation.HIGHLIGHT_INVERT);
//This would give underline instead of borders
//linkA.SetBorderStyle(PdfLinkAnnotation.STYLE_UNDERLINE);
linkA.SetAction(PdfAction.CreateURI("http://www.google.com"));
Link link = new Link("Please no borders", linkA);
d.Add(new Paragraph(link));
pdfDoc.Close();
In order to get no borders in your second example you need to specify borders via PdfLinkAnnotation#SetBorder(PdfAnnotationBorder) method instead of the SetBorderStyle.
Here is a code snippet of yours slightly modified example:
PdfDocument pdfDoc = new PdfDocument(new PdfWriter("links.pdf"));
Document d = new Document(pdfDoc);
Link link = new Link("Please no borders", PdfAction.CreateURI("http://www.google.com"));
link.GetLinkAnnotation().SetBorder(new PdfAnnotationBorder(0, 0, 0));
d.Add(new Paragraph(link));
pdfDoc.Close();
You can find more info about this method call in javadocs: http://itextsupport.com/apidocs/itext7/latest/com/itextpdf/kernel/pdf/annot/PdfAnnotation.html#getBorder--
Some background
By default iText doesn't specify any specific border properties for link annotations. And as per PDF specification default value for annotations is to have borders:
ISO32000-1 12.5.2 "Annotation Dictionaries" Table 164 – "Entries common to all annotation dictionaries":
Border - An array specifying the characteristics of the annotation’s border, which shall be drawn as a rounded rectangle.
The array consists of three numbers defining the horizontal corner radius, vertical corner radius, and border width, all in default user space units. If the corner radii are 0, the border has square (not rounded) corners; if the border width is 0, no border is drawn.
[...]
Default value: [0 0 1].

iTextSharp ShowTextAligned Anchor Point

I'm currently successfully adding text to a PDF using iTextSharp's ShowTextAligned method. The method looks like this (C#):
public void ShowTextAligned(
int alignment,
string text,
float x,
float y,
float rotation
)
However, it is unclear where the anchor point is for the text we're making. We provide x and y, but does these correspond to the upper left corner of the text rectangle, the lower left corner, or something else? Also is this impacted by line spacing?
I looked at the documentation at this website, but it isn't very explanatory. See PdfContentByte Class / PdfContentByte Methods / ShowTextAligned Method.
Obviously the anchor point depends on the kind of alignment. It does not make sense to say you right-align if your anchor point is at the left side of the text.
Furthermore, text operations usually align relative to the baseline.
Thus:
For left aligned text the anchor point is the left-most point of the text baseline.
For center aligned text the anchor point is the middle point of the text baseline.
For right aligned text the anchor point is the right-most point of the text baseline.
More visually:
This has been generated using:
[Test]
public void ShowAnchorPoints()
{
Directory.CreateDirectory(#"C:\Temp\test-results\content\");
string dest = #"C:\Temp\test-results\content\showAnchorPoints.pdf";
using (Document document = new Document())
{
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(dest, FileMode.Create, FileAccess.Write));
document.Open();
PdfContentByte canvas = writer.DirectContent;
canvas.MoveTo(300, 100);
canvas.LineTo(300, 700);
canvas.MoveTo(100, 300);
canvas.LineTo(500, 300);
canvas.MoveTo(100, 400);
canvas.LineTo(500, 400);
canvas.MoveTo(100, 500);
canvas.LineTo(500, 500);
canvas.Stroke();
ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT, new Phrase("Left aligned"), 300, 500, 0);
ColumnText.ShowTextAligned(canvas, Element.ALIGN_CENTER, new Phrase("Center aligned"), 300, 400, 0);
ColumnText.ShowTextAligned(canvas, Element.ALIGN_RIGHT, new Phrase("Right aligned"), 300, 300, 0);
}
}

itextsharp add text over a circle image in a table cell

I need to have a table with multiple columns where I have different coloured circles in different cells with a number in the middle of the circle.
Similar to the mockup below but with everything centralized and equal.
I have tried the following:
PdfContentByte canvas = writer.DirectContent;
PdfTemplate template = canvas.CreateTemplate(40, 40);
template.SetLineWidth(1f);
template.Circle(15f, 15f, 15);
template.Stroke();
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(template);
img.Alignment = iTextSharp.text.Image.UNDERLYING | iTextSharp.text.Image.ALIGN_CENTER;
Phrase imgPhrase = new Paragraph(new Chunk(img, 1f, 1f));
PdfPCell meAnswerCell = new PdfPCell();
meAnswerCell.Colspan = 1;
meAnswerCell.BorderWidthBottom = 0;
meAnswerCell.HorizontalAlignment = Element.ALIGN_CENTER;
string meAnswerText = "1;
Phrase phrase = new Phrase(meAnswerText, questionFont);
Paragraph para = new Paragraph();
para.Add(imgPhrase);
para.Add(phrase);
para.Alignment = Element.ALIGN_CENTER;
meAnswerCell.AddElement(para);
answersTable.AddCell(meAnswerCell);
but I end up with something like this. (I haven't tried setting the colour yet). I cannot get the image and the text to sit in the same place.
I have also tried following this post:
iTextSharp - Text overlapping image
which explains how to put an event on the cell to set the background image of the cell but my circle appears half way down the page.
Has anyone go an example of this working?
There are many different ways to achieve what you want.
Actually, I just voted to close a question https://stackoverflow.com/questions/28066639/how-to-get-text-on-image-in-itext-using-java because it was a duplicate of How to add text to an image?
In your case, you may also benefit from the documentation. There are some examples in The Best iText Questions on StackOverflow that explain how to use cell events, but your requirement is very similar to what was done in a couple of examples from the book iText in Action - Second Edition.
You could use cell events to draw the background of a cell, as shown in the Calendar examples: calendar.pdf, but your requirement can also be met using a generic tag event: movie_years.pdf
Do you see how the word IMDB nicely fits inside an ellipse? You could fit a number inside a circle in the exact same way.
With this code, one draws an ellipse (changing it into a circle is fairly easy):
class GenericTags : PdfPageEventHelper {
public override void OnGenericTag(
PdfWriter writer, Document pdfDocument, Rectangle rect, String text) {
PdfContentByte content = writer.DirectContentUnder, rect);
content.SaveState();
content.SetRGBColorFill(0x00, 0x00, 0xFF);
content.Ellipse(
rect.Left - 3f, rect.Bottom - 5f,
rect.Right + 3f, rect.Top + 3f
);
content.Fill();
content.RestoreState();
}
}
With this snippet, you introduce this event:
GenericTags gevent = new GenericTags();
writer.PageEvent = gevent;
With this snippet, you mark a Chunk with the generic tag:
chunk.SetGenericTag("circle");

itextsharp columntext overlapping with table

I have a columntext that comes before a pdftable, how do I stop the two elements from overlapping?
ColumnText addressHeader = new ColumnText(cb);
Phrase addressText = new Phrase("Lorem ipsum");
addressHeader.SetSimpleColumn(addressText, 34, 750, 580, 317, 15, Element.ALIGN_LEFT);
addressHeader.FollowingIndent = 10f;
addressHeader.Go();
PdfPTable contactTable = new PdfPTable(2);
float[] contactWidths = new float[] { 1f, 1f };
contactTable.TotalWidth = 400f;
contactTable.LockedWidth = true;
contactTable.SpacingBefore = 10f;
contactTable.SetWidths(contactWidths);
PdfPCell contactInfoCell = new PdfPCell();
contactInfoCell.AddElement(new Chunk("Date Requested));
doc.Add(contactTable);
ColumnText.SetSimpleColumn() is used to absolutely position things whereas the Document.Add() method is used to relatively position things. Absolute and relative objects aren't aware of each other, that's just their nature.
So if you can use relative positioning then get rid of the ColumnText and add the Phrase to the document normally.
If you need absolute positioning then you'll need to absolutely position the table as well. This can be done using the table's WriteSelectedRows() method where you tell how many rows to write and what's the upper left corner to start drawing at.
A third possible option is that if you're using the ColumnText.SetSimpleColumn() to draw a page header then you can just change the document's margins. You can still absolutely position things outside of the margins but when you use Document.Add() it will respect those margins.

draw multiple curves in WinForms picturebox

I am working on a program which I want to draw diode curves in a WinForms application. I have a list of diode names and I have theire points as you can see at the right side of the picture. That is Voltage as X and Current as Y ( A curve contains like 50 points).
What I want to do is by selecting one or more diodes from the list theire curve show up on my plot. What you see is just a picture box at the moment filled with a bmp. I know that this is not a reliable solution, so I am asking you what can be the best approach to do such thing? I dont know any good component which can make me do this. So I just need to know what can be the best approuch for this task?
A diode curve is something like:
I might have up to 100 of diode curves in my program which all of them (single or multiple) should be drawn by clicking on them in the list.
So what you think?
UPDATE
ALSO important thing is by deselecting a pin in the curve, its curve should be removed from the plot!
I am drawing that axis you see using the code below:
Bitmap xyCords = new Bitmap(500, 500);
Graphics g = Graphics.FromImage(xyCords);
g.DrawLine(penAxis, 250, 0, 250, 500);
g.DrawLine(penAxis, 0, 250, 500, 250);
curveBox.Image = xyCords;
how is it possible later if I made a new Graphics I append it like:
curveBox.Image += newGraphic;
** Please let me know if there is any component or something which already can do what I want. or else show me a good approach! Thanks!
Try using Graphics.DrawCurve. You just put all of the points you want in an array, and pass that and a pen to the method.
Edit:
Add this after your code to prove to yourself that both graphs coexist. To erase one or the other, just plot the same points, but in the background color of the bitmap (test for it, I don't remember what it is).
Point[] ptarray = new Point[3];
ptarray[0] = new Point(250, 250);
ptarray[1] = new Point(300, 300);
ptarray[2] = new Point(350, 400);
Pen pengraph = new Pen(Color.Green, 0.75F);
g.DrawCurve(pengraph, ptarray);
Point[] ptarray2 = new Point[3];
ptarray2[0] = new Point(100, 100);
ptarray2[1] = new Point(200, 150);
ptarray2[2] = new Point(250, 250);
Pen pengraph2 = new Pen(Color.Yellow, 1.25F);
g.DrawCurve(pengraph2, ptarray2);

Categories

Resources