获取文本写入的像素宽度

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
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值