https://opensource.apple.com/source/WebCore/WebCore-955.66/platform/wx/wxcode/win/fontprops.cpp.auto.html
Windows的方案:
Function | Description |
---|---|
AddFontMemResourceEx | Adds an embedded font to the system font table. |
AddFontResource | Adds a font resource to the system font table. |
AddFontResourceEx | Adds a private or non-enumerable font to the system font table. |
CreateFont | Creates a logical font. |
CreateFontIndirect | Creates a logical font from a structure. |
CreateFontIndirectEx | Creates a logical font from a structure. |
DrawText | Draws formatted text in a rectangle. |
DrawTextEx | Draws formatted text in rectangle. |
EnumFontFamExProc | An application definedcallback function used with EnumFontFamiliesEx to process fonts. |
EnumFontFamiliesEx | Enumerates all fonts in the system with certain characteristics. |
ExtTextOut | Draws a character string. |
GetAspectRatioFilterEx | Gets the setting for the aspect-ratio filter. |
GetCharABCWidths | Gets the widths of consecutive characters from the TrueType font. |
GetCharABCWidthsFloat | Gets the widths of consecutive characters from the current font. |
GetCharABCWidthsI | Gets the widths of consecutive glyph indices or from an array of glyph indices from the TrueType font. |
GetCharacterPlacement | Gets information about a character string. |
GetCharWidth32 | Gets the widths of consecutive characters from the current font. |
GetCharWidthFloat | Gets the fractional widths of consecutive characters from the current font. |
GetCharWidthI | Gets the widths of consecutive glyph indices or an array of glyph indices from the current font. |
GetFontData | Gets metric data for a TrueType font. |
GetFontLanguageInfo | Returns information about the selected font for a display context. |
GetFontUnicodeRanges | Tells which Unicode characters are supported by a font. |
GetGlyphIndices | Translates a string into an array of glyph indices. |
GetGlyphOutline | Gets the outline or bitmap for a character in the TrueType font. |
GetKerningPairs | Gets the character-kerning pairs for a font. |
GetOutlineTextMetrics | Gets text metrics for TrueType fonts. |
GetRasterizerCaps | Tells whether TrueType fonts are installed. |
GetTabbedTextExtent | Computes the width and height of a character string, including tabs. |
GetTextAlign | Gets the text-alignment setting for a device context. |
GetTextCharacterExtra | Gets the current intercharacter spacing for a device context. |
GetTextColor | Gets the text color for a device context. |
GetTextExtentExPoint | Gets the number of characters in a string that will fit within a space. |
GetTextExtentExPointI | Gets the number of glyph indices that will fit within a space. |
GetTextExtentPoint32 | Computes the width and height of a string of text. |
GetTextExtentPointI | Computes the width and height of an array of glyph indices. |
GetTextFace | Gets the name of the font that is selected into a device context. |
GetTextMetrics | Fills a buffer with the metrics for a font. |
PolyTextOut | Draws several strings using the font and text colors in a device context. |
RemoveFontMemResourceEx | Removes a font whose source was embedded in a document from the system font table. |
RemoveFontResource | Removes the fonts in a file from the system font table. |
RemoveFontResourceEx | Removes a private or non-enumerable font from the system font table. |
SetMapperFlags | Alters the algorithm used to map logical fonts to physical fonts. |
SetTextAlign | Sets the text-alignment flags for a device context. |
SetTextCharacterExtra | Sets the intercharacter spacing. |
SetTextColor | Sets the text color for a device context. |
SetTextJustification | Specifies the amount of space the system should add to the break characters in a string. |
TabbedTextOut | Writes a character string at a location, expanding tabs to specified values. |
TextOut | Writes a character string at a location. |
void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height,
wxCoord *descent, wxCoord *externalLeading )
{
HDC dc = GetDC(0);
WXHFONT hFont = font.GetHFONT();
::SelectObject(dc, hFont);
HFONT hfontOld;
if ( font != wxNullFont )
{
wxASSERT_MSG( font.Ok(), _T("invalid font in wxDC::GetTextExtent") );
hfontOld = (HFONT)::SelectObject(dc, hFont);
}
else // don't change the font
{
hfontOld = 0;
}
SIZE sizeRect;
const size_t len = str.length();
if ( !::GetTextExtentPoint32(dc, str, len, &sizeRect) )
{
wxLogLastError(_T("GetTextExtentPoint32()"));
}
#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
// the result computed by GetTextExtentPoint32() may be too small as it
// accounts for under/overhang of the first/last character while we want
// just the bounding rect for this string so adjust the width as needed
// (using API not available in 2002 SDKs of WinCE)
if ( len > 1 )
{
ABC width;
const wxChar chFirst = *str.begin();
if ( ::GetCharABCWidths(dc, chFirst, chFirst, &width) )
{
if ( width.abcA < 0 )
sizeRect.cx -= width.abcA;
if ( len > 1 )
{
const wxChar chLast = *str.rbegin();
::GetCharABCWidths(dc, chLast, chLast, &width);
}
//else: we already have the width of the last character
if ( width.abcC < 0 )
sizeRect.cx -= width.abcC;
}
//else: GetCharABCWidths() failed, not a TrueType font?
}
#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
TEXTMETRIC tm;
::GetTextMetrics(dc, &tm);
if (width)
*width = sizeRect.cx;
if (height)
*height = sizeRect.cy;
if (descent)
*descent = tm.tmDescent;
if (externalLeading)
*externalLeading = tm.tmExternalLeading;
if ( hfontOld )
{
::SelectObject(dc, hfontOld);
}
ReleaseDC(0, dc);
}
https://opensource.apple.com/source/WebCore/WebCore-955.66/platform/wx/wxcode/mac/carbon/fontprops.mm.auto.html
Mac平台使用了wxWidgets方案
void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height,
wxCoord *descent, wxCoord *externalLeading )
{
wxGraphicsContext * const gc = wxGraphicsContext::Create();
gc->SetFont(font, *wxBLACK); // colour doesn't matter but must be specified
struct GCTextExtent
{
wxDouble width, height, descent, externalLeading;
} e;
gc->GetTextExtent(str, &e.width, &e.height, &e.descent, &e.externalLeading);
if ( width )
*width = wxCoord(e.width + .5);
if ( height )
*height = wxCoord(e.height + .5);
if ( descent )
*descent = wxCoord(e.descent + .5);
if ( externalLeading )
*externalLeading = wxCoord(e.externalLeading + .5);
delete gc;
}
void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
wxDouble *descent, wxDouble *externalLeading ) const
{
wxCHECK_RET( !m_font.IsNull(), wxT("wxMacCoreGraphicsContext::GetTextExtent - no valid font set") );
if ( width )
*width = 0;
if ( height )
*height = 0;
if ( descent )
*descent = 0;
if ( externalLeading )
*externalLeading = 0;
// In wxWidgets (MSW-inspired) API it is possible to call GetTextExtent()
// with an empty string to get just the descent and the leading of the
// font, so support this (mis)use.
wxString strToMeasure(str);
if (str.empty())
strToMeasure = wxS(" ");
wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
wxCFStringRef text(strToMeasure, wxLocale::GetSystemEncoding() );
wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, fref->OSXGetCTFontAttributes() ) );
wxCFRef line( CTLineCreateWithAttributedString(attrtext) );
CGFloat a, d, l, w;
w = CTLineGetTypographicBounds(line, &a, &d, &l);
if ( !str.empty() )
{
if ( width )
*width = w;
if ( height )
*height = a+d+l;
}
if ( descent )
*descent = d;
if ( externalLeading )
*externalLeading = l;
CheckInvariants();
}
void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
{
widths.clear();
wxCHECK_RET( !m_font.IsNull(), wxT("wxMacCoreGraphicsContext::DrawText - no valid font set") );
if (text.empty())
return;
wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
wxCFStringRef t(text, wxLocale::GetSystemEncoding() );
wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, t, fref->OSXGetCTFontAttributes()) );
wxCFRef line( CTLineCreateWithAttributedString(attrtext) );
widths.reserve(text.length());
CFIndex u16index = 1;
for ( wxString::const_iterator iter = text.begin(); iter != text.end(); ++iter, ++u16index )
{
// Take care of surrogate pairs: they take two, not one, of UTF-16 code
// units used by CoreText.
if ( *iter >= 0x10000 )
{
++u16index;
}
widths.push_back( CTLineGetOffsetForStringIndex( line, u16index, NULL ) );
}
CheckInvariants();
}
因为wxWidgets也是跨平台的:
https://opensource.apple.com/source/WebCore/WebCore-955.66/platform/wx/wxcode/gtk/fontprops.cpp.auto.html
Linux平台使用了Pango:
void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading ) { if ( width ) *width = 0; if ( height ) *height = 0; if ( descent ) *descent = 0; if ( externalLeading ) *externalLeading = 0; if (str.empty()) return; // FIXME: Doesn't support height, descent or external leading, though we don't need this for WebKit // it will need to be implemented before merging into wx unless we craft a new API. #if USE(WXGC) PangoFont* pangoFont = WebCore::createPangoFontForFont(&font); PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(WebCore::pangoFontMap())); PangoGlyph pangoGlyph = WebCore::pango_font_get_glyph(pangoFont, pangoContext, (gunichar)g_utf8_get_char(str.ToUTF8())); cairo_glyph_t cglyph = { pangoGlyph, 0, 0 }; cairo_text_extents_t extents; cairo_scaled_font_t* scaled_font = WebCore::createScaledFontForFont(&font); cairo_scaled_font_glyph_extents(scaled_font, &cglyph, 1, &extents); if (cairo_scaled_font_status(scaled_font) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0) *width = (wxCoord)extents.x_advance; cairo_scaled_font_destroy(scaled_font); g_object_unref(pangoContext); g_object_unref(pangoFont); #else PangoContext* context = gdk_pango_context_get_for_screen( gdk_screen_get_default() ); PangoLayout* m_layout = pango_layout_new(context); // and use it if it's valid if ( font && font->IsOk() ) { pango_layout_set_font_description ( m_layout, font->GetNativeFontInfo()->description ); } // Set layout's text const wxCharBuffer dataUTF8 = wxConvUTF8.cWX2MB(str); if ( !dataUTF8 ) { // hardly ideal, but what else can we do if conversion failed? return; } pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) ); int h = 0; pango_layout_get_pixel_size( m_layout, width, &h ); if (descent) { PangoLayoutIter *iter = pango_layout_get_iter(m_layout); int baseline = pango_layout_iter_get_baseline(iter); pango_layout_iter_free(iter); *descent = h - PANGO_PIXELS(baseline); } if (height) *height = (wxCoord) h; #endif }