Directwrite:获取字体的高度

我的目标:   我想获得IDWriteTextFormat字体的高度,这样我就可以计算出一定高度的IDWriteTextLayout可以容纳多少行文本。 我的问题:   现在我正在使用此代码计算可见的行数:
inline int kmTextCtrl::GetVisLines() const
{

    /* pTextFormat is an IDWriteTextFormat pointer, dpi_y is the desktop's vertical dpi,
       and GetHeight() returns the height (in pixels) of the render target. */
    float size = (pTextFormat->GetFontSize()/72.0f)*dpi_y;
    return (int)(GetHeight()/size);
}
对于某些字体,计算似乎是准确的,但对于任何TrueType字体(例如:Courier New,Arial,Times New Roman)都没有。对于这些字体,显示的文本剪裁得远远低于渲染目标的下垂直边界。 一些背景:   我正在制作一个文本回滚缓冲区控件,它使用IDWriteTextLayout将文本放到控件的渲染目标中。我使用GetVisLines()的结果来确定循环缓冲区(由行存储std :: strings中的文本)中的文本行数以拉入布局,并在每次滚动或调整窗口大小时重新创建它。 这是使用“本机”Win32 API C ++完成的。     
已邀请:
最简单和最健壮的方法是仅仅询问布局本身的文本指标,因为这是它为设计,绘图和测量设计的两件事之一。你可以使用文本格式创建一个
IDWriteTextLayout
并调用
GetMetrics
来获得
DWRITE_TEXT_METRICS::height
。我猜你正在使用
ID2D1RenderTarget::DrawText
并传递一种文本格式,所以你可能没有直接创建一个布局,但是调用
DrawText
就像调用
CreateTextLayout
自己跟着
DrawTextLayout
一样。 请注意,通过较低层来获得此答案(
IDWriteFontFace
之类)会做出某些假设,即通用世界就绪文本控件不应该假设,例如假设将使用基本字体并且所有行都具有相同的高度。只要所有字符都出现在给定的基本字体中,这就好了(很可能你大部分都显示英语,这就是为什么一切都很好),但是输入一些CJK或RTL语言(像Times这样的基本字体) New Roman当然不支持),并且行高将相应地增加或缩小到替换字体。 GDI重新调整替换字体,使它们符合基本字体的高度,但这会导致泰语和藏语等语言中的字母很差,需要更多的呼吸空间来上升和下降。
IDWriteTextLayout
和WPF / Word中的其他布局将所有字体字形保持在相同的em大小,这意味着它们在彼此相邻时排列得更好;但它确实意味着线高是可变的。 如果您只是绘制每行文本,就好像它们都是相同的高度一样,您可以看到字形之间的字形和非均匀基线之间的重叠,或者控件顶部和底部的剪裁。所以理想的做法是使用每条线的实际高度;但是如果你需要它们都是相同的高度(或者如果它使控制太复杂),那么至少使用
SetLineSpacing
DWRITE_LINE_SPACING_UNIFORM
设置一个明确的行间距到基本字体 - 这样基线是均匀间隔的。 虽然,好奇,是的,线高确实是使用字体设计指标上升+下降,加上恰好存在的任何lineGap(大多数字体设置为零,但Gabriola是大线间隙的一个很好的例子) ,乘以em大小并除以每个em的单位。注意所有的em尺寸都是DIP(典型的96DPI表示1:1,DIP正好==像素),而不是点(1/72英寸)。     
我找到了答案。 要在Directwrite中查找行的间距(字体高度加间隙),您必须执行类似于以下操作的操作:
inline int kmTextCtrl::GetVisLines() const
{

    IDWriteFontCollection* collection;
    TCHAR name[64]; UINT32 findex; BOOL exists;
    pTextFormat->GetFontFamilyName(name, 64);
    pTextFormat->GetFontCollection(&collection);
    collection->FindFamilyName(name, &findex, &exists); 
    IDWriteFontFamily *ffamily;
    collection->GetFontFamily(findex, &ffamily);
    IDWriteFont* font;
    ffamily->GetFirstMatchingFont(pTextFormat->GetFontWeight(), pTextFormat->GetFontStretch(), pTextFormat->GetFontStyle(), &font);
    DWRITE_FONT_METRICS metrics;
    font->GetMetrics(&metrics);
    float ratio = pTextFormat->GetFontSize() / (float)metrics.designUnitsPerEm;
    float size = (metrics.ascent + metrics.descent + metrics.lineGap) * ratio;
    float height = GetHeight();
    int retval = static_cast<int>(height/size);
    ffamily->Release();
    collection->Release();
    font->Release();
    return retval;
}
当然,您可能不希望每次必须调用常用的内联函数时都执行所有操作。     

要回复问题请先登录注册