问题
I'm trying to make a pdf document with itext7 in c# which should have fixed rectangles containing varying text that should scale within the boundaries of the (invisible) rectangles.
I have tried to find if there's automatic scaling, but so far only found auto-scaling for formfields. Since the pdf will be used for plotting text, formfields are of no use.
Code below is a snippet placing a 'box' with fixed dimensions, where all the text should be shown scaled (on one line)
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));
回答1:
Layout module of iText 7 allows you to simulate rendering of an element (by creating the renderer tree from the element and then using Layout
method) and check whether it fits the given area (by checking LayoutResult
object). Thus what you can do is check whether the text fits into your fixed rectangle with the given font size. Then you can just do a binary search on the font size.
Here is a sample code:
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();
来源:https://stackoverflow.com/questions/57890666/how-to-scale-text-within-a-fixed-rectangle-with-itext7