FPDF/FPDI: How to vertically align a cell or multi-cell? - alignment

I'm starting to think is not possible? (out of the box/default class)
I am using FPDF/FPDI PHP class to generate a .pdf
In this situation, I have some text that can be short, or be long (no telling)
So I set a width on my cell.. and change from Cell() to MultiCell()..
This allows long text to wrap.. however it seems to vertically align to the top?
Which is no good if the string is NOT long enough to wrap..
How can you force the text to the bottom of the cell regardless if it is a single line or a wrapped line?
Is there a default way to do this?
I saw mention of TCPDF (or whatever).. and some dead links to 'plug-ins'.. (but not sure if they were FPDI or not?)
This works and looks fine:
$pdf->MultiCell(185, 12, 'ABC-123-DEF-456 And-Last-Name-Here', 1, 'C', false);
However this way, does NOT have the (single line) text at the bottom.. so there is a cap between the string output and the 'underline' it shoudl match up with with (baseline)
$pdf->MultiCell(185, 12, 'ABC-123 DEF-456', 1, 'C', false);
How do you overcome this?

I think, I just found solution.
As default FPDF class I use this code: https://github.com/Setasign/tFPDF/blob/master/tfpdf.php (it supports UTF-8 chars)
Than have edited this class code: http://www.fpdf.org/en/script/script52.php
In Function drawRows() I have changed this row:
$l+=$cw[$c];
To this:
$l+=$this->GetStringWidth($c)/$this->FontSize*1000;
And than use drawTextBox() as is descripted in http://www.fpdf.org/en/script/script52.php
Now I will try to explain:
GetStringWidth() function supports utf-8 chars soo we can use it to calculate char width. And than we can get correct value with some multiplications and divisions for compability with that fpdf class.
I didnt test this code extensivly... only basic testing.

You can do it with a new line, "\n". But you need to keep in mind that cell height needs to be determined by number of "\n", as multi_cell will increase cell height automatically when required.
This is how I have done it:
spacing = " \n\n\n\n\n\n\n\n\n"
contents = "\n" + "hello" + spacing
pdf.multi_cell(10, 3, contents, border=1, align="R")
This will align "hello" to the top right corner.
When creating the spacing I added a space before the \n's otherwise it will be very close to the edge. I also added a \n before the "hello" as otherwise it will be too close to the top. I kept the multi_cell height to 3, but you can even put it to 1 or anything that makes sure your size of \n's is not smaller than the cell height.
I know this is very gimmicky, so if you have a better way please let me know.

This seems could be the answer:
http://www.fpdf.org/en/script/script52.php
Unfortunately, at least to me, it doesn't seem to work when using UTF-8 characters.

Related

How to align two UILabels on the Y axis of the center of the first line of text

please see the image below for two examples of what is to be achived
the alignment should be on the Center Y of the first lines of each UILabels and should work regardless of font size or font. currently we have implemented this with different constraints to the top of the super view for different font and font size combinations.
the constraint to align the center of the two UILabels does not work since the text of the second UILabel is not fixed and can have several lines.
also the text is dynamic, so it is not known where the text will wrap to create the first line, thus it cannot be shown in an one line UILabel with the rest of the text in another one below.
currently this is implemented using UIKit, but if there is an easy solution in SwiftUI we can put these two labels in a SwiftUI component. so a SwiftUI solution would also be welcomed.
Your comments said "it should be on the glyphs" ... but, without additional information, my guess is that "real world" usage would not really need that level of precision.
For example:
While the glyphs are not perfectly center-Y aligned, it seems unlikely you'd run into a case where the first line of the "rightLabel" is " ' " ' " or . , . , ..
This layout can be easily done with only a few constraints - no need to do any calculations:
The "Positioning" label would, of course, be set .hidden = true so it would never be seen.
If you really, really want glyph-precision, you'll need to calculate
the Glyph bounding box for the left-label
the Glyph bounding box for first line of the right-label
calculate the "character box" offsets to align the Glyph Y-centers
and then position the two labels accordingly, or use Core Text to draw the text (instead of using UILabel).
Probably more work than necessary -- unless your actual use-case demands it.
That's an interesting problem! You can try using the centerYAnchor for the label on the left, and the firstBaselineAnchor for the label on the right... that will align the center Y with the text baseline, which isn't quite what you want.
To find the correct offset to apply, you can use the information from UIFont about the size of the characters. I'd probably start with capHeight * 0.5 and see if that looks or feels right. Something like:
leftLabel.centerYAnchor.constraint(equalTo: rightLabel.firstBaseLineAnchor, constant: rightFont.capHeight * 0.5)
This is a more difficult problem in SwiftUI, I think, because resolved font metrics aren't directly available to you.

Alignment in flextable correct in Rstudio viewer, incorrect in Word

I am trying to left align some columns in a few of my tables. Most of the time this works no problem, but other times, the columns selected with:
ft <-align(ft, j=1:2, align = "left", part = "body")
ft <-align(ft, j=4:6, align = "left", part = "body")
look correct in the Rstudio viewer. I used a loop to make 39 tables and want to add them to a word document using officer
However, when printed to a word doc using:
doc <- read_docx() %>%
body_add_flextable(tab0)
body_add_break(doc, pos="after")
for (i in 1:38) {
body_add_flextable(doc,get(paste0("tab", i)), align = "left")
body_add_break(doc, pos="after")
}
print(doc,target=documentname)
it center aligns the columns (only changes those that were left aligned). When I click on the text, it says that they are left aligned, but then I center and re-left align and that fixes the issue. I have only noticed the issue which character variables
I tried triming whitespace with
trimws() before I make the flextable with no luck.
I tried other alignments and the issue only seems to occur with left alignment.
I don't believe my code to be wrong, since it works for my other tables. Therefore, I think trying to make reproducible code would be a waste of time.
Therefore, I'm assuming the text itself is causing the issue? Does anyone know what could be wrong with the character variables themselves? Or any other ideas?
Fixed it...
Somewhere within my flextable manipulation this leading white space was added.
So trimming white space before didn't do anything. Had to trim right before naming my table (within a loop). Here is the loop I used to correct it.
for (j in 1: length(ft[["body"]][["content"]][["content"]][["data"]])){
ft[["body"]][["content"]][["content"]][["data"]][[j]][["txt"]] <- trimws(ft[["body"]][["content"]][["content"]][["data"]][[j]][["txt"]])
}

Find substring that would fit inside UILabel of certain area

For a UILabel of certain width, with certain font and font size, i want to calculate amount of characters that would make 7 lines worth of text inside it + ... (three dots showing continuation). Is there a fancier way to achieve this? Currently what i'm trying is counting up to X amount of characters or 7 new line characters, which ever comes first and i cut on the text right there.
More Detail:
Trying to make an expandable row Cell which contains the UILabel, i'm achieving this with auto layout... So to control the cell expansion, i change the text to be full text or a substring of that, with a button below which toggles between the string vs substring. All of that is working. The problem i'm getting is my method of finding the substring isnt very neat. Its not consistent on how it handles text of different combination of characters or newlines. I get variations of how it looks and sometimes it just ends with three dots on a new line rather than finishing on the 7th line.
Even using auto layout you can still use the lines property of UILabel to limit the number of lines displayed by the label.
So set it 7 and you'll get 7 or less rows. Just assign the complete text.

iOS + UIlabel with Start and end Quotes in UITableViewCell

I'm trying to create a UITableViewCell like the one in picture. It has a UILabel and at the start and end Start and endQuotes. I have already looked at NSAttributedText string but it looks horrible when quotes are included in text. Do let me know if anyone has ideas
One idea is to make sure the text starts at the specified distance to the right, e.g. by inserting spaces. Then you would have to find out the x position of the last character - this should also be possible. The quotes could be images that you then superimpose.
For finding the x of the last line, you could calculate the total height, figure out how much of the text fits if you remove one line, then calculate the width of the remaining text.
The new boundingRectWithSize:options:attributes:context: should be enough to make these calculations.

Calculate characters that fit a fixed rect TextView

I have seen here people needing to calculate the size of the NSString given a size but I need to do the opposite.
Given a specified rect (or fixed UITextView, or multiline UILabel, no scrolling) I need to know:
if it managed to show all the chars of my NSString
if not, what is the last char shown
So that I can display the remaining text in another UITextView (of course if I could use a single UITextView I would not have this problem).
At first it seems a simple thing to do, but actually I am not finding a way, intuitively I think I could use either UITextView's:
textView.contentSize.height;
or NSString's:
sizeWithFont:constrainedToSize:lineBreakMode:
or a combination of the two, but I need to be precise and those methods do not help me in telling what is the last character that managed to fit the visible area of the UITextView.
Not sure if this is actually possible, but is a requirement of my client who thinks programming iOS is like printing a newspaper and expects to be able to format text around an image....
You could maybe get the maximum height of one line of text from a one character long string.
If you use that with sizeWithFont:constrainedToSize:lineBreakMode: then you should be able to know if your text runs onto more than one line (if the cgsize height is greater than the height of one line of text).
In order to find out the last character (or word) you would have to loop around the length of the string adding characters (or words) as you go and checking for when the cgsize height increases to add a new line, this will give you the character point when to split into multiple strings ( for multiple fields/labels/textviews ) or when to insert line breaks into the text ( if using a single multi-line textview or label ).
I hope you find an easier way...

Resources