Positioning Texts with different font sizes

Hi,

I need to achieve something like this:
grafik.png (32.2 KB)

Please not that the font sizes are extremely different (the biggest being 280, the smallest being 14).
Unfortunately anything I try leads to some text being not aligned correctly relative to the other texts… for example the “big 5” might be lower than the “29” (the upper line of the 5 should be on the same level as the upper part of the “29”)… or the “Netto”-text is placed with too much whitespace etc.

Can you please advise on how to achieve the result in the screenshot?
Thanks in advance.

Best Regards
Yahia

@it-yeq

Can you please share the sample code snippet that you have tried so far to achieve your requirements? We will modify it and will try to produce the expected results at our end and share with you.

Hi,

some small helper methods:

    Aspose.Pdf.Text.TextParagraph GetTextParagraph(string pText, Aspose.Pdf.Text.Font pFont, double pFontSize, Aspose.Pdf.Rectangle pRect)
    {
        Aspose.Pdf.Text.TextParagraph Result = new Aspose.Pdf.Text.TextParagraph();
        Result.FormattingOptions.LineSpacing = Aspose.Pdf.Text.TextFormattingOptions.LineSpacingMode.FullSize;
        Result.FormattingOptions.WrapMode = Aspose.Pdf.Text.TextFormattingOptions.WordWrapMode.ByWords;
        Result.Rectangle = pRect;

        Result.AppendLine(pText, new Aspose.Pdf.Text.TextState(pFontSize) { Font = pFont });

        return (Result);
    }

    double GetTextWidthFromParagraph(Aspose.Pdf.Text.TextParagraph pParagraph)
    {
        double Result = 0.0;

        if (pParagraph != null)
        {
            Result = Math.Ceiling(pParagraph.TextRectangle.Width * 10) / 10;
        }

        return (Result);
    }

    double GetTextHeightFromParagraph(Aspose.Pdf.Text.TextParagraph pParagraph)
    {
        double Result = 0.0;

        if (pParagraph != null)
        {
            Result = Math.Ceiling(pParagraph.TextRectangle.Height * 10) / 10;
        }

        return (Result);
    }

and this is the current code:

        using (System.IO.MemoryStream vMStream = new System.IO.MemoryStream(System.IO.File.ReadAllBytes("SomeFont.otf")))
        {
            vFont = Aspose.Pdf.Text.FontRepository.OpenFont(vMStream, Aspose.Pdf.Text.FontTypes.OTF);
        };

        using (var vPDFDoc = new Aspose.Pdf.Document())
        {
            vPDFDoc.DisableFontLicenseVerifications = true;
            vPDFDoc.PageLayout = Aspose.Pdf.PageLayout.SinglePage;

            var vPageSize = new Aspose.Pdf.PageSize(Aspose.Pdf.PageSize.A3.Width, Aspose.Pdf.PageSize.A3.Height) { IsLandscape = true };
            var vPDFPage = vPDFDoc.Pages.Add();
            vPDFPage.SetPageSize(vPageSize.Width, vPageSize.Height);
            vPDFPage.PageInfo.Margin = new Aspose.Pdf.MarginInfo(0,0,0,0);

            var vPageGrossRECT = vPDFPage.GetPageRect(true);
            vPageGrossRECT = new Aspose.Pdf.Rectangle((vPageGrossRECT.Width * 15) / 1000, (vPageGrossRECT.Height * 15) / 1000, (vPageGrossRECT.Width * 985) / 1000, (vPageGrossRECT.Height * 985) / 1000);

            var vPageTextBuilder = new Aspose.Pdf.Text.TextBuilder(vPDFPage);

            var vCurrW = 0.0;
            var vCurrH = 0.0;

            var vText = "29";
            var vFontSize = 163;

            var vParagraphTEMP = GetTextParagraph(vText, vFont, vFontSize, vPageGrossRECT);

            vCurrW = GetTextWidthFromParagraph(vParagraphTEMP);
            vCurrH = GetTextHeightFromParagraph(vParagraphTEMP);

            var vCurrLLY = vPageGrossRECT.URY - vCurrH;
            var vCurrLLX = vPageGrossRECT.URX - vCurrW;


            vPageTextBuilder.AppendParagraph(GetTextParagraph(vText, vFont, vFontSize, new Aspose.Pdf.Rectangle(vCurrLLX, vCurrLLY, vCurrLLX + vCurrW, vCurrLLY + vCurrH)));

            vText = "5";
            vFontSize = 280;

            vParagraphTEMP = GetTextParagraph(vText, vFont, vFontSize, vPageGrossRECT);

            vCurrW = GetTextWidthFromParagraph(vParagraphTEMP);
            vCurrH = GetTextHeightFromParagraph(vParagraphTEMP);

            vCurrLLY = vPageGrossRECT.URY - vCurrH;
            vCurrLLX = vCurrLLX - vCurrW;

            vPageTextBuilder.AppendParagraph(GetTextParagraph(vText, vFont, vFontSize, new Aspose.Pdf.Rectangle(vCurrLLX, vCurrLLY, vCurrLLX + vCurrW, vCurrLLY + vCurrH)));

            vText = "Netto";
            vFontSize = 14;

            vParagraphTEMP = GetTextParagraph(vText, vFont, vFontSize, vPageGrossRECT);

            vCurrW = GetTextWidthFromParagraph(vParagraphTEMP);
            vCurrH = GetTextHeightFromParagraph(vParagraphTEMP);

            vCurrLLX = vPageGrossRECT.URX - vCurrW;

            vPageTextBuilder.AppendParagraph(GetTextParagraph(vText, vFont, vFontSize, new Aspose.Pdf.Rectangle(vCurrLLX, vCurrLLY, vCurrLLX + vCurrW, vCurrLLY + vCurrH)));


            using (System.IO.MemoryStream vMStream = new System.IO.MemoryStream())
            {
                vPDFDoc.Save(vMStream);

                vMStream.Position = 0;

                System.IO.File.WriteAllBytes(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Test.pdf"), vMStream.ToArray());
            };
        };

The text ends up on really strange positions :frowning:

Thanks in advance.

Best Regards
Yahia

The result looks like this:
grafik.png (5.0 KB)

The yellow areas are the ones I don’t understand:
The upper line of the “5” should be at the same level as the upper part of the “29”
AND
The lower part of the “Netto” should be at the same level as the lower part of the “5”.

@it-yeq

We have logged an investigation task as PDFNET-50303 in our issue management system to analyze your requirements and investigate how can they be achieved. The ticket ID has been linked to this forum thread so that you will be notified as soon as it is resolved. Please be patient and spare us some time.

We are sorry for the inconvenience.

Any update on this issue?

@it-yeq

The ticket was recently logged in our issue management system and we will investigate/resolve it on first come first serve basis. We will surely inform you in this forum thread as soon as we make some progress towards its resolution. Please be patient and give us some time.

We are sorry for the inconvenience.

any news on this issue?

@it-yeq

The ticket was recently logged in our issue tracking system under normal support model. We are afraid that it is not yet investigated. We will investigate and resolve it on a first come first serve basis and let you know as soon as we have additional updates regarding its resolution. Please be patient and spare us some time.

We are sorry for the inconvenience.

Any news on this issue regarding Texts?

@it-yeq

We regret to share that the earlier logged ticket could not get resolved yet due to other pending issues in the queue. We have recorded your concerns and will surely inform you as soon as we have some definite updates regarding its resolution. Please be patient and spare us some time.

We apologize for your inconvenience.

any news when this issue will be resolved?

@it-yeq

Sadly, the ticket could not get resolved due to previously logged issues in the queue. Nevertheless, your concerns have already been recorded under the ticket and you will be notified once the ticket is resolved. We highly appreciate your patience and cooperation in this regard.

We apologize for the delay and the inconvenience.

any news regardings this issue?

@it-yeq

Regretfully, the ticket is not yet resolved due to its complexity level. However, we will surely let you know once we have some definite updates regarding issue fix or its resolution ETA. We humbly apologize for the inconvenience caused.

Hi,

Is it possible to get this problem fixed within the next 4 weeks? Is there something like a paid fix?

Thanks in advance.

Best Regards
Yahia

@it-yeq

We do offer paid support options where issues are resolved on urgent basis and have highest priority. We will soon let you know how soon the resolution can be made in case you use this option.

@it-yeq

Please review the information about font metrics. This is necessary to understand the proposed solution.

To align text to the top line of numeric characters it should to take into account ‘internal leading’ value. See: 1920px-Font_metrics.svg.png

Body height = Descent + Ascent Ascent = Cap Height + Internal Leading // Number characters glyphs have height close to the Cap Height value

Different font families has different ratio of ‘cap heigth’ to ‘body height’. It is about of 0.582 for the “Arial”. (Refer to the font documentation or special tools to get the value for other fonts.) The ratio is independent from font size. But measured values of ‘cap heigth’ and ‘internal leading’ depends from the font size.

Please consider the following code:

public static double GetFontMetricsInternalLeading(string fontName, int fontSize)
{
    int emSize;                     // font family body height in design units
    int descent;                    // font family descent in design units
    double capHeightRatio = 0.582;  // cap height ratio for Arial font. It may differ for other font families
    double internalLeading;         // internal leading in design units
    double internalLeadingPoints;   // internal leading converted to points

    FontFamily fontFamily = new FontFamily(fontName);

    emSize = fontFamily.GetEmHeight(System.Drawing.FontStyle.Regular);
    descent = fontFamily.GetCellDescent(System.Drawing.FontStyle.Regular);
    internalLeading = emSize - descent - emSize * capHeightRatio;

    internalLeadingPoints = fontSize * internalLeading / emSize;

    return internalLeadingPoints;
}
string fontName = "Arial";
Font vFont = Aspose.Pdf.Text.FontRepository.FindFont(fontName);

using (var vPDFDoc = new Aspose.Pdf.Document())
{
    vPDFDoc.DisableFontLicenseVerifications = true;
    vPDFDoc.PageLayout = Aspose.Pdf.PageLayout.SinglePage;

    var vPageSize = new Aspose.Pdf.PageSize(Aspose.Pdf.PageSize.A3.Width, Aspose.Pdf.PageSize.A3.Height) { IsLandscape = true };
    var vPDFPage = vPDFDoc.Pages.Add();
    vPDFPage.SetPageSize(vPageSize.Width, vPageSize.Height);
    vPDFPage.PageInfo.Margin = new Aspose.Pdf.MarginInfo(0, 0, 0, 0);

    var vPageGrossRECT = vPDFPage.GetPageRect(true);
    vPageGrossRECT = new Aspose.Pdf.Rectangle((vPageGrossRECT.Width * 15) / 1000, 
        (vPageGrossRECT.Height * 15) / 1000, (vPageGrossRECT.Width * 985) / 1000, 
        (vPageGrossRECT.Height * 985) / 1000);

    var vPageTextBuilder = new Aspose.Pdf.Text.TextBuilder(vPDFPage);

    var vCurrW = 0.0;
    var vCurrH = 0.0;

    var vText = "29";
    var vFontSize = 163;

    var vParagraphTEMP = GetTextParagraphModified(vText, vFont, vFontSize, vPageGrossRECT);

    vCurrW = GetTextWidthFromParagraph(vParagraphTEMP);
    vCurrH = GetTextHeightFromParagraph(vParagraphTEMP);
    var subTextInternalLeading = GetFontMetricsInternalLeading(fontName, vFontSize);

    var vCurrLLY = vPageGrossRECT.URY - vCurrH;
    var vCurrLLX = vPageGrossRECT.URX - vCurrW;

    vPageTextBuilder.AppendParagraph(GetTextParagraphModified(vText, vFont, vFontSize, 
        new Aspose.Pdf.Rectangle(vCurrLLX, vCurrLLY, vCurrLLX + vCurrW, vCurrLLY + vCurrH)));

    vText = "5";
    vFontSize = 280;

    vParagraphTEMP = GetTextParagraphModified(vText, vFont, vFontSize, vPageGrossRECT);

    vCurrW = GetTextWidthFromParagraph(vParagraphTEMP);
    vCurrH = GetTextHeightFromParagraph(vParagraphTEMP);
    var mainTextInternalLeading = GetFontMetricsInternalLeading(fontName, vFontSize);

    vCurrLLY = vPageGrossRECT.URY - vCurrH + (mainTextInternalLeading - subTextInternalLeading);
    vCurrLLX = vCurrLLX - vCurrW;

    vPageTextBuilder.AppendParagraph(GetTextParagraphModified(vText, vFont, vFontSize, 
        new Aspose.Pdf.Rectangle(vCurrLLX, vCurrLLY, vCurrLLX + vCurrW, vCurrLLY + vCurrH)));

    vText = "Netto";
    vFontSize = 14;

    vParagraphTEMP = GetTextParagraph(vText, vFont, vFontSize, vPageGrossRECT);

    vCurrW = GetTextWidthFromParagraph(vParagraphTEMP);
    vCurrH = GetTextHeightFromParagraph(vParagraphTEMP);

    vCurrLLX = vPageGrossRECT.URX - vCurrW;

    vPageTextBuilder.AppendParagraph(GetTextParagraph(vText, vFont, vFontSize,
        new Aspose.Pdf.Rectangle(vCurrLLX, vCurrLLY, vCurrLLX + vCurrW, vCurrLLY + vCurrH)));


    using (System.IO.MemoryStream vMStream = new System.IO.MemoryStream())
    {
        vPDFDoc.Save(vMStream);

        vMStream.Position = 0;

        System.IO.File.WriteAllBytes(System.IO.Path.Combine(dataDir, "50303_out.pdf"), vMStream.ToArray());
    };
};

It produces expected result.

1920px-Font_metrics.svg.png (21.1 KB)
50303_out.pdf (74.3 KB)

Hi,

thank you - this looks good.
Is it possible to get a method (perhaps on the Font class) which returns the Cap Height Ratio for a given font?

Best Regards
Yahia

@it-yeq

We will surely investigate the possibility of this requirement. Can you please share a little bit more details with some example so that we can log a ticket and share the ID with you?