fontutil.cpp

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

CPP
1,420
字号
// ----------------------------------------------------------------------------
// wxNativeFontInfo
// ----------------------------------------------------------------------------

void wxNativeFontInfo::Init()
{
    m_isDefault = TRUE;
}

bool wxNativeFontInfo::FromString(const wxString& s)
{
    wxStringTokenizer tokenizer(s, _T(";"));

    // check the version
    wxString token = tokenizer.GetNextToken();
    if ( token != _T('0') )
        return FALSE;

    xFontName = tokenizer.GetNextToken();

    // this should be the end
    if ( tokenizer.HasMoreTokens() )
        return FALSE;

    return FromXFontName(xFontName);
}

wxString wxNativeFontInfo::ToString() const
{
    // 0 is the version
    return wxString::Format(_T("%d;%s"), 0, GetXFontName().c_str());
}

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

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

bool wxNativeFontInfo::HasElements() const
{
    // we suppose that the foundry is never empty, so if it is it means that we
    // had never parsed the XLFD
    return !fontElements[0].empty();
}

wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
{
    wxCHECK_MSG( field < wxXLFD_MAX, _T(""), _T("invalid XLFD field") );

    if ( !HasElements() )
    {
        // const_cast
        if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
            return _T("");
    }

    return fontElements[field];
}

bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
{
    // TODO: we should be able to handle the font aliases here, but how?
    wxStringTokenizer tokenizer(fontname, _T("-"));

    // skip the leading, usually empty field (font name registry)
    if ( !tokenizer.HasMoreTokens() )
        return FALSE;

    (void)tokenizer.GetNextToken();

    for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
    {
        if ( !tokenizer.HasMoreTokens() )
        {
            // not enough elements in the XLFD - or maybe an alias
            return FALSE;
        }

        wxString field = tokenizer.GetNextToken();
        if ( !field.empty() && field != _T('*') )
        {
            // we're really initialized now
            m_isDefault = FALSE;
        }

        fontElements[n] = field;
    }

    // this should be all
    if ( tokenizer.HasMoreTokens() )
        return FALSE;

    return TRUE;
}

wxString wxNativeFontInfo::GetXFontName() const
{
    if ( xFontName.empty() )
    {
        for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
        {
            // replace the non specified elements with '*' except for the
            // additional style which is usually just omitted
            wxString elt = fontElements[n];
            if ( elt.empty() && n != wxXLFD_ADDSTYLE )
            {
                elt = _T('*');
            }

            // const_cast
            ((wxNativeFontInfo *)this)->xFontName << _T('-') << elt;
        }
    }

    return xFontName;
}

void
wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
{
    wxCHECK_RET( field < wxXLFD_MAX, _T("invalid XLFD field") );

    // this class should be initialized with a valid font spec first and only
    // then the fields may be modified!
    wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") );

    if ( !HasElements() )
    {
        // const_cast
        if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
        {
            wxFAIL_MSG( _T("can't set font element for invalid XLFD") );

            return;
        }
    }

    fontElements[field] = value;

    // invalidate the XFLD, it doesn't correspond to the font elements any more
    xFontName.clear();
}

void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
{
    // invalidate the font elements, GetXFontComponent() will reparse the XLFD
    fontElements[0].clear();

    xFontName = xFontName_;

    m_isDefault = FALSE;
}

int wxNativeFontInfo::GetPointSize() const
{
    const wxString s = GetXFontComponent(wxXLFD_POINTSIZE);

    // return -1 to indicate that the size is unknown
    long l;
    return s.ToLong(&l) ? l : -1;
}

wxFontStyle wxNativeFontInfo::GetStyle() const
{
    const wxString s = GetXFontComponent(wxXLFD_SLANT);

    if ( s.length() != 1 )
    {
        // it is really unknown but we don't have any way to return it from
        // here
        return wxFONTSTYLE_NORMAL;
    }

    switch ( s[0] )
    {
        default:
            // again, unknown but consider normal by default

        case _T('r'):
            return wxFONTSTYLE_NORMAL;

        case _T('i'):
            return wxFONTSTYLE_ITALIC;

        case _T('o'):
            return wxFONTSTYLE_SLANT;
    }
}

wxFontWeight wxNativeFontInfo::GetWeight() const
{
    const wxString s = GetXFontComponent(wxXLFD_WEIGHT).MakeLower();
    if ( s.find(_T("bold")) != wxString::npos || s == _T("black") )
        return wxFONTWEIGHT_BOLD;
    else if ( s == _T("light") )
        return wxFONTWEIGHT_LIGHT;

    return wxFONTWEIGHT_NORMAL;
}

bool wxNativeFontInfo::GetUnderlined() const
{
    // X fonts are never underlined
    return FALSE;
}

wxString wxNativeFontInfo::GetFaceName() const
{
    // wxWidgets facename probably more accurately corresponds to X family
    return GetXFontComponent(wxXLFD_FAMILY);
}

wxFontFamily wxNativeFontInfo::GetFamily() const
{
    // and wxWidgets family -- to X foundry, but we have to translate it to
    // wxFontFamily somehow...
    wxFAIL_MSG(_T("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY);

    return wxFONTFAMILY_DEFAULT;
}

wxFontEncoding wxNativeFontInfo::GetEncoding() const
{
    // we already have the code for this but need to refactor it first
    wxFAIL_MSG( _T("not implemented") );

    return wxFONTENCODING_MAX;
}

void wxNativeFontInfo::SetPointSize(int pointsize)
{
    SetXFontComponent(wxXLFD_POINTSIZE, wxString::Format(_T("%d"), pointsize));
}

void wxNativeFontInfo::SetStyle(wxFontStyle style)
{
    wxString s;
    switch ( style )
    {
        case wxFONTSTYLE_ITALIC:
            s = _T('i');
            break;

        case wxFONTSTYLE_SLANT:
            s = _T('o');
            break;

        case wxFONTSTYLE_NORMAL:
            s = _T('r');

        default:
            wxFAIL_MSG( _T("unknown wxFontStyle in wxNativeFontInfo::SetStyle") );
            return;
    }

    SetXFontComponent(wxXLFD_SLANT, s);
}

void wxNativeFontInfo::SetWeight(wxFontWeight weight)
{
    wxString s;
    switch ( weight )
    {
        case wxFONTWEIGHT_BOLD:
            s = _T("bold");
            break;

        case wxFONTWEIGHT_LIGHT:
            s = _T("light");
            break;

        case wxFONTWEIGHT_NORMAL:
            s = _T("medium");
            break;

        default:
            wxFAIL_MSG( _T("unknown wxFontWeight in wxNativeFontInfo::SetWeight") );
            return;
    }

    SetXFontComponent(wxXLFD_WEIGHT, s);
}

void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined))
{
    // can't do this under X
}

void wxNativeFontInfo::SetFaceName(wxString facename)
{
    SetXFontComponent(wxXLFD_FAMILY, facename);
}

void wxNativeFontInfo::SetFamily(wxFontFamily family)
{
    // wxFontFamily -> X foundry, anyone?
    wxFAIL_MSG( _T("not implemented") );

    // SetXFontComponent(wxXLFD_FOUNDRY, ...);
}

void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
{
    wxNativeEncodingInfo info;
    if ( wxGetNativeFontEncoding(encoding, &info) )
    {
        SetXFontComponent(wxXLFD_ENCODING, info.xencoding);
        SetXFontComponent(wxXLFD_REGISTRY, info.xregistry);
    }
}

// ----------------------------------------------------------------------------
// common functions
// ----------------------------------------------------------------------------

bool wxGetNativeFontEncoding(wxFontEncoding encoding,
                             wxNativeEncodingInfo *info)
{
    wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );

    if ( encoding == wxFONTENCODING_DEFAULT )
    {
        encoding = wxFont::GetDefaultEncoding();
    }

    switch ( encoding )
    {
        case wxFONTENCODING_ISO8859_1:
        case wxFONTENCODING_ISO8859_2:
        case wxFONTENCODING_ISO8859_3:
        case wxFONTENCODING_ISO8859_4:
        case wxFONTENCODING_ISO8859_5:
        case wxFONTENCODING_ISO8859_6:
        case wxFONTENCODING_ISO8859_7:
        case wxFONTENCODING_ISO8859_8:
        case wxFONTENCODING_ISO8859_9:
        case wxFONTENCODING_ISO8859_10:
        case wxFONTENCODING_ISO8859_11:
        case wxFONTENCODING_ISO8859_12:
        case wxFONTENCODING_ISO8859_13:
        case wxFONTENCODING_ISO8859_14:
        case wxFONTENCODING_ISO8859_15:
            {
                int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
                info->xregistry = wxT("iso8859");
                info->xencoding.Printf(wxT("%d"), cp);
            }
            break;

        case wxFONTENCODING_UTF8:
            info->xregistry = wxT("iso10646");
            info->xencoding = wxT("*");
            break;

        case wxFONTENCODING_GB2312:
            info->xregistry = wxT("GB2312");   // or the otherway round?
            info->xencoding = wxT("*");
            break;

        case wxFONTENCODING_KOI8:
        case wxFONTENCODING_KOI8_U:
            info->xregistry = wxT("koi8");

            // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
            info->xencoding = wxT("*");
            break;

        case wxFONTENCODING_CP1250:
        case wxFONTENCODING_CP1251:
        case wxFONTENCODING_CP1252:
        case wxFONTENCODING_CP1253:
        case wxFONTENCODING_CP1254:
        case wxFONTENCODING_CP1255:
        case wxFONTENCODING_CP1256:
        case wxFONTENCODING_CP1257:
            {
                int cp = encoding - wxFONTENCODING_CP1250 + 1250;
                info->xregistry = wxT("microsoft");
                info->xencoding.Printf(wxT("cp%d"), cp);
            }
            break;

        case wxFONTENCODING_EUC_JP:
        case wxFONTENCODING_SHIFT_JIS:
            info->xregistry = "jis*";
            info->xencoding = "*";
            break;

        case wxFONTENCODING_SYSTEM:
            info->xregistry =
            info->xencoding = wxT("*");
            break;

        default:
            // don't know how to translate this encoding into X fontspec
            return FALSE;
    }

    info->encoding = encoding;

    return TRUE;
}

bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
{
    wxString fontspec;
    fontspec.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
                    !info.facename ? _T("*") : info.facename.c_str(),
                    info.xregistry.c_str(),
                    info.xencoding.c_str());

    return wxTestFontSpec(fontspec);
}

// ----------------------------------------------------------------------------
// X-specific functions
// ----------------------------------------------------------------------------

wxNativeFont wxLoadQueryNearestFont(int pointSize,
                                    int family,
                                    int style,
                                    int weight,
                                    bool underlined,
                                    const wxString &facename,
                                    wxFontEncoding encoding,
                                    wxString* xFontName)
{
    if ( encoding == wxFONTENCODING_DEFAULT )
    {
        encoding = wxFont::GetDefaultEncoding();
    }

    // first determine the encoding - if the font doesn't exist at all in this
    // encoding, it's useless to do all other approximations (i.e. size,
    // family &c don't matter much)
    wxNativeEncodingInfo info;
    if ( encoding == wxFONTENCODING_SYSTEM )
    {
        // This will always work so we don't test to save time
        wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
    }
    else
    {
        if ( !wxGetNativeFontEncoding(encoding, &info) ||
             !wxTestFontEncoding(info) )
        {
#if wxUSE_FONTMAP
            if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
#endif // wxUSE_FONTMAP
            {
                // unspported encoding - replace it with the default
                //
                // NB: we can't just return 0 from here because wxGTK code doesn't
                //     check for it (i.e. it supposes that we'll always succeed),
                //     so it would provoke a crash
                wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
            }
        }
    }

    // OK, we have the correct xregistry/xencoding in info structure
    wxNativeFont font = 0;

    // if we already have the X font name, try to use it
    if( xFontName && !xFontName->IsEmpty() )
    {
        //
        //  Make sure point size is correct for scale factor.
        //

⌨️ 快捷键说明

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