获取文本写入的像素宽度

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.
GetTextExtentPoint32
GetTextExtentPoint
GetTextExtentExPoint
DrawText
DrawTextEx
GetTextExtent
GetTextMetrics
GetCharWidth: 不能用于Truetype或Opentype
LpkUseGDIWidthCache
GetTabbedTextExtent
LpkGetTextExtentExPoint
GetTextExtentExPointWPri
GetCharABCWidths:只能用于Truetype或Opentype
GetCharABCWidthsFloat : 支持所有字体,但是系统必须是win2k以上。
GetOutlineTextMetrics

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
}


你可能感兴趣的:(获取文本写入的像素宽度)