c# - 如何使用 itext7 在固定矩形内缩放文本?
问题描述
我正在尝试在 c# 中使用 itext7 制作一个 pdf 文档,该文档应该具有包含不同文本的固定矩形,这些文本应该在(不可见)矩形的边界内缩放。
我试图找到是否有自动缩放,但到目前为止只发现表单域的自动缩放。由于 pdf 将用于绘制文本,因此表单域没有用。
下面的代码是放置一个具有固定尺寸的“框”的片段,其中所有文本都应按比例显示(在一行上)
float fontSize = 22f;
Text lineTxt = new Text("A VERY LONG TEXT SHOULD BE SCALED").SetFont(lineFont).SetFontSize(fontSize);
iText.Kernel.Geom.Rectangle lineTxtRect = new iText.Kernel.Geom.Rectangle(100, posHeight - 200, (float)plotline.producttype_plotmaxwidthpts, (float)plotline.producttype_plotmaxheightpts);
Div lineDiv = new Div();
lineDiv.SetMaxHeight((float)plotline.producttype_plotmaxheightpts);
lineDiv.SetWidth((float)plotline.producttype_plotmaxwidthpts);
lineDiv.SetHeight((float)plotline.producttype_plotmaxheightpts);
lineDiv.SetVerticalAlignment(VerticalAlignment.MIDDLE);
lineDiv.SetBorder(new DashedBorder(1));
Paragraph linePara = new Paragraph().Add(lineTxt).
SetTextAlignment(iText.Layout.Properties.TextAlignment.CENTER).
SetBorder(new DottedBorder(1)).
SetMultipliedLeading(0.7f).
SetMaxHeight((float)plotline.producttype_plotmaxheightpts).
SetHeight((float)plotline.producttype_plotmaxheightpts);
lineDiv.Add(linePara);
new Canvas(PageCanvas, pdf, lineTxtRect).Add(lineDiv).SetBorder(new SolidBorder(1f));
解决方案
iText 7 的布局模块允许您模拟元素的渲染(通过从元素创建渲染器树然后使用Layout
方法)并检查它是否适合给定区域(通过检查LayoutResult
对象)。因此,您可以做的是检查文本是否适合具有给定字体大小的固定矩形。然后你可以对字体大小进行二进制搜索。
这是一个示例代码:
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
Text lineTxt = new Text("A VERY LONG TEXT SHOULD BE SCALED");
iText.Kernel.Geom.Rectangle lineTxtRect = new iText.Kernel.Geom.Rectangle(100, 200, 100, 100);
Div lineDiv = new Div();
lineDiv.SetVerticalAlignment(VerticalAlignment.MIDDLE);
lineDiv.SetBorder(new DashedBorder(1));
Paragraph linePara = new Paragraph().Add(lineTxt)
.SetTextAlignment(iText.Layout.Properties.TextAlignment.CENTER).SetBorder(new DottedBorder(1))
.SetMultipliedLeading(0.7f);
lineDiv.Add(linePara);
float fontSizeL = 1; // 1 is the font size that is definitely small enough to draw all the text
float fontSizeR = 20; // 20 is the maximum value of the font size you want to use
Canvas canvas = new Canvas(new PdfCanvas(pdfDocument.AddNewPage()), pdfDocument, lineTxtRect);
// Binary search on the font size
while (Math.Abs(fontSizeL - fontSizeR) > 1e-1) {
float curFontSize = (fontSizeL + fontSizeR) / 2;
lineDiv.SetFontSize(curFontSize);
// It is important to set parent for the current element renderer to a root renderer
IRenderer renderer = lineDiv.CreateRendererSubTree().SetParent(canvas.GetRenderer());
LayoutContext context = new LayoutContext(new LayoutArea(1, lineTxtRect));
if (renderer.Layout(context).GetStatus() == LayoutResult.FULL) {
// we can fit all the text with curFontSize
fontSizeL = curFontSize;
} else {
fontSizeR = curFontSize;
}
}
// Use the biggest font size that is still small enough to fit all the text
lineDiv.SetFontSize(fontSizeL);
canvas.Add(lineDiv);
pdfDocument.Close();
推荐阅读
- java - Spring boot 和 springfox-swagger2 - $ref 值必须是符合 RFC3986 的百分比编码 URI - 提供的解决方案
- docker - Ansible - 通过 Docker 安装 Check_MK
- null - 在 Java8 中使用流时我们是否应该始终检查 Optional?
- azure-devops - 本地 Azure Devops Server 2020 上的 odata 查询的使用和资源限制是什么?
- android - Kotlin Coroutine 抛出 JobCancellationException 并触发观察者
- cypress - 等到元素在 Cypress 中消失
- reactjs - 如何将 onClick 从父链接传播到嵌套跨度?
- python - 如何将时间序列中的每个值作为具有唯一 ID 的列
- ios - 水平 UIStackView :值 999 或 1000 在水平内容压缩阻力中是否有任何特殊含义?
- python - 我怎样才能得到一条线?