GDI+ - 为啥 MeasureString 函数使用 Courier 字体失败?
Posted
技术标签:
【中文标题】GDI+ - 为啥 MeasureString 函数使用 Courier 字体失败?【英文标题】:GDI+ - Why the MeasureString function fails with a Courier font?GDI+ - 为什么 MeasureString 函数使用 Courier 字体失败? 【发布时间】:2018-02-11 10:26:03 【问题描述】:我正在使用 RAD Studio XE7。在几个项目中,我使用通用代码获取文本周围的边界框(以像素为单位),使用 GDI+ MeasureString 函数:
// configure the font to use. NOTE be careful, the SVG font size matches with the
// GDI font HEIGHT property, and not with the font SIZE
std::auto_ptr<TFont> pTextFont(new TFont());
pTextFont->Name = fontFamily;
pTextFont->Height = -fontSize;
std::auto_ptr<Gdiplus::Font> pFont(new Gdiplus::Font(pCanvas->Handle, pTextFont->Handle));
// char range is required to extract the first char bounds
Gdiplus::CharacterRange charRange;
charRange.First = 0;
charRange.Length = 1;
// configure the text format
std::auto_ptr<Gdiplus::StringFormat> pTextFormat(new Gdiplus::StringFormat());
pTextFormat->SetAlignment(Gdiplus::StringAlignmentNear);
pTextFormat->SetLineAlignment(Gdiplus::StringAlignmentNear);
pTextFormat->SetFormatFlags(Gdiplus::StringFormatFlagsNoWrap);
pTextFormat->SetTrimming(Gdiplus::StringTrimmingNone);
pTextFormat->SetMeasurableCharacterRanges(1, &charRange);
Gdiplus::RectF boundingBox;
Gdiplus::RectF viewBoxF(viewBox);
// measure the rect surrounding the text
if (pGraphics->MeasureString(text.c_str(), text.length(), pFont.get(), viewBoxF,
pTextFormat.get(), &boundingBox) != Gdiplus::Ok)
// error is handled here
此函数在某些情况下运行良好,但有时 MeasureString 会莫名其妙地失败,返回 InvalidParameter 作为错误消息,而例如字体参数如下:
pTextFont->Name = L"Courier";
pTextFont->Height = -16;
我首先认为这可能是字体后备问题。我尝试实现以下解决方案来获取后备字体:How to automatically choose most suitable font for different language?
但是,这并没有解决我的问题:
-
在上述情况下,返回的备用字体也是 Courier,这意味着我的系统以某种方式认为此字体是有效的(除非字体备用代码本身已损坏,但我认为并非如此)李>
对于另一个用 Delphi 编写的项目,我翻译了上面的代码,我遇到了完全相同的问题
GDI(不是 GDI+)似乎可以通过 SelectObject 和 DrawText 等函数使用此字体(使用 DrawText 和 DT_CALCRECT 测量时,返回的 rect 似乎有效)
另一方面,GDI+ 似乎无法对字体(在 pFont 中实例化的字体)进行处理。绘图功能也失败了
有人可以向我解释我做错了什么吗?
【问题讨论】:
不应该是“新快递”吗? 不,我没有混淆 Courier 和 Courier New。我从几个来源收到这个名称,afaik Courier 也是一个有效的字体名称(请参阅en.wikipedia.org/wiki/Courier_(typeface))但是 Courier 可能是包括 Courier New 在内的一类字体的通用名称,但我真的不知道.但是在这种情况下,GDI+ 引擎应该能够处理,还是不能?因为 GDI 确实... Courier New 是 Truetype 字体,但 Courier 不是。 但除非我错了,否则 GDI+ 应该也支持非 truetype 字体,对吧? 只是为了好奇:pTextFont->Height 不应该总是一个正值吗? GDI 应该如何计算负大小?至少在 C' 中,如果我尝试使用 negitve 字体大小绘制,我会收到异常。我怀疑 C 和 MeasureString 是一样的 【参考方案1】:与我的想法相反,GDI+ 确实不支持所有已安装的字体,正如 DrawString 函数备注 (https://msdn.microsoft.com/en-us/library/windows/desktop/ms535991(v=vs.85).aspx) 中所说:
请注意,GDI+ 不支持 PostScript 字体或 OpenType 字体 没有 TrueType 轮廓。
Courier 字体似乎属于不能在 GDI+ 中“按原样”使用的那种字体。因此,如果使用 GDI+ 绘制失败,我需要改用 GDI,或者提供替代字体。
【讨论】:
以上是关于GDI+ - 为啥 MeasureString 函数使用 Courier 字体失败?的主要内容,如果未能解决你的问题,请参考以下文章
为啥使用“RenderTargetBitmap”类会使 GDI 句柄数增加?