【问题标题】:itext7 - Maximum font size without clipping contentitext7 - 不剪裁内容的最大字体大小
【发布时间】:2020-01-15 07:53:23
【问题描述】:

以粗体编辑

我有一个表格,其中几个单元格包含 Paragraphs 和一些任意长的文本。 表格宽度是通过useAllAvailableWidth确定的,我也在调用setAutoLayout

我正在使用Renderer 框架将Paragraph 的字体大小设置为尽可能大的值,而不会剪掉任何内容。

我特别希望获得与iText Maximum Font Size 类似的结果,但是这些问题是为 itext5 编写的。我正在使用 itext7

我已阅读this sample由于之前的回答,我提出了以下(部分)解决方案:

class FontSizeRenderer(val content: Paragraph) : ParagraphRenderer(content) {
    override fun getNextRenderer() = FontSizeRenderer(content)

    override fun layout(layoutContext: LayoutContext?): LayoutResult {
        val currentFontSize = content.getProperty<UnitValue>(Property.FONT_SIZE).value

        return layoutBinarySearch(layoutContext, 1f, currentFontSize, 20)
    }

    private tailrec fun layoutBinarySearch(layoutContext: LayoutContext?, minFontSize: Float, maxFontSize: Float, iterationThreshold: Int): LayoutResult {
        val currentLayout = super.layout(layoutContext)

        if (iterationThreshold <= 0) {
            return currentLayout
        }

        val currentFontSize = content.getProperty<UnitValue>(Property.FONT_SIZE).value

        return if (currentLayout.status == LayoutResult.FULL) {
            val increment = (currentFontSize + maxFontSize) / 2
            content.setFontSize(increment)

            layoutBinarySearch(layoutContext, currentFontSize, maxFontSize, iterationThreshold - 1)
        } else {
            val decrement = (minFontSize + currentFontSize) / 2
            content.setFontSize(decrement)

            layoutBinarySearch(layoutContext, minFontSize, currentFontSize, iterationThreshold - 1)
        }
    }
}

当在一个成熟的表中使用这个渲染器时,它“有点工作”,因为它开始递归但它停止得太早了。

第一页底部单元格中的预期输出字符串为Scramble: R' U' F R F2 D2 R' B2 U2 R F2 R' B2 R' B F U' L2 B' R' B' U' R F2 R' U' F。完整的代码示例可以在this repositorywebscrambles/src/main/kotlin/org/worldcubeassociation/tnoodle/server/webscrambles/pdf、文件FmcSolutionSheet.ktutil/FooRenderer.kt 下查看(和下载)。

如何调整我的Renderer 以防止单元格溢出?

【问题讨论】:

    标签: java pdf itext7


    【解决方案1】:

    拥有一个布局元素,您可以从中创建一个渲染器子树,并尝试将其布局在给定区域中。然后根据元素是否完全适合该区域或没有足够的空间,您可以增加或减少字体大小并重试。

    为了测试不同的字体大小,二分搜索是我们最好的朋友,它可以大大加快速度。

    首先,递归设置元素字体大小的辅助函数:

    private void setFontSizeRecursively(IElement element, float size) {
        element.setProperty(Property.FONT_SIZE, UnitValue.createPointValue(size));
        if (element instanceof com.itextpdf.layout.element.AbstractElement) {
            for (Object child : ((AbstractElement) element).getChildren()) {
                setFontSizeRecursively((IElement) child, size);
            }
        }
    }
    

    现在是代码的重要部分。在二分搜索正文中,我们缩放元素的所有字体大小并模拟布局以查看我们的根元素(表格)是否适合给定区域。然后我们移动左或右搜索边界并再次尝试直到我们收敛。您可以根据自己的喜好调整迭代次数(在代码中设置为 20),以权衡准确性/速度。如果您可以根据预期输入做出这样的判断,您还可以调整二进制搜索的左右边界。最后,我们设置我们收敛的字体大小比例并进行最终布局。

    PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
    Document document = new Document(pdfDocument);
    
    Table table = new Table(UnitValue.createPercentArray(new float[] {20, 40, 40}));
    for (int i = 0; i < 9; i++) {
        table.addCell(new Cell().add(new Paragraph("Hello random text")));
    }
    
    float lFontSize = 1f;
    float rFontSize = 100f;
    
    float desiredWidth = 300;
    float desiredHeight = 400;
    
    table.setWidth(UnitValue.createPointValue(desiredWidth));
    
    for (int i = 0; i < 20; i++) {
        float midFontSize = (lFontSize + rFontSize) / 2;
        setFontSizeRecursively(table, midFontSize);
    
        IRenderer tableRenderer = table.createRendererSubTree().setParent(document.getRenderer());
        LayoutResult result = tableRenderer.layout(new LayoutContext(new LayoutArea(1,
                new Rectangle(0, 0, desiredWidth, desiredHeight)))); // You can tweak desired size to fit the table in
    
        if (result.getStatus() == LayoutResult.FULL) {
            lFontSize = midFontSize;
        } else {
            rFontSize = midFontSize;
        }
    }
    
    setFontSizeRecursively(table, lFontSize);
    document.add(table);
    
    document.close();
    

    【讨论】:

    • 感谢代码示例!如果我不知道表格的宽度和高度,因为它设置为自动布局,因此无法轻松确定LayoutAreaRectangle
    • @suushiemaniac 是您添加到页面的根元素吗?如果是这样,您知道页面大小和页边距,您可以通过简单的计算找到该区域。如果没有,那么您需要调整您的问题以包含更多详细信息和显示您的案例的代码示例
    • 我已经编辑了我的问题,其中包含更多细节和我在此期间获得的新见解。
    • @suushiemaniac 请向我们展示您如何创建表格并将其添加到文档中
    猜你喜欢
    • 2011-12-03
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多