有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java iText ColumnText设置矩形中的文本大小

我想将文本添加到一个矩形中(x,y,w,h)。文本应该适合矩形的大小(意味着它有一个最大大小,但它仍然包含在矩形中)
我试图根据BaseFont.getWidthPoint()来测量文本大小。问题是最终的文本大小不能适应矩形。看起来是这样的:
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) 个答案

  1. # 1 楼答案

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

    这是iText{}中的一种新方法

    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

  2. # 2 楼答案

    这里有两个bug,都在

    while(measureWidth < width){
        measureWidth = bf.getWidthPoint(text, fontSize++);          
    }
    
    1. 您将一直停留在循环中直到measureWidth >= width-换句话说,当您退出while循环时,measureWidth对于矩形来说已经太大了
    2. 你在做fontSize++,这意味着在你用fontSize来计算measureWidth之后,你在增加它。当您确实抽出时间返回它时,它比您刚才测试的值多出一个。因此,该方法的返回值将比您测试的最后一个值(由于第1点,该值已经太大)多一个
  3. # 3 楼答案

    主要问题

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

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

    与后面的cb.rectangle调用不同

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

    方法{}有参数{}({}和{}是宽度和高度)方法{}有参数{}(ll是左下ur是右上)。因此,您的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;
    }
    

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