简体   繁体   中英

How to scale text within a fixed rectangle with itext7?

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));

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);

// 1 is the font size that is definitely small enough to draw all the text
float fontSizeL = 1;

// 20 is the maximum value of the font size you want to use
float fontSizeR = 20;

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM