iText: PdfTable cell vertical alignment - java

I'm trying to vertical align my headet cell text to be in the middle of the cell height.
This is my code:
PdfPCell c1 = new PdfPCell(cerate_phrase("" ,regular_bold ));
c1.setHorizontalAlignment(Element.ALIGN_CENTER);
c1.setVerticalAlignment(Element.ALIGN_MIDDLE);
c1.setBackgroundColor(BaseColor.LIGHT_GRAY);
table_.addCell(c1);
but this does not work. setHorizontalAlignment is centered but not setVerticalAlignment.
Am I doing something wrong? how can i vertically align it in the middle?
Any help will be appreciated.

According to Lowagie:
PdfPCell cell = new PdfPCell(new Phrase("blah Blah blah");
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
This is always correct in a technical sense, but sometimes looks bad.
To center, draw a box around the object, find its middle, and align it with the center of its surrounding object.
iText thus finds the center of the phrase, and aligns it. But human eyes sometimes focus on the bulk of text, say the parts of the font between the baseline and the cap height. So to have it look good, you need to center relative to that.
Phrase content = new Phrase("Blah blah blah", Font);
Float fontSize = content.getFont().getSize();
Float capHeight = content.getFont().getBaseFont().getFontDescriptor(BaseFont.CAPHEIGHT, fontSize);
Float padding = 5f;
PdfPCell cell = new PdfPCell(content);
cell.setPadding(padding);
cell.setPaddingTop(capHeight - fontSize + padding);
Note that the PdfPCell method setVerticalAlignment(..) isn't used.
It seems like this wouldn't necessarily work for a multi-line phrase, but it does.
The problem would be obvious if iText could show bounding boxes around things (mind, you can tell iText to draw bounding boxes, it's just more work than a magical on/off switch).
This solution is adapted from an email from Paulo Soares.

Add cell.setUseAscender(true) before c1.setVerticalAlignment(Element.ALIGN_MIDDLE);
I have the same problem with you, when add code above I find it can work, hope this can solve your problem, thanks.

You can use the option ExtraParagraphSpace:
c1.HorizontalAlignment = Element.ALIGN_CENTER;
c1.VerticalAlignment = Element.ALIGN_MIDDLE;
c1.ExtraParagraphSpace = 2;

You cant do like this :
cell.setBackgroundColor(BaseColor.GRAY);
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setUseAscender(true);

Related

How to decrease font size to 0.0001f when using drawString()?

I have an assignment right now about OpenStreetMaps, where one of the exercises is to display the road names at their respective roads on the map.
My problem right now, is that the coordinates we're using are so small, that even the smallest int font size is hundred times larger than what it's supposed to be.
I have tried the method deriveFont(), but it doesn't seem to have any effect.
g.setPaint(Color.black);
for (DrawnString d : model.getRoads()){
Point2D.Double p = d.getPosition();
Font font = new Font("TimesRoman", Font.PLAIN, 1);
font.deriveFont(0.0001f); //doesn't work!
g.setFont(font);
g.drawString(d.getText(), (float) p.x, (float) p.y);
}
My question is, if there's a way to decrease the font size to a small size like 0.0001f?
The deriveFont() method returns an object of type font that is a replica of the calling font with changed parameters.
So change the line to: font = font.deriveFont(0.001f); and everything works just as expected (with very tiny font)
Okay it's me who's stupid, I just missed a "font =" in front of derivedFont().
font = font.deriveFont(0.0001f);
It works now.

LibGdx Label text wrap bug?

I use a Label with text wrap enabled. In this case, the text wraps wrong. The text wraps into 3 lines, when it should be only 2 and the Label size only reflects the 2 lines. I debugged through the code and found the reason for this to be in the Label.layout() method. Not sure if this is a bug or if I am doing something wrong.
In the code below you can see that the text is set twice to the GlyphLayout. The first time it wraps correct, the second time we use the reduced width and it wraps into more lines as before. I think the second time we set the text into the GlyphLayout, the same width should be used.
public class Label extends Widget {
public void layout () {
...
float width = getWidth(), height = getHeight();
...
GlyphLayout layout = this.layout;
float textWidth, textHeight;
if (wrap || text.indexOf("\n") != -1) {
// Set the text into the GlyphLayout. The text is wrapped correctly here
layout.setText(font, text, 0, text.length, Color.WHITE, width, lineAlign, wrap, ellipsis);
textWidth = layout.width;
textHeight = layout.height;
...
} else {
textWidth = width;
textHeight = font.getData().capHeight;
}
...
// Set the text again into the GlyphLayout. This time with the width that we got when we set it the first time
// This time the text is wrapped wrong as it uses less width as it should
layout.setText(font, text, 0, text.length, Color.WHITE, textWidth, lineAlign, wrap, ellipsis);
...
}
}
Make sure to invalidate() the label and then pack() the label so it calculates any new preferred sizes; this may or may not fix the problem.
Looking at the source code of Label then you can see that the last invocation of layout.setText() is always invoked regardless of text wrapping or not.
The previous layout.setText() invocation is used to set the textWidth and textHeight for the later call where those values are actually used.
If wrapping is on or there is a newline character then the width and height is set to that of the label and if it is off then the width is set to the actual text width and the height set to the font data height.
From the above, another problem that may be causing this to happen is if you have scaled the font and/or label. The scaling factor is not being applied from within Label.layout() which may cause the label size to be that of 2 lines whilst the actual text is 3 lines as the width doesn't allow for overflow with wrapping set to on.
If all else fails, I would ensure that your font files are correct and that there are not any characters or data in your text that may cause a new line to occur.
I would also suggest to use another font of the same glyph width and height and see if the problem persists. If it does not then at least you know it is a problem relating to the font and not the label.
Hope this helped you.
This issue has been solved in libgdx 1.9.12

How to draw a rectangle around multiline text

I am trying to draw a rectangle around multiline text in iText.
The user will be able to enter some lines of text. The font size of the text might be different and it can be formatted (bold, underlined...).
I use this code to draw the text:
ColumnText ct = new ColumnText(cb);
Phrase phrase = new Phrase("Some String\nOther string etc...\n test");
ct.setSimpleColumn(myText......);
ct.addElement(phrase);
ct.go();
I know how to draw a rectangle, but I am not able to draw a rectangle outlining this text.
It sounds as if you are missing only a single piece of the puzzle to meet your requirement. That piece is called getYLine().
Please take a look at the DrawRectangleAroundText example. This example draws the same paragraph twice. The first time, it adds a rectangle that probably looks like the solution you already have. The second time, it adds a rectangle the way you want it to look:
The first time, we add the text like this:
ColumnText ct = new ColumnText(cb);
ct.setSimpleColumn(120f, 500f, 250f, 780f);
Paragraph p = new Paragraph("This is a long paragraph that doesn't"
+ "fit the width we defined for the simple column of the"
+ "ColumnText object, so it will be distributed over several"
+ "lines (and we don't know in advance how many).");
ct.addElement(p);
ct.go();
You define your column using the coordinates:
llx = 120;
lly = 500;
urx = 250;
ury = 780;
This is a rectangle with lower left corner (120, 500), a width of 130 and a height of 380. Hence you draw a rectangle like this:
cb.rectangle(120, 500, 130, 280);
cb.stroke();
Unfortunately, that rectangle is too big.
Now let's add the text once more at slightly different coordinates:
ct = new ColumnText(cb);
ct.setSimpleColumn(300f, 500f, 430f, 780f);
ct.addElement(p);
ct.go();
Instead of using (300, 500) as lower left corner for the rectangle, we ask the ct object for its current Y position using the getYLine() method:
float endPos = ct.getYLine() - 5;
As you can see, I subtract 5 user units, otherwise the bottom line of my rectangle will coincide with the baseline of the final line of text and that doesn't look very nice. Now I can use the endPos value to draw my rectangle like this:
cb.rectangle(300, endPos, 130, 780 - endPos);
cb.stroke();

Correct text position center in rectangle iText

I try to draw text inside rectangle which fit rectangle size, like my previous question, I want text align center in rectangle.
The problem is display text has wrong Y coordinate, look like this one:
And here is my code:
PdfContentByte cb = writer.getDirectContent();
Rectangle rect = new Rectangle(100, 150, 100 + 120, 150 + 50);
cb.saveState();
ColumnText ct = new ColumnText(writer.getDirectContent());
Font font = new Font(BaseFont.createFont());
float maxFontSize;
// try to get max font size that fit in rectangle
font.setSize(maxFontSize);
ct.setText(new Phrase("test", font));
ct.setSimpleColumn(rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop());
ct.go();
// draw the rect
cb.setColorStroke(BaseColor.BLUE);
cb.rectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight());
cb.stroke();
cb.restoreState();
I even draw text like this:
cb.saveState();
cb.beginText();
cb.moveText(rect.getLeft(), rect.getBottom());
cb.setFontAndSize(BaseFont.createFont(), maxSize);
cb.showText("test");
cb.endText();
cb.setColorStroke(BaseColor.BLUE);
cb.rectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight());
cb.stroke();
And got the result:
So I wonder how can itext render text base on the coordinates? Because I use the same rectangle frame for text and rectangle bound.
I'm not sure if I understand your question correctly. I'm assuming you want to fit some text into a rectangle vertically, but I don't understand how you calculate the font size, and I don't see you setting the leading anywhere (which you can avoid by using ColumnText.showAligned()).
I've created an example named FitTextInRectangle which results in the PDF chunk_in_rectangle.pdf. Due to rounding factors (we're working with float values), the word test slightly exceeds the rectangle, but the code shows how to calculate a font size that makes the text fit more or less inside the rectangle.
In your code samples, the baseline is defined by the leading when using ColumnText (and the leading is wrong) or the bottom coordinate of the rectangle when using showText() (and you forgot to take into account value of the descender).

itext multiline text in bounding box

Does anyone know, how to, in iText, add multiline text in bounding box (with coordinates specified).
I tried
cb.showTextAligned(
PdfContentByte.ALIGN_LEFT,
text,
bounds.getLeft(),
TOTAL_HEIGHT-bounds.getTop(),
0 );
But it does not support newlines.
I also tried
PdfContentByte cb = writer.getDirectContent();
cb.moveText(300,400);
document.add(new Paragraph("TEST paragraph\nNewline"));
This supports newlines but does not react to moveText, so I don't know how to put it at given position or better: bounding box.
I suspect chunks or PdfTemplate or maybe table might help, but i don't (yet) know how to put it together. TIA for help.
Try this:
ColumnText ct = new ColumnText(cb);
Phrase myText = new Phrase("TEST paragraph\nAfter Newline");
ct.setSimpleColumn(myText, 34, 750, 580, 317, 15, Element.ALIGN_LEFT);
ct.go();
parameters of SetSimpleColumn are:
the phrase
the lower left x corner (left)
the lower left y corner (bottom)
the upper right x corner (right)
the upper right y corner (top)
line height (leading)
alignment.
ColumnText ct = new ColumnText(content);
ct.setSimpleColumn(
new Phrase("Very Long Text"),
left=20, bottom=100, right=500, top=500,
fontSize=18, Element.ALIGN_JUSTIFIED);
ct.go(); // for drawing

Categories

Resources