fontutil.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,420 行 · 第 1/3 页

CPP
1,420
字号
/////////////////////////////////////////////////////////////////////////////
// Name:        unix/fontutil.cpp
// Purpose:     Font helper functions for X11 (GDK/X)
// Author:      Vadim Zeitlin
// Modified by:
// Created:     05.11.99
// RCS-ID:      $Id: fontutil.cpp,v 1.62.2.1 2006/02/13 00:24:55 VZ Exp $
// Copyright:   (c) Vadim Zeitlin
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// ============================================================================
// declarations
// ============================================================================

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
    #pragma implementation "fontutil.h"
#endif

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/font.h" // wxFont enums
    #include "wx/encinfo.h"
#endif // PCH

#include "wx/fontutil.h"
#include "wx/fontmap.h"
#include "wx/tokenzr.h"
#include "wx/hash.h"
#include "wx/module.h"

#if wxUSE_PANGO

#include "pango/pango.h"

#ifdef __WXGTK20__
#include "wx/gtk/private.h"
extern GtkWidget *wxGetRootWindow();
#else
#include "wx/x11/private.h"
#endif

// ----------------------------------------------------------------------------
// wxNativeFontInfo
// ----------------------------------------------------------------------------

void wxNativeFontInfo::Init()
{
    description = NULL;
}

void
wxNativeFontInfo::Init(const wxNativeFontInfo& info)
{
    if (info.description)
        description = pango_font_description_copy(info.description);
    else
        description = NULL;
}

void wxNativeFontInfo::Free()
{
    if (description)
        pango_font_description_free(description);
}

int wxNativeFontInfo::GetPointSize() const
{
    return pango_font_description_get_size( description ) / PANGO_SCALE;
}

wxFontStyle wxNativeFontInfo::GetStyle() const
{
    wxFontStyle m_style = wxFONTSTYLE_NORMAL;

    switch (pango_font_description_get_style( description ))
    {
        case PANGO_STYLE_NORMAL:
            m_style = wxFONTSTYLE_NORMAL;
            break;
        case PANGO_STYLE_ITALIC:
            m_style = wxFONTSTYLE_ITALIC;
            break;
        case PANGO_STYLE_OBLIQUE:
            m_style = wxFONTSTYLE_SLANT;
            break;
    }

    return m_style;
}

wxFontWeight wxNativeFontInfo::GetWeight() const
{
#if 0
    // We seem to currently initialize only by string.
    // In that case PANGO_FONT_MASK_WEIGHT is always set.
    if (!(pango_font_description_get_set_fields(description) & PANGO_FONT_MASK_WEIGHT))
        return wxFONTWEIGHT_NORMAL;
#endif

    PangoWeight pango_weight = pango_font_description_get_weight( description );

    // Until the API can be changed the following ranges of weight values are used:
    // wxFONTWEIGHT_LIGHT:  100 .. 349 - range of 250
    // wxFONTWEIGHT_NORMAL: 350 .. 599 - range of 250
    // wxFONTWEIGHT_BOLD:   600 .. 900 - range of 301 (600 is "semibold" already)

    if (pango_weight >= 600)
        return wxFONTWEIGHT_BOLD;

    if (pango_weight < 350)
        return wxFONTWEIGHT_LIGHT;

    return wxFONTWEIGHT_NORMAL;
}

bool wxNativeFontInfo::GetUnderlined() const
{
    return FALSE;
}

wxString wxNativeFontInfo::GetFaceName() const
{
    wxString tmp = wxGTK_CONV_BACK( pango_font_description_get_family( description ) );

    return tmp;
}

wxFontFamily wxNativeFontInfo::GetFamily() const
{
    wxFontFamily ret = wxFONTFAMILY_DEFAULT;
    // note: not passing -1 as the 2nd parameter to g_ascii_strdown to work
    // around a bug in the 64-bit glib shipped with solaris 10, -1 causes it
    // to try to allocate 2^32 bytes.
    const char *family_name = pango_font_description_get_family( description );
    char *family_text = g_ascii_strdown( family_name, family_name ? strlen( family_name ) : 0 );
    // Check for some common fonts, to salvage what we can from the current win32 centric wxFont API:
    if (strncmp( family_text, "monospace", 9 ) == 0)
        ret = wxFONTFAMILY_TELETYPE; // begins with "Monospace"
    else if (strncmp( family_text, "courier", 7 ) == 0)
        ret = wxFONTFAMILY_TELETYPE; // begins with "Courier"
#if defined(__WXGTK24__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
    else
#ifdef __WXGTK24__
    if (!gtk_check_version(2,4,0))
#endif
    {
        PangoFontFamily **families;
        PangoFontFamily  *family = NULL;
        int n_families;
        pango_context_list_families(
#ifdef __WXGTK20__
                gtk_widget_get_pango_context( wxGetRootWindow() ),
#else
                wxTheApp->GetPangoContext(),
#endif
                &families, &n_families);

        for (int i = 0;i < n_families;++i)
        {
            if (g_ascii_strcasecmp(pango_font_family_get_name( families[i] ), pango_font_description_get_family( description )) == 0 )
            {
                family = families[i];
                break;
            }
        }

        g_free(families);

        // Some gtk+ systems might query for a non-existing font from wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)
        // on initialization, don't assert until wxSystemSettings::GetFont is checked for this - MR
        // wxASSERT_MSG( family, wxT("wxNativeFontInfo::GetFamily() - No appropriate PangoFontFamily found for ::description") );

        //BCI: Cache the wxFontFamily inside the class. Validate cache with
        //BCI: g_ascii_strcasecmp(pango_font_description_get_family(description), pango_font_family_get_name(family)) == 0

        if (family != NULL && pango_font_family_is_monospace( family ))
            ret = wxFONTFAMILY_TELETYPE; // is deemed a monospace font by pango
    }
#endif // gtk24 || HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE

    if (ret == wxFONTFAMILY_DEFAULT)
    {
        if (strstr( family_text, "sans" ) != NULL) // checked before serif, so that "* Sans Serif" fonts are detected correctly
            ret = wxFONTFAMILY_SWISS; // contains "Sans"
        else if (strstr( family_text, "serif" ) != NULL)
            ret = wxFONTFAMILY_ROMAN; // contains "Serif"
        else if (strncmp( family_text, "times", 5 ) == 0)
            ret = wxFONTFAMILY_ROMAN; // begins with "Times"
        else if (strncmp( family_text, "old", 3 ) == 0)
            ret = wxFONTFAMILY_DECORATIVE; // Begins with "Old" - "Old English", "Old Town"
    }

    free(family_text);
    return ret;
}

wxFontEncoding wxNativeFontInfo::GetEncoding() const
{
    return wxFONTENCODING_SYSTEM;
}


void wxNativeFontInfo::SetPointSize(int pointsize)
{
    pango_font_description_set_size( description, pointsize * PANGO_SCALE );
}

void wxNativeFontInfo::SetStyle(wxFontStyle style)
{
    switch (style)
    {
        case wxFONTSTYLE_ITALIC:
            pango_font_description_set_style( description, PANGO_STYLE_ITALIC );
            break;
        case wxFONTSTYLE_SLANT:
            pango_font_description_set_style( description, PANGO_STYLE_OBLIQUE );
            break;
        default:
            wxFAIL_MSG( _T("unknown font style") );
            // fall through
        case wxFONTSTYLE_NORMAL:
            pango_font_description_set_style( description, PANGO_STYLE_NORMAL );
            break;
    }
}

void wxNativeFontInfo::SetWeight(wxFontWeight weight)
{
    switch (weight)
    {
        case wxFONTWEIGHT_BOLD:
            pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
            break;
        case wxFONTWEIGHT_LIGHT:
            pango_font_description_set_weight(description, PANGO_WEIGHT_LIGHT);
            break;
        default:
            wxFAIL_MSG( _T("unknown font weight") );
            // fall through
        case wxFONTWEIGHT_NORMAL:
            pango_font_description_set_weight(description, PANGO_WEIGHT_NORMAL);
    }
}

void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined))
{
    wxFAIL_MSG( _T("not implemented") );
}

void wxNativeFontInfo::SetFaceName(wxString facename)
{
    pango_font_description_set_family( description, wxGTK_CONV(facename) );
}

void wxNativeFontInfo::SetFamily(wxFontFamily WXUNUSED(family))
{
    wxFAIL_MSG( _T("not implemented") );
}

void wxNativeFontInfo::SetEncoding(wxFontEncoding WXUNUSED(encoding))
{
    wxFAIL_MSG( _T("not implemented") );
}



bool wxNativeFontInfo::FromString(const wxString& s)
{
    if (description)
        pango_font_description_free( description );

    description = pango_font_description_from_string( wxGTK_CONV( s ) );

    return TRUE;
}

wxString wxNativeFontInfo::ToString() const
{
    char *str = pango_font_description_to_string( description );
    wxString tmp = wxGTK_CONV_BACK(  str );
    g_free( str );

    return tmp;
}

bool wxNativeFontInfo::FromUserString(const wxString& s)
{
    return FromString( s );
}

wxString wxNativeFontInfo::ToUserString() const
{
    return ToString();
}

// ----------------------------------------------------------------------------
// wxNativeEncodingInfo
// ----------------------------------------------------------------------------

bool wxNativeEncodingInfo::FromString(const wxString& WXUNUSED(s))
{
    return FALSE;
}

wxString wxNativeEncodingInfo::ToString() const
{
    return wxEmptyString;
}

bool wxTestFontEncoding(const wxNativeEncodingInfo& WXUNUSED(info))
{
    return TRUE;
}

bool wxGetNativeFontEncoding(wxFontEncoding encoding,
                             wxNativeEncodingInfo *info)
{
    info->facename.clear();

    switch ( encoding )
    {
        // we *must* return true for default encodings as otherwise wxFontMapper
        // considers that we can't load any font and aborts with wxLogFatalError!
        case wxFONTENCODING_DEFAULT:
        case wxFONTENCODING_SYSTEM:
            info->encoding = wxFONTENCODING_SYSTEM;
            return true;

        case wxFONTENCODING_UTF8:
            info->encoding = wxFONTENCODING_UTF8;
            return true;

        default:
            // everything else must be converted to UTF-8
            return false;
    }
}

#else // GTK+ 1.x

#ifdef __X__
    #ifdef __VMS__
        #pragma message disable nosimpint
    #endif

    #include <X11/Xlib.h>

    #ifdef __VMS__
        #pragma message enable nosimpint
    #endif

    #include "wx/utils.h"       // for wxGetDisplay()
#elif defined(__WXGTK__)
    // we have to declare struct tm to avoid problems with first forward
    // declaring it in C code (glib.h included from gdk.h does it) and then
    // defining it when time.h is included from the headers below - this is
    // known not to work at least with Sun CC 6.01
    #include <time.h>

    #include <gdk/gdk.h>
#endif


// ----------------------------------------------------------------------------
// private data
// ----------------------------------------------------------------------------

static wxHashTable *g_fontHash = (wxHashTable*) NULL;

// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------

// define the functions to create and destroy native fonts for this toolkit
#ifdef __X__
    wxNativeFont wxLoadFont(const wxString& fontSpec)
    {
        return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
    }

    inline void wxFreeFont(wxNativeFont font)
    {
        XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
    }
#elif defined(__WXGTK__)
    wxNativeFont wxLoadFont(const wxString& fontSpec)
    {
        // VZ: we should use gdk_fontset_load() instead of gdk_font_load()
        //     here to be able to display Japanese fonts correctly (at least
        //     this is what people report) but unfortunately doing it results
        //     in tons of warnings when using GTK with "normal" European
        //     languages and so we can't always do it and I don't know enough
        //     to determine when should this be done... (FIXME)
        return gdk_font_load( wxConvertWX2MB(fontSpec) );
    }

    inline void wxFreeFont(wxNativeFont font)
    {
        gdk_font_unref(font);
    }
#else
    #error "Unknown GUI toolkit"
#endif

static bool wxTestFontSpec(const wxString& fontspec);

static wxNativeFont wxLoadQueryFont(int pointSize,
                                    int family,
                                    int style,
                                    int weight,
                                    bool underlined,
                                    const wxString& facename,
                                    const wxString& xregistry,
                                    const wxString& xencoding,
                                    wxString* xFontName);

// ============================================================================
// implementation
// ============================================================================

// ----------------------------------------------------------------------------
// wxNativeEncodingInfo
// ----------------------------------------------------------------------------

// convert to/from the string representation: format is
//      encodingid;registry;encoding[;facename]
bool wxNativeEncodingInfo::FromString(const wxString& s)
{
    // use ";", not "-" because it may be part of encoding name
    wxStringTokenizer tokenizer(s, _T(";"));

    wxString encid = tokenizer.GetNextToken();
    long enc;
    if ( !encid.ToLong(&enc) )
        return FALSE;
    encoding = (wxFontEncoding)enc;

    xregistry = tokenizer.GetNextToken();
    if ( !xregistry )
        return FALSE;

    xencoding = tokenizer.GetNextToken();
    if ( !xencoding )
        return FALSE;

    // ok even if empty
    facename = tokenizer.GetNextToken();

    return TRUE;
}

wxString wxNativeEncodingInfo::ToString() const
{
    wxString s;
    s << (long)encoding << _T(';') << xregistry << _T(';') << xencoding;
    if ( !!facename )
    {
        s << _T(';') << facename;
    }

    return s;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?