獲取文本寫入的像素寬度

https://opensource.apple.com/source/WebCore/WebCore-955.66/platform/wx/wxcode/win/fontprops.cpp.auto.html

Windows的方案:

FunctionDescription
AddFontMemResourceExAdds an embedded font to the system font table.
AddFontResourceAdds a font resource to the system font table.
AddFontResourceExAdds a private or non-enumerable font to the system font table.
CreateFontCreates a logical font.
CreateFontIndirectCreates a logical font from a structure.
CreateFontIndirectExCreates a logical font from a structure.
DrawTextDraws formatted text in a rectangle.
DrawTextExDraws formatted text in rectangle.
EnumFontFamExProcAn application definedcallback function used with EnumFontFamiliesEx to process fonts.
EnumFontFamiliesExEnumerates all fonts in the system with certain characteristics.
ExtTextOutDraws a character string.
GetAspectRatioFilterExGets the setting for the aspect-ratio filter.
GetCharABCWidthsGets the widths of consecutive characters from the TrueType font.
GetCharABCWidthsFloatGets the widths of consecutive characters from the current font.
GetCharABCWidthsIGets the widths of consecutive glyph indices or from an array of glyph indices from the TrueType font.
GetCharacterPlacementGets information about a character string.
GetCharWidth32Gets the widths of consecutive characters from the current font.
GetCharWidthFloatGets the fractional widths of consecutive characters from the current font.
GetCharWidthIGets the widths of consecutive glyph indices or an array of glyph indices from the current font.
GetFontDataGets metric data for a TrueType font.
GetFontLanguageInfoReturns information about the selected font for a display context.
GetFontUnicodeRangesTells which Unicode characters are supported by a font.
GetGlyphIndicesTranslates a string into an array of glyph indices.
GetGlyphOutlineGets the outline or bitmap for a character in the TrueType font.
GetKerningPairsGets the character-kerning pairs for a font.
GetOutlineTextMetricsGets text metrics for TrueType fonts.
GetRasterizerCapsTells whether TrueType fonts are installed.
GetTabbedTextExtentComputes the width and height of a character string, including tabs.
GetTextAlignGets the text-alignment setting for a device context.
GetTextCharacterExtraGets the current intercharacter spacing for a device context.
GetTextColorGets the text color for a device context.
GetTextExtentExPointGets the number of characters in a string that will fit within a space.
GetTextExtentExPointIGets the number of glyph indices that will fit within a space.
GetTextExtentPoint32Computes the width and height of a string of text.
GetTextExtentPointIComputes the width and height of an array of glyph indices.
GetTextFaceGets the name of the font that is selected into a device context.
GetTextMetricsFills a buffer with the metrics for a font.
PolyTextOutDraws several strings using the font and text colors in a device context.
RemoveFontMemResourceExRemoves a font whose source was embedded in a document from the system font table.
RemoveFontResourceRemoves the fonts in a file from the system font table.
RemoveFontResourceExRemoves a private or non-enumerable font from the system font table.
SetMapperFlagsAlters the algorithm used to map logical fonts to physical fonts.
SetTextAlignSets the text-alignment flags for a device context.
SetTextCharacterExtraSets the intercharacter spacing.
SetTextColorSets the text color for a device context.
SetTextJustificationSpecifies the amount of space the system should add to the break characters in a string.
TabbedTextOutWrites a character string at a location, expanding tabs to specified values.
TextOutWrites 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<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, fref->OSXGetCTFontAttributes() ) );
    wxCFRef<CTLineRef> 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<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, t, fref->OSXGetCTFontAttributes()) );
    wxCFRef<CTLineRef> 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
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章