Java iText- ColumnText 在矩形中设置文本适合大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20769881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 04:12:40  来源:igfitidea点击:

iText- ColumnText set text fit size in Rectangle

javaitext

提问by R4j

I want to add text into a rectangle(x,y,w,h). Text should be fitted size of rectangle (mean it has a maximum size but it still contains in rectangle).
I tried to measure the text size base on BaseFont.getWidthPoint()The problem is the final text size can't fit the rect. It looks like this:
enter image description here

我想将文本添加到矩形(x,y,w,h)中。文本应该适合矩形的大小(意味着它有一个最大大小,但它仍然包含在矩形中)。
我试图BaseFont.getWidthPoint()根据问题来测量文本大小问题是最终的文本大小不能适合矩形。它看起来像这样:
在此处输入图片说明

Here is my try:

这是我的尝试:

  PdfContentByte cb = writer.getDirectContent();
    cb.saveState();
    ColumnText ct = new ColumnText(writer.getDirectContent());
    Font font = new Font(BaseFont.createFont());
    int rectWidth = 80;
    float maxFontSize = getMaxFontSize(BaseFont.createFont(), "text", rectWidth );
    font.setSize(maxFontSize);
    ct.setText(new Phrase("test", font));
    ct.setSimpleColumn(10, 10, rectWidth , 70);
    ct.go();        

    // draw the rect
    cb.setColorStroke(BaseColor.BLUE);
    cb.rectangle(10, 10, rectWidth , 70);
    cb.stroke();
    cb.restoreState();

   // get max font size base on rect width
  private static float getMaxFontSize(BaseFont bf, String text, int width){
    float measureWidth = 1;
    float fontSize = 0.1f;
    float oldSize = 0.1f;
    while(measureWidth < width){
        measureWidth = bf.getWidthPoint(text, fontSize);     
        oldSize = fontSize;
        fontSize += 0.1f;
    }

    return oldSize;
}

Could you please tell me where I am wrong?

你能告诉我我错在哪里吗?

Another problem, I want to measure for both width and height, which text completely contains in rectangle and has the maximum font size. Is there any way to do this?

另一个问题,我想测量宽度和高度,哪个文本完全包含在矩形中并且具有最大字体大小。有没有办法做到这一点?

Update: here is the complete source code that worked for me:

更新:这是对我有用的完整源代码:

   private static float getMaxFontSize(BaseFont bf, String text, int width, int height){
   // avoid infinite loop when text is empty
    if(TextUtils.isEmpty(text)){
        return 0.0f;
    }


    float fontSize = 0.1f;
    while(bf.getWidthPoint(text, fontSize) < width){
        fontSize += 0.1f;
    }

    float maxHeight = measureHeight(bf, text, fontSize);
    while(maxHeight > height){
        fontSize -= 0.1f;
        maxHeight = measureHeight(bf, text, fontSize);
    };

    return fontSize;
}

public static  float measureHeight(BaseFont baseFont, String text, float fontSize) 
{ 
    float ascend = baseFont.getAscentPoint(text, fontSize); 
    float descend = baseFont.getDescentPoint(text, fontSize); 
    return ascend - descend; 
}

采纳答案by mkl

The main issue

主要问题

The main issue is that you use the wrong arguments in ct.setSimpleColumn:

主要问题是您在ct.setSimpleColumn以下内容中使用了错误的参数:

ct.setSimpleColumn(10, 10, rectWidth , 70);

In contrast to the later cb.rectanglecall

与后来的cb.rectangle电话相反

cb.rectangle(10, 10, rectWidth , 70);

which has arguments float x, float y, float w, float h(wand hbeing width and height) the method ct.setSimpleColumnhas arguments float llx, float lly, float urx, float ury(llbeing lower leftand urbeing upper right). Thus your ct.setSimpleColumnshould look like this:

它有参数float x, float y, float w, float hw并且h是宽度和高度)该方法ct.setSimpleColumn有参数float llx, float lly, float urx, float uryll左下角ur右上角)。因此你ct.setSimpleColumn应该看起来像这样:

ct.setSimpleColumn(10, 10, 10 + rectWidth, 10 + 70);

A side issue

一个侧面问题

In addition to the main issue your result font size is 0.1 too large; essentially this is an error already pointed out by @David.

除了主要问题之外,您的结果字体大小为 0.1 太大;本质上,这是@David 已经指出的错误。

Your main loop in your getMaxFontSizemethod is this:

getMaxFontSize方法中的主循环是这样的:

while(measureWidth < width){
    measureWidth = bf.getWidthPoint(text, fontSize);     
    oldSize = fontSize;
    fontSize += 0.1f;
}

This essentially results in oldSize(which eventually is returned) being the first font size which does notfit. You could fix this by instead using

这基本上导致oldSize(最终返回)是第一个适合的字体大小。你可以通过使用来解决这个问题

while(bf.getWidthPoint(text, fontSize) < width){
    oldSize = fontSize;
    fontSize += 0.1f;
}

Even better would be an approach only calculating the string width once, not using a loop at all, e.g.

更好的是只计算一次字符串宽度的方法,根本不使用循环,例如

private static float getMaxFontSize(BaseFont bf, String text, int width)
{
    int textWidth = bf.getWidth(text);

    return (1000 * width) / textWidth;
}

(This method uses integer arithmetic. If you insist on an exact fit, switch to float or double arithmetic.)

(此方法使用整数算术。如果您坚持精确拟合,请切换到浮点或双精度算术。)

回答by Dawood ibn Kareem

There are two bugs here, both in

这里有两个错误,都在

while(measureWidth < width){
    measureWidth = bf.getWidthPoint(text, fontSize++);          
}
  1. You're staying in the loop until measureWidth >= width- in other words, by the time you escape from the whileloop, measureWidthis already too big for the rectangle.
  2. You're doing fontSize++, which means that after you've used fontSizeto calculate measureWidth, you're increasing it. When you do get round to returning it, it's one more than the value you just tested. So the return value from the method will be one more than the last value that you tested (which, due to point 1., was already too big).
  1. 您一直停留在循环中,直到measureWidth >= width- 换句话说,当您从while循环中逃脱时,measureWidth对于矩形来说已经太大了。
  2. 你在做fontSize++,这意味着在你使用fontSize了计算之后measureWidth,你正在增加它。当您确实要返回它时,它比您刚刚测试的值多 1。因此,该方法的返回值将比您测试的最后一个值多一个(由于第 1 点,该值已经太大了)。

回答by Дмитрий Игоревич

I've spent quite a while to implement such functionality using binary search method to find rectangle fitting font size. And today i stumbled upon an interesting method in iText...

我花了很长时间来使用二进制搜索方法来实现这样的功能,以找到适合字体大小的矩形。今天我在 iText 中偶然发现了一个有趣的方法......

It is quite a new method in iText ColumnText;

这是 iText 中相当新的方法ColumnText

public float fitText(Font font, String text, Rectangle rect, float maxFontSize, int runDirection)
//Fits the text to some rectangle adjusting the font size as needed.

In my version of iText it is static. See details: http://developers.itextpdf.com/reference/com.itextpdf.text.pdf.ColumnText

在我的 iText 版本中,它是静态的。查看详情:http: //developers.itextpdf.com/reference/com.itextpdf.text.pdf.ColumnText