itextsharp自动字体大小和仅限空格上的Linebreak

时间:2017-11-20 13:43:57

标签: wpf itext font-size viewbox

我有一个itextsharp表,具有严格的单元格高度和宽度。 然后我得到一个字数可以在字数和工作长度上有所不同的字符串。 如何将字体大小自动设置为尽可能大,并且只允许在单词结束后中断,就像在WPF的Viewbox中一样。

目前我正在处理这个问题:

Cell.AddElement(new Paragraph(text, new Font(Font.FontFamily.COURIER, 
Convert.ToInt32(FZ), 1)){Alignment = Element.ALIGN_CENTER});
            Cell.VerticalAlignment = Element.ALIGN_MIDDLE;
            Cell.HorizontalAlignment = Element.ALIGN_MIDDLE;
            Cell.Padding = 4;
            Cell.FixedHeight = Utilities.MillimetersToPoints(46);
            return Cell;

FZ是我直接从视箱中获取的字体,但直接转换不起作用

提前致谢!

1 个答案:

答案 0 :(得分:0)

我创建了一个包含大量"test""test\ntest""test test test test"等单元格的独立应用程序。结果如下:

enter image description here

我做了几个假设:

  • 我假设使用String值创建单元格。在内部,这将导致List包含单个Paragraph。此Paragraph将包含一个Text对象。
  • 我假设没有定义字体,这就是我引入默认字体(Helvetica)的原因。
  • 我假设没有定义前导,因此我引入了1的乘法前导。
  • 我假设没有定义填充,因此我引入了1
  • 的填充

这是我的代码:

import java.io.File;
import java.io.IOException;

import com.itextpdf.io.font.FontProgram;
import com.itextpdf.io.font.FontProgramFactory;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.IRenderer;

public class FitCell {

    public static final String[] TEST = {
        "test",
        "test test test test test test test",
        "test test",
        "test",
        "test test test test\ntest test test test test test test test test test test",
        "test",
        "test",
        "test",
        "test\ntest\ntest\ntest",
        "test",
        "test",
        "test",
        "test",
        "test",
        "test",
        "test",
        "test",
        "test\ntest",
        "test",
        "test",
        "test",
        "test",
        "test",
        "test",
        "test test test test test test test test test test test test test test"
    };

    private class FitContentCellRenderer extends CellRenderer {
        public FitContentCellRenderer(Cell modelElement) {
            super(modelElement);
            try {
                // We assume that the Cell is created by passing a String
                // This means that the Cell consists of one Paragraph
                Paragraph p = (Paragraph)modelElement.getChildren().get(0);
                // And that the Paragraph has one Text object
                Text t = (Text)p.getChildren().get(0);
                // Using the default font
                FontProgram f = FontProgramFactory.createFont();

                // We get the content from the Text object
                String content = t.getText();
                // Define a default font size (to make sure that you don't have text that is excessively big).
                float fs = 100;
                // Define a font size depending on the number of lines and the height
                int[] fontBbox = f.getFontMetrics().getBbox();
                int fh = (fontBbox[2] - fontBbox[1]);
                float padding = 1;
                modelElement.setPadding(padding);
                float ch = modelElement.getHeight() - 2 * padding;
                String text[] = content.split("\\r\\n|\\n|\\r");
                fs = Math.min(fs, ch / (fh * text.length) * FontProgram.UNITS_NORMALIZATION);
                // Loop over all the lines
                PdfFont font = PdfFontFactory.createFont(f);
                float cw = modelElement.getWidth().getValue() - 2 * padding;
                for (String l : text) {
                    float w = font.getWidth(l, 1);
                    fs = Math.min(fs, cw / w);
                }
                p.setFontSize(fs);
                p.setMultipliedLeading(1);
            }
            catch(IOException ioe) {
                // occurs when font program can't be created; this never happens
            }
        }
        @Override
        public IRenderer getNextRenderer(){
            return new FitContentCellRenderer(getModelElement());
        }
    }

    private class FitContentCell extends Cell {
        public FitContentCell() {
            super();
            this.setWidth(50);
        }

        @Override
        protected IRenderer makeNewRenderer() {
            return new FitContentCellRenderer(this);
        }
    }

    public static final String DEST = "results/tables/cell_fit_content.pdf";

    public static void main(String args[]) throws IOException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new FitCell().createPdf(DEST);
    }

    public void createPdf(String dest) throws IOException {
        PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
        Document document = new Document(pdf);
        Table table = new Table(new float[]{1, 1, 1, 1, 1, 1, 1});
        int testcount = 0;
        for (int i = 0; i < 70; i++) {
            if (testcount >= TEST.length) {
                testcount = 0;
            }
            table.addCell(new FitContentCell().add(TEST[testcount++]).setHeight(20 + 10 * (i / 10)));
        }
        document.add(table);
        document.close();
    }
}

在此代码中,我更改了名为Cell的子类中FitCell对象的行为。通过覆盖FitCell来更改CellRenderer的行为。

实际上,我并没有真正改变渲染器的行为,但是我在创建渲染器实例时(在其他任何事情发生之前)改变了一些东西。我为单元格定义了一个填充,我为Paragraph定义了一个字体和一个前导,我计算了Paragraph的字体大小,以便文本适合单元格。我首先定义一个100的字体大小(这是巨大的),但没有一个内容最终的字体大小为100,因为我首先确保所有文本都适合单元格的高度;然后我确保所有文本都符合单元格的宽度。

结果是所有文本都符合单元格。