java - itext7 - 不剪裁内容的最大字体大小
问题描述
以粗体编辑
我有一个表格,其中几个单元格包含Paragraph
s 和一些任意长的文本。表格宽度是通过 确定的useAllAvailableWidth
,我也在调用setAutoLayout
.
我正在使用Renderer
框架将Paragraph
's 的字体大小设置为尽可能大的值,而不会剪掉任何内容。
特别是我希望获得与iText Maximum Font Size类似的结果,但是这些问题是为 itext5 编写的。我正在使用itext7。
我已阅读此示例,并且由于先前的答案,我提出了以下(部分)解决方案:
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
. 可以在此存储库、webscrambles/src/main/kotlin/org/worldcubeassociation/tnoodle/server/webscrambles/pdf
文件FmcSolutionSheet.kt
和util/FooRenderer.kt
.
如何调整我Renderer
的以防止 Cell 溢出?
解决方案
拥有一个布局元素,您可以从中创建一个渲染器子树,并尝试将其布局在给定区域中。然后根据元素是否完全适合该区域或没有足够的空间,您可以增加或减少字体大小并重试。
为了测试不同的字体大小,二分搜索是我们最好的朋友,并且可以大大加快速度。
首先,一个帮助函数递归地设置元素的字体大小:
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();
推荐阅读
- output - 文本文件已保存。在记事本中打开时,行是缩进的。不确定这是为什么?
- r - 在 R 中编码一个多种族类别
- cakephp - 如何在 CakePHP 中通过 $form->end() 使用特殊字符
- android - 将拆分的 APK 转换为 aab
- javascript - Firestore 如何清除Persistence()
- sas - SAS EG 7.15 错误:尝试建立连接的 CLI 错误:[Microsoft][ODBC Driver Manager] Driver's SQLAllocHandle on SQL_HANDLE_ENV failed
- javascript - 我可以在打字稿中使用什么来显示两个接口的值之间的关系
- javascript - 反应 setState 不更新状态数组
- git - 为什么 --cached 标志似乎在不同的 git 命令中引用了不同的内存?
- swift - 在我的角色上创建一个盾牌!(附加 2 个精灵)