iText- ColumnText在Rectangle中设置文本适合大小

时间:2013-12-25 06:46:32

标签: java itext

我想将文本添加到矩形(x,y,w,h)中。文本应该适合矩形的大小(意味着它具有最大尺寸,但它仍然包含在矩形中) 我尝试根据BaseFont.getWidthPoint()测量文本大小。问题是最终文本大小不适合rect。它看起来像这样:
enter image description here

这是我的尝试:

  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;
}
你可以告诉我哪里错了吗?

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

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

   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; 
}

3 个答案:

答案 0 :(得分:4)

主要问题

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

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

与后来的cb.rectangle电话

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

其参数float x, float y, float w, float hwh是宽度和高度)方法ct.setSimpleColumn具有参数float llx, float lly, float urx, float ury ll 左下 右上角)。因此,您的ct.setSimpleColumn应如下所示:

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

副作用

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

getMaxFontSize方法中的主循环是:

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

这实际上导致oldSize(最终返回)是第一个适合的字体大小。您可以通过使用

来解决此问题
while(bf.getWidthPoint(text, fontSize) < width){
    oldSize = fontSize;
    fontSize += 0.1f;
}

更好的方法是仅计算字符串宽度一次,而不是完全使用循环,例如

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

    return (1000 * width) / textWidth;
}

(此方法使用整数运算。如果您坚持精确拟合,请切换到float或double算术。)

答案 1 :(得分:1)

这里有两个错误,都在

while(measureWidth < width){
    measureWidth = bf.getWidthPoint(text, fontSize++);          
}
  1. 你一直待到measureWidth >= width - 换句话说,当你从while循环中逃脱时,measureWidth对于矩形来说已经太大了。
  2. 您正在执行fontSize++,这意味着在您使用fontSize计算measureWidth后,您正在增加它。当你回归它时,它比你刚测试的值多一个。因此,该方法的返回值将比您测试的最后一个值多一个(由于第1点,已经太大了)。

答案 2 :(得分:0)

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

这是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.

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