]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/fontutil.cpp
No significant change
[wxWidgets.git] / src / unix / fontutil.cpp
index 27c2de464aa47c5e354f0c47b275c91642e5f6c6..2802d1170b9c04ac470b42f86da095eeebe5f0de 100644 (file)
@@ -6,7 +6,7 @@
 // Created:     05.11.99
 // RCS-ID:      $Id$
 // Copyright:   (c) Vadim Zeitlin
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 #ifndef WX_PRECOMP
 #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"
+#else
+#include "wx/x11/private.h"
+#endif
+
+// ----------------------------------------------------------------------------
+// wxNativeFontInfo
+// ----------------------------------------------------------------------------
+
+void wxNativeFontInfo::Init()
+{
+    description = NULL;
+}
+
+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
+{
+    wxFontWeight m_weight = wxFONTWEIGHT_NORMAL;
+
+    switch (pango_font_description_get_weight( description ))
+    {
+        case PANGO_WEIGHT_ULTRALIGHT:
+            m_weight = wxFONTWEIGHT_LIGHT;
+            break;
+        case PANGO_WEIGHT_LIGHT:
+            m_weight = wxFONTWEIGHT_LIGHT;
+            break;
+        case PANGO_WEIGHT_NORMAL:
+            m_weight = wxFONTWEIGHT_NORMAL;
+            break;
+        case PANGO_WEIGHT_BOLD:
+            m_weight = wxFONTWEIGHT_BOLD;
+            break;
+        case PANGO_WEIGHT_ULTRABOLD:
+            m_weight = wxFONTWEIGHT_BOLD;
+            break;
+        case PANGO_WEIGHT_HEAVY:
+            m_weight = wxFONTWEIGHT_BOLD;
+            break;
+    }
+
+    return m_weight;
+}
+
+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
+{
+    return wxFONTFAMILY_SWISS;
+}
+
+wxFontEncoding wxNativeFontInfo::GetEncoding() const
+{
+    return wxFONTENCODING_SYSTEM;
+}
+
+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& s)
+{
+    return FALSE;
+}
+
+wxString wxNativeEncodingInfo::ToString() const
+{
+    return wxEmptyString;
+}
+
+bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
+{
+    return TRUE;
+}
+
+bool wxGetNativeFontEncoding(wxFontEncoding encoding,
+                             wxNativeEncodingInfo *info)
+{
+    return FALSE;
+}
+
+#else // GTK+ 1.x
+
 #ifdef __X__
     #ifdef __VMS__
         #pragma message disable nosimpint
     #include <gdk/gdk.h>
 #endif
 
-#include "wx/fontutil.h"
-#include "wx/fontmap.h"
-#include "wx/tokenzr.h"
-#include "wx/hash.h"
-#include "wx/module.h"
 
 // ----------------------------------------------------------------------------
 // private data
@@ -71,22 +223,28 @@ static wxHashTable *g_fontHash = (wxHashTable*) NULL;
 
 // define the functions to create and destroy native fonts for this toolkit
 #ifdef __X__
-    static inline wxNativeFont wxLoadFont(const wxString& fontSpec)
+    wxNativeFont wxLoadFont(const wxString& fontSpec)
     {
         return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
     }
 
-    static inline void wxFreeFont(wxNativeFont font)
+    inline void wxFreeFont(wxNativeFont font)
     {
         XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
     }
 #elif defined(__WXGTK__)
-    static inline wxNativeFont wxLoadFont(const wxString& fontSpec)
+    wxNativeFont wxLoadFont(const wxString& fontSpec)
     {
-       return gdk_font_load( wxConvertWX2MB(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) );
     }
 
-    static inline void wxFreeFont(wxNativeFont font)
+    inline void wxFreeFont(wxNativeFont font)
     {
         gdk_font_unref(font);
     }
@@ -159,7 +317,7 @@ wxString wxNativeEncodingInfo::ToString() const
 
 void wxNativeFontInfo::Init()
 {
-    xFontName.clear();
+    m_isDefault = TRUE;
 }
 
 bool wxNativeFontInfo::FromString(const wxString& s)
@@ -196,11 +354,18 @@ 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 ( fontElements[0].empty() )
+    if ( !HasElements() )
     {
         // const_cast
         if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
@@ -213,7 +378,13 @@ wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
 bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
 {
     // TODO: we should be able to handle the font aliases here, but how?
-    wxStringTokenizer tokenizer(fontname, _T("-"), wxTOKEN_STRTOK);
+    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++ )
     {
@@ -223,11 +394,21 @@ bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
             return FALSE;
         }
 
-        fontElements[n] = tokenizer.GetNextToken();
+        wxString field = tokenizer.GetNextToken();
+        if ( !field.empty() && field != _T('*') )
+        {
+            // we're really initialized now
+            m_isDefault = FALSE;
+        }
+
+        fontElements[n] = field;
     }
 
     // this should be all
-    return !tokenizer.HasMoreTokens();
+    if ( tokenizer.HasMoreTokens() )
+        return FALSE;
+
+    return TRUE;
 }
 
 wxString wxNativeFontInfo::GetXFontName() const
@@ -239,7 +420,7 @@ wxString wxNativeFontInfo::GetXFontName() const
             // replace the non specified elements with '*' except for the
             // additional style which is usually just omitted
             wxString elt = fontElements[n];
-            if ( elt.empty() && n != 5 )
+            if ( elt.empty() && n != wxXLFD_ADDSTYLE )
             {
                 elt = _T('*');
             }
@@ -252,6 +433,200 @@ wxString wxNativeFontInfo::GetXFontName() const
     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
+{
+    // wxWindows facename probably more accurately corresponds to X family
+    return GetXFontComponent(wxXLFD_FAMILY);
+}
+
+wxFontFamily wxNativeFontInfo::GetFamily() const
+{
+    // and wxWindows 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
 // ----------------------------------------------------------------------------
@@ -295,6 +670,11 @@ bool wxGetNativeFontEncoding(wxFontEncoding encoding,
             info->xencoding = wxT("*");
             break;
 
+        case wxFONTENCODING_GB2312:
+            info->xregistry = wxT("GB2312");   // or the otherway round? 
+            info->xencoding = wxT("*");
+            break;
+
         case wxFONTENCODING_KOI8:
             info->xregistry = wxT("koi8");
 
@@ -376,7 +756,7 @@ wxNativeFont wxLoadQueryNearestFont(int pointSize,
              !wxTestFontEncoding(info) )
         {
 #if wxUSE_FONTMAP
-            if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
+            if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
 #endif // wxUSE_FONTMAP
             {
                 // unspported encoding - replace it with the default
@@ -406,7 +786,7 @@ wxNativeFont wxLoadQueryNearestFont(int pointSize,
 
         (void) tokenizer.NextToken();
 
-        newFontName += wxString::Format("%d-", pointSize);
+        newFontName += wxString::Format(wxT("%d-"), pointSize);
 
         while(tokenizer.HasMoreTokens())
           newFontName += tokenizer.GetNextToken();
@@ -564,7 +944,77 @@ static wxNativeFont wxLoadQueryFont(int pointSize,
         case wxSCRIPT:     xfamily = wxT("utopia"); break;
         default:           xfamily = wxT("*");
     }
+#if wxUSE_NANOX
+    int xweight;
+    switch (weight)
+    {
+         case wxBOLD:
+             {
+                 xweight = MWLF_WEIGHT_BOLD;
+                 break;
+             }
+        case wxLIGHT:
+             {
+                 xweight = MWLF_WEIGHT_LIGHT;
+                 break;
+             }
+         case wxNORMAL:
+             {
+                 xweight = MWLF_WEIGHT_NORMAL;
+                 break;
+             }
+
+     default:
+             {
+                 xweight = MWLF_WEIGHT_DEFAULT;
+                 break;
+             }
+    }
+    GR_SCREEN_INFO screenInfo;
+    GrGetScreenInfo(& screenInfo);
+
+    int yPixelsPerCM = screenInfo.ydpcm;
+
+    // A point is 1/72 of an inch.
+    // An inch is 2.541 cm.
+    // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
+    // In fact pointSize is 10 * the normal point size so
+    // divide by 10.
+
+    int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM) ;
+
+    // An alternative: assume that the screen is 72 dpi.
+    //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
+    //int pixelHeight = (int) ((float)pointSize / 10.0) ;
+
+    GR_LOGFONT logFont;
+    logFont.lfHeight = pixelHeight;
+    logFont.lfWidth = 0;
+    logFont.lfEscapement = 0;
+    logFont.lfOrientation = 0;
+    logFont.lfWeight = xweight;
+    logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
+    logFont.lfUnderline = 0;
+    logFont.lfStrikeOut = 0;
+    logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
+    logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
+    logFont.lfClipPrecision = 0; // Not used
+    logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
+    logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
+    logFont.lfSansSerif = !logFont.lfSerif ;
+    logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
+    logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
+    logFont.lfOblique = 0;
+    logFont.lfSmallCaps = 0;
+    logFont.lfPitch = 0; // 0 = default
+    strcpy(logFont.lfFaceName, facename.c_str());
+
+    XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
+    fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
+    GrGetFontInfo(fontInfo->fid, & fontInfo->info);
+    return (wxNativeFont) fontInfo;
 
+#else
     wxString fontSpec;
     if (!facename.IsEmpty())
     {
@@ -722,7 +1172,7 @@ static wxNativeFont wxLoadQueryFont(int pointSize,
 
     // if pointSize is -1, don't specify any
     wxString sizeSpec;
-    if ( fontSpec == -1 )
+    if ( pointSize == -1 )
     {
         sizeSpec = _T('*');
     }
@@ -740,6 +1190,8 @@ static wxNativeFont wxLoadQueryFont(int pointSize,
         *xFontName = fontSpec;
 
     return wxLoadFont(fontSpec);
+#endif
+    // wxUSE_NANOX
 }
 
 // ----------------------------------------------------------------------------
@@ -771,3 +1223,6 @@ void wxFontModule::OnExit()
 
     g_fontHash = (wxHashTable *)NULL;
 }
+
+#endif // GTK 2.0/1.x
+