0

I can measure the text dimensions with DirectWrite for an existing IDWriteTextFormat:

    CComPtr<IDWriteTextLayout> lay = 0;
    pWriteFactory->CreateTextLayout(txt, (UINT32)wcslen(txt), TextFormat, 1000, 1000, &lay);
    DWRITE_TEXT_METRICS m = { 0 };
    lay->GetMetrics(&m);

Now, is there a way to do the reverse? On a given rectangle, find out how would I call pWriteFactory->CreateTextFormat() (what to pass as font size) to have the text fit into this rectangle without wrapping.

Currently, my only way is to manually estimate it:

float TextValueForRect(D2F Fit, LOGFONT& lf, const wchar_t* txt, UINT32 ly)
{
    DWRITE_FONT_STYLE fst = DWRITE_FONT_STYLE_NORMAL;
    if (lf.lfItalic)
        fst = DWRITE_FONT_STYLE_ITALIC;
    DWRITE_FONT_STRETCH fsr = DWRITE_FONT_STRETCH_NORMAL;
    auto we = lf.lfWeight > 500 ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL;

    FLOAT fs = 500.0f;
    D2D1_POINT_2F Bounds = { 0,1000.0f };

    for (int t = 0; t < 20; t++)
    {
        CComPtr<IDWriteTextFormat> Text;
        WriteFa->CreateTextFormat(lf.lfFaceName, 0, we, fst, fsr, fs, L"", &Text);

        auto tu = MeasureString(WriteFa, Text, txt, ly);
        if (std::get<0>(tu) < Fit.Width() && std::get<1>(tu) < Fit.Height())
        {
            // Enlarge font
            Bounds.x = fs;
            fs = Bounds.x + (Bounds.y - Bounds.x) / 2.0f;
        }
        else
            if (std::get<0>(tu) > Fit.Width() || std::get<1>(tu) > Fit.Height())
            {
                // Smallen font
                Bounds.y = fs;
                fs = Bounds.x + (Bounds.y - Bounds.x) / 2.0f;
            }
    }

    return (Bounds.y + Bounds.x) / 2.0f;
}

Thanks a lot

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
  • I don't think dwrite has something like that but font size and sizes are not integers, so have you tried proportionality `fs = (rectwidth * fs0) / rectwidth0` – Simon Mourier May 01 '20 at 08:02
  • What would `fs0` be? I don't have information for a pre-existing measurement. – Michael Chourdakis May 01 '20 at 08:11
  • There is no way to get such estimation with existing DirectWrite api. You probably could estimate it yourself, by binary search from small enough to large enough font size. – bunglehead May 01 '20 at 08:18
  • @bunglehead I'm already doing that- question edited. – Michael Chourdakis May 01 '20 at 08:24
  • 1
    yes, you need one test (like you do in your code for 1000). You measure for one given font size (fs0) => rectwith0, and then compute the font size (fs) for your required width (rectwidth) by this fs = (rectwidth * fs0) / rectwidth0 – Simon Mourier May 01 '20 at 10:18
  • 1
    Using such proportional function means making assumptions of course, in particular it's assuming that metrics are linearly dependent on font size, which is not always the case, that text format disables wrapping, which is not always usable. But some iterative process like that would work for some cases. – bunglehead May 01 '20 at 13:28

0 Answers0