diff --git a/configure.in b/configure.in index ba6ad07009..99af6f1075 100644 --- a/configure.in +++ b/configure.in @@ -2213,6 +2213,15 @@ equivalent variable and GTK+ is version 1.2.3 or above. wxUSE_PRINTING_ARCHITECTURE="no" ] ) + PKG_CHECK_MODULES(PANGOXFT, pangoxft, + [ + CXXFLAGS="$CXXFLAGS $PANGOXFT_CFLAGS" + LIBS="$LIBS $PANGOXFT_LIBS" + ], + [ + AC_MSG_WARN([pangoxft library not found, library will be compiled without anti-aliasing support]) + ] + ) fi wxUSE_UNIVERSAL="yes" diff --git a/include/wx/defs.h b/include/wx/defs.h index a468967973..86ec8bcd1b 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -2084,16 +2084,24 @@ typedef GtkWidget *WXWidget; #endif #ifdef __WXGTK20__ +/* Input method thing */ +typedef struct _GtkIMMulticontext GtkIMMulticontext; +#endif // __WXGTK20__ + +#endif // __WXGTK__ + +#if defined(__WXGTK20__) || (defined(__WXX11__) && wxUSE_UNICODE) +#define wxUSE_PANGO 1 +#else +#define wxUSE_PANGO 0 +#endif + +#if wxUSE_PANGO /* Stand-ins for Pango types */ typedef struct _PangoContext PangoContext; typedef struct _PangoLayout PangoLayout; typedef struct _PangoFontDescription PangoFontDescription; - -/* Input method thing */ -typedef struct _GtkIMMulticontext GtkIMMulticontext; -#endif // GTK+ 2.0 - -#endif // GTK +#endif #ifdef __WXMGL__ typedef struct window_t *WXWidget; diff --git a/include/wx/fontutil.h b/include/wx/fontutil.h index 90ec00dc1c..2adeb7ed40 100644 --- a/include/wx/fontutil.h +++ b/include/wx/fontutil.h @@ -72,7 +72,9 @@ enum wxXLFDField // further it might make sense to make it a real class with virtual methods struct WXDLLEXPORT wxNativeFontInfo { -#if defined(_WX_X_FONTLIKE) +#if wxUSE_PANGO + PangoFontDescription *description; +#elif defined(_WX_X_FONTLIKE) // the members can't be accessed directly as we only parse the // xFontName on demand private: @@ -113,8 +115,6 @@ public: FATTRS fa; FONTMETRICS fm; FACENAMEDESC fn; -#elif defined(__WXGTK20__) - PangoFontDescription *description; #else // other platforms // // This is a generic implementation that should work on all ports diff --git a/include/wx/x11/app.h b/include/wx/x11/app.h index c1e44dad6e..3621558b9f 100644 --- a/include/wx/x11/app.h +++ b/include/wx/x11/app.h @@ -101,6 +101,13 @@ public: const wxSize& GetInitialSize() const { return m_initialSize; } bool GetShowIconic() const { return m_showIconic; } +#if wxUSE_UNICODE + // Global context for Pango layout. Either use X11 + // or use Xft rendering according to GDK_USE_XFT + // environment variable + PangoContext* GetPangoContext(); +#endif + // We need this before creating the app static WXDisplay* GetDisplay() { return ms_display; } static WXDisplay* ms_display; diff --git a/include/wx/x11/dcclient.h b/include/wx/x11/dcclient.h index ce76814dca..f2a16a37fe 100644 --- a/include/wx/x11/dcclient.h +++ b/include/wx/x11/dcclient.h @@ -133,6 +133,11 @@ protected: wxRegion m_currentClippingRegion; wxRegion m_paintClippingRegion; +#if wxUSE_UNICODE + PangoContext *m_context; + PangoFontDescription *m_fontdesc; +#endif + void SetUpDC(); void Destroy(); void ComputeScaleAndOrigin(); diff --git a/include/wx/x11/font.h b/include/wx/x11/font.h index faf0d35801..0ddfb252b2 100644 --- a/include/wx/x11/font.h +++ b/include/wx/x11/font.h @@ -48,10 +48,11 @@ public: bool underlined = FALSE, const wxString& face = wxEmptyString, wxFontEncoding encoding = wxFONTENCODING_DEFAULT); - - // wxMOTIF-specific + +#if wxUSE_UNICODE bool Create(const wxString& fontname, wxFontEncoding fontenc = wxFONTENCODING_DEFAULT); +#endif bool Create(const wxNativeFontInfo& fontinfo); virtual ~wxFont(); @@ -69,6 +70,8 @@ public: virtual wxFontEncoding GetEncoding() const; virtual wxNativeFontInfo *GetNativeFontInfo() const; + virtual bool IsFixedWidth() const; + virtual void SetPointSize(int pointSize); virtual void SetFamily(int family); virtual void SetStyle(int style); @@ -78,8 +81,13 @@ public: virtual void SetEncoding(wxFontEncoding encoding); virtual void SetNativeFontInfo( const wxNativeFontInfo& info ); - // Implementation + virtual void SetNoAntiAliasing( bool no = TRUE ); + virtual bool GetNoAntiAliasing(); + // Implementation + +#if wxUSE_PANGO +#else // Find an existing, or create a new, XFontStruct // based on this wxFont and the given scale. Append the // font to list in the private data for future reference. @@ -98,13 +106,12 @@ public: // Helper function for convenient access of the above. WXFontStructPtr GetFontStruct(double scale = 1.0, WXDisplay* display = NULL) const; +#endif protected: // common part of all ctors void Init(); - // VZ: IMHO, we don't need it at all... - bool RealizeResource() { return TRUE; } void Unshare(); private: diff --git a/include/wx/x11/private.h b/include/wx/x11/private.h index bb6d9be7f6..303f28a8ee 100644 --- a/include/wx/x11/private.h +++ b/include/wx/x11/private.h @@ -21,10 +21,26 @@ // Include common declarations #include "wx/x11/privx.h" +#if wxUSE_UNICODE +#include "pango/pango.h" +#endif + class wxMouseEvent; class wxKeyEvent; class wxWindow; +// ---------------------------------------------------------------------------- +// Some Unicode <-> UTF8 macros stolen from GTK +// ---------------------------------------------------------------------------- + +#if wxUSE_UNICODE + #define wxGTK_CONV(s) wxConvUTF8.cWX2MB(s) + #define wxGTK_CONV_BACK(s) wxConvUTF8.cMB2WX(s) +#else + #define wxGTK_CONV(s) s.c_str() + #define wxGTK_CONV_BACK(s) s +#endif + // ---------------------------------------------------------------------------- // we maintain a hash table which contains the mapping from Widget to wxWindow // corresponding to the window for this widget diff --git a/include/wx/x11/privx.h b/include/wx/x11/privx.h index c8c63f63b8..7a3473593a 100644 --- a/include/wx/x11/privx.h +++ b/include/wx/x11/privx.h @@ -14,6 +14,8 @@ #include "wx/defs.h" #include "wx/utils.h" +#include "wx/colour.h" + #include "X11/Xlib.h" #include "X11/Xatom.h" #include "X11/Xutil.h" diff --git a/samples/internat/internat.cpp b/samples/internat/internat.cpp index d94d9eb457..3245e301e7 100644 --- a/samples/internat/internat.cpp +++ b/samples/internat/internat.cpp @@ -171,10 +171,16 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) ) void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxString localeInfo; +#if 0 localeInfo.Printf( _("Language: %s\nSystem locale name: %s\nCanonical locale name: %s\n"), m_locale.GetLocale(), m_locale.GetSysName().c_str(), m_locale.GetCanonicalName().c_str() ); +#endif + + localeInfo.Printf( _("Language: %s\nCanonical locale name: %s\n"), + m_locale.GetLocale(), + m_locale.GetCanonicalName().c_str() ); wxMessageDialog(this, wxString(_("I18n sample\n(c) 1998, 1999 Vadim Zeitlin and Julian Smart")) + wxT("\n\n") + localeInfo, diff --git a/src/generic/timer.cpp b/src/generic/timer.cpp index c46854c9e9..259a0ebe0e 100644 --- a/src/generic/timer.cpp +++ b/src/generic/timer.cpp @@ -90,7 +90,7 @@ void wxTimerScheduler::QueueTimer(wxTimerDesc *desc, unsigned long when) desc->shotTime = when; desc->running = TRUE; - wxLogTrace("timer", "queued timer %p at tick %ld", + wxLogTrace( wxT("timer"), wxT("queued timer %p at tick %ld"), desc->timer, (long) when); if ( m_timers ) @@ -143,7 +143,7 @@ void wxTimerScheduler::NotifyTimers() if ( !timerDeleted ) { - wxLogTrace("timer", "notified timer %p sheduled for %ld", + wxLogTrace( wxT("timer"), wxT("notified timer %p sheduled for %ld"), desc->timer, (long) desc->shotTime); desc->deleteFlag = NULL; @@ -172,7 +172,7 @@ void wxTimer::Init() wxTimer::~wxTimer() { - wxLogTrace("timer", "destroying timer %p...", this); + wxLogTrace( wxT("timer"), wxT("destroying timer %p..."), this); if ( IsRunning() ) Stop(); @@ -184,7 +184,7 @@ wxTimer::~wxTimer() *m_desc->deleteFlag = TRUE; delete m_desc; - wxLogTrace("timer", " ...done destroying timer %p...", this); + wxLogTrace( wxT("timer"), wxT(" ...done destroying timer %p..."), this); } bool wxTimer::IsRunning() const @@ -194,7 +194,7 @@ bool wxTimer::IsRunning() const bool wxTimer::Start(int millisecs, bool oneShot) { - wxLogTrace("timer", "started timer %p: %i ms, oneshot=%i", + wxLogTrace( wxT("timer"), wxT("started timer %p: %i ms, oneshot=%i"), this, millisecs, oneShot); if ( !wxTimerBase::Start(millisecs, oneShot) ) diff --git a/src/gtk/font.cpp b/src/gtk/font.cpp index c13b08a612..bd093a795d 100644 --- a/src/gtk/font.cpp +++ b/src/gtk/font.cpp @@ -133,12 +133,10 @@ protected: void InitFromNative(); private: -#ifdef __WXGTK20__ - void ClearGdkFonts() { } -#else // GTK 1.x - // clear m_scaled_xfonts + // clear m_scaled_xfonts if any void ClearGdkFonts(); +#ifndef __WXGTK20__ // the map of font sizes to "GdkFont *" wxScaledFontList m_scaled_xfonts; #endif // GTK 2.0/1.x @@ -159,12 +157,8 @@ private: friend class wxFont; }; -// ============================================================================ -// wxFontRefData implementation -// ============================================================================ - // ---------------------------------------------------------------------------- -// wxFontRefData creation +// wxFontRefData // ---------------------------------------------------------------------------- void wxFontRefData::Init(int pointSize, @@ -423,9 +417,9 @@ wxFontRefData::wxFontRefData(const wxString& fontname) InitFromNative(); } -#ifndef __WXGTK20__ void wxFontRefData::ClearGdkFonts() { +#ifndef __WXGTK20__ for ( wxScaledFontList::iterator i = m_scaled_xfonts.begin(); i != m_scaled_xfonts.end(); ++i ) @@ -435,8 +429,8 @@ void wxFontRefData::ClearGdkFonts() } m_scaled_xfonts.clear(); -} #endif // GTK 1.x +} wxFontRefData::~wxFontRefData() { @@ -606,10 +600,6 @@ void wxFontRefData::SetNativeFontInfo(const wxNativeFontInfo& info) InitFromNative(); } -// ============================================================================ -// wxFont implementation -// ============================================================================ - // ---------------------------------------------------------------------------- // wxFont creation // ---------------------------------------------------------------------------- @@ -633,7 +623,7 @@ wxFont::wxFont(const wxNativeFontInfo& info) info.GetFaceName(), info.GetEncoding() ); #else - Create(info.GetXFontName()); + (void) Create(info.GetXFontName()); #endif } @@ -645,6 +635,8 @@ bool wxFont::Create( int pointSize, const wxString& face, wxFontEncoding encoding) { + UnRef(); + m_refData = new wxFontRefData(pointSize, family, style, weight, underlined, face, encoding); @@ -688,9 +680,6 @@ wxFont::~wxFont() // accessors // ---------------------------------------------------------------------------- -// all accessors are just forwarded to wxFontRefData which has everything we -// need - int wxFont::GetPointSize() const { wxCHECK_MSG( Ok(), 0, wxT("invalid font") ); diff --git a/src/gtk1/font.cpp b/src/gtk1/font.cpp index c13b08a612..bd093a795d 100644 --- a/src/gtk1/font.cpp +++ b/src/gtk1/font.cpp @@ -133,12 +133,10 @@ protected: void InitFromNative(); private: -#ifdef __WXGTK20__ - void ClearGdkFonts() { } -#else // GTK 1.x - // clear m_scaled_xfonts + // clear m_scaled_xfonts if any void ClearGdkFonts(); +#ifndef __WXGTK20__ // the map of font sizes to "GdkFont *" wxScaledFontList m_scaled_xfonts; #endif // GTK 2.0/1.x @@ -159,12 +157,8 @@ private: friend class wxFont; }; -// ============================================================================ -// wxFontRefData implementation -// ============================================================================ - // ---------------------------------------------------------------------------- -// wxFontRefData creation +// wxFontRefData // ---------------------------------------------------------------------------- void wxFontRefData::Init(int pointSize, @@ -423,9 +417,9 @@ wxFontRefData::wxFontRefData(const wxString& fontname) InitFromNative(); } -#ifndef __WXGTK20__ void wxFontRefData::ClearGdkFonts() { +#ifndef __WXGTK20__ for ( wxScaledFontList::iterator i = m_scaled_xfonts.begin(); i != m_scaled_xfonts.end(); ++i ) @@ -435,8 +429,8 @@ void wxFontRefData::ClearGdkFonts() } m_scaled_xfonts.clear(); -} #endif // GTK 1.x +} wxFontRefData::~wxFontRefData() { @@ -606,10 +600,6 @@ void wxFontRefData::SetNativeFontInfo(const wxNativeFontInfo& info) InitFromNative(); } -// ============================================================================ -// wxFont implementation -// ============================================================================ - // ---------------------------------------------------------------------------- // wxFont creation // ---------------------------------------------------------------------------- @@ -633,7 +623,7 @@ wxFont::wxFont(const wxNativeFontInfo& info) info.GetFaceName(), info.GetEncoding() ); #else - Create(info.GetXFontName()); + (void) Create(info.GetXFontName()); #endif } @@ -645,6 +635,8 @@ bool wxFont::Create( int pointSize, const wxString& face, wxFontEncoding encoding) { + UnRef(); + m_refData = new wxFontRefData(pointSize, family, style, weight, underlined, face, encoding); @@ -688,9 +680,6 @@ wxFont::~wxFont() // accessors // ---------------------------------------------------------------------------- -// all accessors are just forwarded to wxFontRefData which has everything we -// need - int wxFont::GetPointSize() const { wxCHECK_MSG( Ok(), 0, wxT("invalid font") ); diff --git a/src/unix/fontenum.cpp b/src/unix/fontenum.cpp index 5ce2b4e93d..9c9dc5bc7c 100644 --- a/src/unix/fontenum.cpp +++ b/src/unix/fontenum.cpp @@ -26,20 +26,22 @@ #include "wx/string.h" #include "wx/regex.h" #include "wx/utils.h" - +#include "wx/app.h" #include "wx/fontmap.h" #include "wx/fontenum.h" #include "wx/fontutil.h" // ---------------------------------------------------------------------------- -// GTK 2.0 +// Pango // ---------------------------------------------------------------------------- +#if wxUSE_PANGO + +#include "pango/pango.h" + #ifdef __WXGTK20__ - -#include "wx/gtk/private.h" - extern GtkWidget *wxGetRootWindow(); +#endif static int cmp_families (const void *a, const void *b) @@ -63,7 +65,11 @@ bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding, PangoFontFamily **families = NULL; gint n_families = 0; pango_context_list_families ( +#ifdef __WXGTK20__ gtk_widget_get_pango_context( wxGetRootWindow() ), +#else + wxTheApp->GetPangoContext(), +#endif &families, &n_families ); qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families); @@ -86,7 +92,7 @@ bool wxFontEnumerator::EnumerateEncodings(const wxString& family) #else - // GTK 2.0 + // Pango #ifdef __VMS__ // Xlib.h for VMS is not (yet) compatible with C++ // The resulting warnings are switched off here diff --git a/src/unix/fontutil.cpp b/src/unix/fontutil.cpp index 6ccc808a87..5cb5e28a95 100644 --- a/src/unix/fontutil.cpp +++ b/src/unix/fontutil.cpp @@ -37,9 +37,15 @@ #include "wx/hash.h" #include "wx/module.h" -#ifdef __WXGTK20__ +#if wxUSE_PANGO +#include "pango/pango.h" + +#ifdef __WXGTK20__ #include "wx/gtk/private.h" +#else +#include "wx/x11/private.h" +#endif // ---------------------------------------------------------------------------- // wxNativeFontInfo diff --git a/src/x11/app.cpp b/src/x11/app.cpp index 09aa2ff2f2..12502ea7a7 100644 --- a/src/x11/app.cpp +++ b/src/x11/app.cpp @@ -238,7 +238,6 @@ int wxEntryStart( int& argc, char *argv[] ) } - // X11 display stuff Display* xdisplay = XOpenDisplay( displayName ); if (!xdisplay) @@ -254,32 +253,14 @@ int wxEntryStart( int& argc, char *argv[] ) XSelectInput( xdisplay, XDefaultRootWindow(xdisplay), PropertyChangeMask); - - // Command line argument stuff - wxTheApp->argc = argc; -#if wxUSE_UNICODE - wxTheApp->argv = new wxChar*[argc+1]; - int mb_argc = 0; - while (mb_argc < argc) - { - wxString tmp = wxString::FromAscii( argv[mb_argc] ); - wxTheApp->argv[mb_argc] = wxStrdup( tmp.c_str() ); - mb_argc++; - } - wxTheApp->argv[mb_argc] = (wxChar *)NULL; -#else - wxTheApp->argv = argv; -#endif - - if (wxTheApp->argc > 0) - { - wxFileName fname( wxTheApp->argv[0] ); - wxTheApp->SetAppName( fname.GetName() ); - } - // Misc. wxSetDetectableAutoRepeat( TRUE ); +#if wxUSE_UNICODE + // Glib's type system required by Pango + g_type_init(); +#endif + if (!wxApp::Initialize()) return -1; @@ -329,6 +310,28 @@ int wxEntry( int argc, char *argv[] ) return 0; } + // Command line argument stuff + wxTheApp->argc = argc; +#if wxUSE_UNICODE + wxTheApp->argv = new wxChar*[argc+1]; + int mb_argc = 0; + while (mb_argc < argc) + { + wxString tmp = wxString::FromAscii( argv[mb_argc] ); + wxTheApp->argv[mb_argc] = wxStrdup( tmp.c_str() ); + mb_argc++; + } + wxTheApp->argv[mb_argc] = (wxChar *)NULL; +#else + wxTheApp->argv = argv; +#endif + + if (wxTheApp->argc > 0) + { + wxFileName fname( wxTheApp->argv[0] ); + wxTheApp->SetAppName( fname.GetName() ); + } + wxTheApp->m_showIconic = g_showIconic; wxTheApp->m_initialSize = g_initialSize; @@ -1099,6 +1102,40 @@ bool wxApp::OnInitGui() return TRUE; } +#if wxUSE_UNICODE + +#include +#include +#include + +PangoContext* wxApp::GetPangoContext() +{ + static int use_xft = -1; + if (use_xft == -1) + { + wxString val = wxGetenv( L"GDK_USE_XFT" ); + use_xft = (val == L"1"); + } + + Display *xdisplay = (Display*) wxApp::GetDisplay(); + int xscreen = DefaultScreen(xdisplay); + + PangoContext *ret = NULL; + +#if 0 + if (use_xft) + ret = pango_xft_get_context( xdisplay, xscreen ); + else +#endif + ret = pango_x_get_context( xdisplay ); + + if (!PANGO_IS_CONTEXT(ret)) + wxLogError( wxT("No pango context.") ); + + return ret; +} +#endif + WXColormap wxApp::GetMainColormap(WXDisplay* display) { if (!display) /* Must be called first with non-NULL display */ diff --git a/src/x11/dcclient.cpp b/src/x11/dcclient.cpp index 005648b95c..20f168f19c 100644 --- a/src/x11/dcclient.cpp +++ b/src/x11/dcclient.cpp @@ -19,11 +19,20 @@ #include "wx/app.h" #include "wx/image.h" #include "wx/module.h" +#include "wx/fontutil.h" #include "wx/x11/private.h" #include +#if wxUSE_UNICODE +#include "glib.h" +#include "pango/pangox.h" +#include "pango/pangoxft.h" + +#include "pangox11.cpp" +#endif + //----------------------------------------------------------------------------- // local defines //----------------------------------------------------------------------------- @@ -163,6 +172,11 @@ wxWindowDC::wxWindowDC() m_isMemDC = FALSE; m_isScreenDC = FALSE; m_owner = (wxWindow *)NULL; + +#if wxUSE_UNICODE + m_context = (PangoContext *)NULL; + m_fontdesc = (PangoFontDescription *)NULL; +#endif } wxWindowDC::wxWindowDC( wxWindow *window ) @@ -193,6 +207,11 @@ wxWindowDC::wxWindowDC( wxWindow *window ) m_display = (WXDisplay *) wxGlobalDisplay(); +#if wxUSE_UNICODE + m_context = wxTheApp->GetPangoContext(); + m_fontdesc = window->GetFont().GetNativeFontInfo()->description; +#endif + int screen = DefaultScreen( (Display*) m_display ); m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen ); @@ -1368,19 +1387,35 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) wxCHECK_RET( Ok(), wxT("invalid window dc") ); if (!m_window) return; - -#if wxUSE_UNICODE - - // later - -#else - XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); - - wxCHECK_RET( xfont, wxT("invalid font") ); x = XLOG2DEV(x); y = YLOG2DEV(y); +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new(m_context); + pango_layout_set_font_description(layout, m_fontdesc); + + const wxCharBuffer data = wxConvUTF8.cWC2MB( text ); + pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); + + // Measure layout. + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + wxCoord width = w; + wxCoord height = h; + + // Draw layout. + x11_draw_layout( (Drawable) m_window, (GC) m_textGC, x, y, layout ); + + g_object_unref( G_OBJECT( layout ) ); + + CalcBoundingBox (x + width, y + height); + CalcBoundingBox (x, y); +#else + XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); + + wxCHECK_RET( xfont, wxT("invalid font") ); + // First draw a rectangle representing the text background, if a text // background is specified if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT)) @@ -1445,6 +1480,39 @@ void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoor { wxCHECK_RET( Ok(), "invalid dc" ); + if (string.IsEmpty()) + { + if (width) (*width) = 0; + if (height) (*height) = 0; + return; + } + +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( m_context ); + + if (font) + pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description ); + else + pango_layout_set_font_description(layout, m_fontdesc); + + const wxCharBuffer data = wxConvUTF8.cWC2MB( string ); + pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); + + // Measure text. + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + + if (width) (*width) = (wxCoord) w; + if (height) (*height) = (wxCoord) h; + if (descent) + { + // Do something about metrics here. TODO. + (*descent) = 0; + } + if (externalLeading) (*externalLeading) = 0; // ?? + + g_object_unref( G_OBJECT( layout ) ); +#else wxFont fontToUse = m_font; if (font) fontToUse = *font; @@ -1468,12 +1536,30 @@ void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoor *descent = (wxCoord)(descent2 / m_scaleY ); if (externalLeading) *externalLeading = 0; // ?? +#endif } wxCoord wxWindowDC::GetCharWidth() const { wxCHECK_MSG( Ok(), 0, "invalid dc" ); +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( m_context ); + + if (!m_fontdesc) + { + char *crash = NULL; + *crash = 0; + } + + pango_layout_set_font_description(layout, m_fontdesc); + pango_layout_set_text(layout, "H", 1 ); + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + g_object_unref( G_OBJECT( layout ) ); + + return w; +#else wxCHECK_MSG( m_font.Ok(), 0, "invalid font" ); XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); @@ -1486,12 +1572,31 @@ wxCoord wxWindowDC::GetCharWidth() const XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall ); return (wxCoord)(overall.width / m_scaleX); +#endif } wxCoord wxWindowDC::GetCharHeight() const { wxCHECK_MSG( Ok(), 0, "invalid dc" ); +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( m_context ); + + if (!m_fontdesc) + { + char *crash = NULL; + *crash = 0; + } + + pango_layout_set_font_description(layout, m_fontdesc); + + pango_layout_set_text(layout, "H", 1 ); + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + g_object_unref( G_OBJECT( layout ) ); + + return h; +#else wxCHECK_MSG( m_font.Ok(), 0, "invalid font" ); XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); @@ -1504,6 +1609,7 @@ wxCoord wxWindowDC::GetCharHeight() const XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall ); return (wxCoord)((ascent+descent) / m_scaleY); +#endif } void wxWindowDC::Clear() diff --git a/src/x11/dcscreen.cpp b/src/x11/dcscreen.cpp index 0efabc519c..d0dabfbbfc 100644 --- a/src/x11/dcscreen.cpp +++ b/src/x11/dcscreen.cpp @@ -17,6 +17,8 @@ #include "wx/frame.h" #include "wx/dcscreen.h" #include "wx/utils.h" +#include "wx/app.h" +#include "wx/fontutil.h" #include "wx/x11/private.h" @@ -47,6 +49,11 @@ wxScreenDC::wxScreenDC() m_isScreenDC = TRUE; +#if wxUSE_UNICODE + m_context = wxTheApp->GetPangoContext(); + m_fontdesc = wxNORMAL_FONT->GetNativeFontInfo()->description; +#endif + SetUpDC(); XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors ); diff --git a/src/x11/font.cpp b/src/x11/font.cpp index 6f6db81d0c..dcef0b7c49 100644 --- a/src/x11/font.cpp +++ b/src/x11/font.cpp @@ -38,12 +38,23 @@ #include "wx/fontutil.h" // for wxNativeFontInfo #include "wx/tokenzr.h" #include "wx/settings.h" + #include "wx/x11/private.h" IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject) // ---------------------------------------------------------------------------- -// private classes +// constants +// ---------------------------------------------------------------------------- + +// the default size (in points) for the fonts +static const int wxDEFAULT_FONT_SIZE = 12; + + +#if wxUSE_UNICODE +#else +// ---------------------------------------------------------------------------- +// wxXFont // ---------------------------------------------------------------------------- // For every wxFont, there must be a font for each display and scale requested. @@ -59,63 +70,6 @@ public: int m_scale; // Scale * 100 }; -class wxFontRefData: public wxGDIRefData -{ -friend class wxFont; - -public: - wxFontRefData(int size = wxDEFAULT, - int family = wxDEFAULT, - int style = wxDEFAULT, - int weight = wxDEFAULT, - bool underlined = FALSE, - const wxString& faceName = wxEmptyString, - wxFontEncoding encoding = wxFONTENCODING_DEFAULT) - { - Init(size, family, style, weight, underlined, faceName, encoding); - } - - wxFontRefData(const wxFontRefData& data) - { - Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight, - data.m_underlined, data.m_faceName, data.m_encoding); - } - - ~wxFontRefData(); - -protected: - // common part of all ctors - void Init(int size, - int family, - int style, - int weight, - bool underlined, - const wxString& faceName, - wxFontEncoding encoding); - - // font attributes - int m_pointSize; - int m_family; - int m_style; - int m_weight; - bool m_underlined; - wxString m_faceName; - wxFontEncoding m_encoding; - - wxNativeFontInfo m_nativeFontInfo; - - // A list of wxXFonts - wxList m_fonts; -}; - -// ============================================================================ -// implementation -// ============================================================================ - -// ---------------------------------------------------------------------------- -// wxXFont -// ---------------------------------------------------------------------------- - wxXFont::wxXFont() { m_fontStruct = (WXFontStructPtr) 0; @@ -130,6 +84,83 @@ wxXFont::~wxXFont() // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct; // XFreeFont((Display*) m_display, fontStruct); } +#endif + +// ---------------------------------------------------------------------------- +// wxFontRefData +// ---------------------------------------------------------------------------- + +class wxFontRefData: public wxObjectRefData +{ +friend class wxFont; + +public: + wxFontRefData(int size = wxDEFAULT, + int family = wxDEFAULT, + int style = wxDEFAULT, + int weight = wxDEFAULT, + bool underlined = FALSE, + const wxString& faceName = wxEmptyString, + wxFontEncoding encoding = wxFONTENCODING_DEFAULT); + + // copy cstr + wxFontRefData(const wxFontRefData& data); + + // from XFLD + wxFontRefData(const wxString& fontname); + + // dstr + virtual ~wxFontRefData(); + + // setters: all of them also take care to modify m_nativeFontInfo if we + // have it so as to not lose the information not carried by our fields + void SetPointSize(int pointSize); + void SetFamily(int family); + void SetStyle(int style); + void SetWeight(int weight); + void SetUnderlined(bool underlined); + void SetFaceName(const wxString& facename); + void SetEncoding(wxFontEncoding encoding); + + void SetNoAntiAliasing( bool no = TRUE ) { m_noAA = no; } + bool GetNoAntiAliasing() { return m_noAA; } + + // and this one also modifies all the other font data fields + void SetNativeFontInfo(const wxNativeFontInfo& info); + +protected: + // common part of all ctors + void Init(int size, + int family, + int style, + int weight, + bool underlined, + const wxString& faceName, + wxFontEncoding encoding); + + // set all fields from (already initialized and valid) m_nativeFontInfo + void InitFromNative(); + + // font attributes + int m_pointSize; + int m_family; + int m_style; + int m_weight; + bool m_underlined; + wxString m_faceName; + wxFontEncoding m_encoding; // Unused in Unicode mode + bool m_noAA; // No anti-aliasing + + wxNativeFontInfo m_nativeFontInfo; + + void ClearX11Fonts(); + +#if wxUSE_UNICODE +#else + // A list of wxXFonts + wxList m_fonts; +#endif +}; // ---------------------------------------------------------------------------- // wxFontRefData @@ -143,34 +174,256 @@ void wxFontRefData::Init(int pointSize, const wxString& faceName, wxFontEncoding encoding) { - if (family == wxDEFAULT) - m_family = wxSWISS; - else - m_family = family; + m_family = family == wxFONTFAMILY_DEFAULT ? wxFONTFAMILY_SWISS : family; m_faceName = faceName; - if (style == wxDEFAULT) - m_style = wxNORMAL; - else - m_style = style; + // we accept both wxDEFAULT and wxNORMAL here - should we? + m_style = style == wxDEFAULT ? wxFONTSTYLE_NORMAL : style; + m_weight = weight == wxDEFAULT ? wxFONTWEIGHT_NORMAL : weight; - if (weight == wxDEFAULT) - m_weight = wxNORMAL; - else - m_weight = weight; - - if (pointSize == wxDEFAULT) - m_pointSize = 12; - else - m_pointSize = pointSize; + // and here, do we really want to forbid creation of the font of the size + // 90 (the value of wxDEFAULT)?? + m_pointSize = pointSize == wxDEFAULT || pointSize == -1 + ? wxDEFAULT_FONT_SIZE + : pointSize; m_underlined = underlined; m_encoding = encoding; + +#if wxUSE_UNICODE + // Create native font info + m_nativeFontInfo.description = pango_font_description_new(); + + // And set its values + switch (m_family) + { + case wxFONTFAMILY_MODERN: + case wxFONTFAMILY_TELETYPE: + pango_font_description_set_family( m_nativeFontInfo.description, "monospace" ); + break; + case wxFONTFAMILY_SWISS: + pango_font_description_set_family( m_nativeFontInfo.description, "serif" ); + break; + default: + pango_font_description_set_family( m_nativeFontInfo.description, "sans" ); + break; + } + SetStyle( m_style ); + SetPointSize( m_pointSize ); + SetWeight( m_weight ); +#endif } -wxFontRefData::~wxFontRefData() +void wxFontRefData::InitFromNative() { + m_noAA = FALSE; + +#if wxUSE_UNICODE + // Get native info + PangoFontDescription *desc = m_nativeFontInfo.description; + + // init fields + m_faceName = wxGTK_CONV_BACK( pango_font_description_get_family( desc ) ); + + m_pointSize = pango_font_description_get_size( desc ) / PANGO_SCALE; + + switch (pango_font_description_get_style( desc )) + { + 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; + } + + switch (pango_font_description_get_weight( desc )) + { + 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; + } + + if (m_faceName == wxT("monospace")) + { + m_family = wxFONTFAMILY_TELETYPE; + } + else if (m_faceName == wxT("sans")) + { + m_family = wxFONTFAMILY_SWISS; + } + else + { + m_family = wxFONTFAMILY_UNKNOWN; + } + + // Pango description are never underlined (?) + m_underlined = FALSE; + + // Cannot we choose that + m_encoding = wxFONTENCODING_SYSTEM; +#else // X11 + // get the font parameters from the XLFD + // ------------------------------------- + + m_faceName = m_nativeFontInfo.GetXFontComponent(wxXLFD_FAMILY); + + m_weight = wxFONTWEIGHT_NORMAL; + + wxString w = m_nativeFontInfo.GetXFontComponent(wxXLFD_WEIGHT).Upper(); + if ( !w.empty() && w != _T('*') ) + { + // the test below catches all of BOLD, EXTRABOLD, DEMIBOLD, ULTRABOLD + // and BLACK + if ( ((w[0u] == _T('B') && (!wxStrcmp(w.c_str() + 1, wxT("OLD")) || + !wxStrcmp(w.c_str() + 1, wxT("LACK"))))) || + wxStrstr(w.c_str() + 1, _T("BOLD")) ) + { + m_weight = wxFONTWEIGHT_BOLD; + } + else if ( w == _T("LIGHT") || w == _T("THIN") ) + { + m_weight = wxFONTWEIGHT_LIGHT; + } + } + + switch ( wxToupper(*m_nativeFontInfo. + GetXFontComponent(wxXLFD_SLANT).c_str()) ) + { + case _T('I'): // italique + m_style = wxFONTSTYLE_ITALIC; + break; + + case _T('O'): // oblique + m_style = wxFONTSTYLE_SLANT; + break; + + default: + m_style = wxFONTSTYLE_NORMAL; + } + + long ptSize; + if ( m_nativeFontInfo.GetXFontComponent(wxXLFD_POINTSIZE).ToLong(&ptSize) ) + { + // size in XLFD is in 10 point units + m_pointSize = (int)(ptSize / 10); + } + else + { + m_pointSize = wxDEFAULT_FONT_SIZE; + } + + // examine the spacing: if the font is monospaced, assume wxTELETYPE + // family for compatibility with the old code which used it instead of + // IsFixedWidth() + if ( m_nativeFontInfo.GetXFontComponent(wxXLFD_SPACING).Upper() == _T('M') ) + { + m_family = wxFONTFAMILY_TELETYPE; + } + else // not monospaceed + { + // don't even try guessing it, it doesn't work for too many fonts + // anyhow + m_family = wxFONTFAMILY_UNKNOWN; + } + + // X fonts are never underlined... + m_underlined = FALSE; + + // deal with font encoding + wxString + registry = m_nativeFontInfo.GetXFontComponent(wxXLFD_REGISTRY).Upper(), + encoding = m_nativeFontInfo.GetXFontComponent(wxXLFD_ENCODING).Upper(); + + if ( registry == _T("ISO8859") ) + { + int cp; + if ( wxSscanf(encoding, wxT("%d"), &cp) == 1 ) + { + m_encoding = (wxFontEncoding)(wxFONTENCODING_ISO8859_1 + cp - 1); + } + } + else if ( registry == _T("MICROSOFT") ) + { + int cp; + if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 ) + { + m_encoding = (wxFontEncoding)(wxFONTENCODING_CP1250 + cp); + } + } + else if ( registry == _T("KOI8") ) + { + m_encoding = wxFONTENCODING_KOI8; + } + else // unknown encoding + { + // may be give a warning here? or use wxFontMapper? + m_encoding = wxFONTENCODING_SYSTEM; + } +#endif // Pango/X11 +} + +wxFontRefData::wxFontRefData( const wxFontRefData& data ) + : wxObjectRefData() +{ + m_pointSize = data.m_pointSize; + m_family = data.m_family; + m_style = data.m_style; + m_weight = data.m_weight; + + m_underlined = data.m_underlined; + + m_faceName = data.m_faceName; + m_encoding = data.m_encoding; + + m_noAA = data.m_noAA; + + m_nativeFontInfo = data.m_nativeFontInfo; +} + +wxFontRefData::wxFontRefData(int size, int family, int style, + int weight, bool underlined, + const wxString& faceName, + wxFontEncoding encoding) +{ + Init(size, family, style, weight, underlined, faceName, encoding); +} + +wxFontRefData::wxFontRefData(const wxString& fontname) +{ + // VZ: FromString() should really work in both cases, doesn't it? +#if wxUSE_UNICODE + m_nativeFontInfo.FromString( fontname ); +#else + m_nativeFontInfo.SetXFontName(fontname); +#endif + + InitFromNative(); +} + +void wxFontRefData::ClearX11Fonts() +{ +#if wxUSE_UNICODE +#else wxNode* node = m_fonts.First(); while (node) { @@ -179,21 +432,119 @@ wxFontRefData::~wxFontRefData() node = node->Next(); } m_fonts.Clear(); +#endif +} + +wxFontRefData::~wxFontRefData() +{ + ClearX11Fonts(); +} + +// ---------------------------------------------------------------------------- +// wxFontRefData SetXXX() +// ---------------------------------------------------------------------------- + +void wxFontRefData::SetPointSize(int pointSize) +{ + m_pointSize = pointSize; + +#if wxUSE_UNICODE + // Get native info + PangoFontDescription *desc = m_nativeFontInfo.description; + + pango_font_description_set_size( desc, m_pointSize * PANGO_SCALE ); +#endif +} + +void wxFontRefData::SetFamily(int family) +{ + m_family = family; + + // TODO: what are we supposed to do with m_nativeFontInfo here? +} + +void wxFontRefData::SetStyle(int style) +{ + m_style = style; + +#if wxUSE_UNICODE + // Get native info + PangoFontDescription *desc = m_nativeFontInfo.description; + + switch ( style ) + { + case wxFONTSTYLE_ITALIC: + pango_font_description_set_style( desc, PANGO_STYLE_ITALIC ); + break; + case wxFONTSTYLE_SLANT: + pango_font_description_set_style( desc, PANGO_STYLE_OBLIQUE ); + break; + default: + wxFAIL_MSG( _T("unknown font style") ); + // fall through + case wxFONTSTYLE_NORMAL: + pango_font_description_set_style( desc, PANGO_STYLE_NORMAL ); + break; + } +#endif +} + +void wxFontRefData::SetWeight(int weight) +{ + m_weight = weight; +} + +void wxFontRefData::SetUnderlined(bool underlined) +{ + m_underlined = underlined; + + // the XLFD doesn't have "underlined" field anyhow +} + +void wxFontRefData::SetFaceName(const wxString& facename) +{ + m_faceName = facename; +} + +void wxFontRefData::SetEncoding(wxFontEncoding encoding) +{ + m_encoding = encoding; +} + +void wxFontRefData::SetNativeFontInfo(const wxNativeFontInfo& info) +{ + // previously cached fonts shouldn't be used + ClearX11Fonts(); + + m_nativeFontInfo = info; + + // set all the other font parameters from the native font info + InitFromNative(); } // ---------------------------------------------------------------------------- // wxFont // ---------------------------------------------------------------------------- +void wxFont::Init() +{ +} + wxFont::wxFont(const wxNativeFontInfo& info) { Init(); - (void)Create(info.GetXFontName()); -} - -void wxFont::Init() -{ +#if wxUSE_UNICODE + Create( info.GetPointSize(), + info.GetFamily(), + info.GetStyle(), + info.GetWeight(), + info.GetUnderlined(), + info.GetFaceName(), + info.GetEncoding() ); +#else + (void) Create(info.GetXFontName()); +#endif } bool wxFont::Create(int pointSize, @@ -205,14 +556,15 @@ bool wxFont::Create(int pointSize, wxFontEncoding encoding) { UnRef(); + m_refData = new wxFontRefData(pointSize, family, style, weight, underlined, faceName, encoding); - RealizeResource(); - return TRUE; } +#if wxUSE_UNICODE +#else bool wxFont::Create(const wxString& fontname, wxFontEncoding enc) { if( !fontname ) @@ -315,6 +667,7 @@ bool wxFont::Create(const wxString& fontname, wxFontEncoding enc) } return TRUE; } +#endif wxFont::~wxFont() { @@ -339,90 +692,14 @@ void wxFont::Unshare() } } -void wxFont::SetPointSize(int pointSize) -{ - Unshare(); - - M_FONTDATA->m_pointSize = pointSize; - M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now - - RealizeResource(); -} - -void wxFont::SetFamily(int family) -{ - Unshare(); - - M_FONTDATA->m_family = family; - M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now - - RealizeResource(); -} - -void wxFont::SetStyle(int style) -{ - Unshare(); - - M_FONTDATA->m_style = style; - M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now - - RealizeResource(); -} - -void wxFont::SetWeight(int weight) -{ - Unshare(); - - M_FONTDATA->m_weight = weight; - M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now - - RealizeResource(); -} - -void wxFont::SetFaceName(const wxString& faceName) -{ - Unshare(); - - M_FONTDATA->m_faceName = faceName; - M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now - - RealizeResource(); -} - -void wxFont::SetUnderlined(bool underlined) -{ - Unshare(); - - M_FONTDATA->m_underlined = underlined; - - RealizeResource(); -} - -void wxFont::SetEncoding(wxFontEncoding encoding) -{ - Unshare(); - - M_FONTDATA->m_encoding = encoding; - M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now - - RealizeResource(); -} - -void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info) -{ - Unshare(); - - M_FONTDATA->m_nativeFontInfo = info; -} - // ---------------------------------------------------------------------------- -// query font attributes +// accessors // ---------------------------------------------------------------------------- int wxFont::GetPointSize() const { wxCHECK_MSG( Ok(), 0, wxT("invalid font") ); - + return M_FONTDATA->m_pointSize; } @@ -430,7 +707,7 @@ wxString wxFont::GetFaceName() const { wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") ); - return M_FONTDATA->m_faceName ; + return M_FONTDATA->m_faceName; } int wxFont::GetFamily() const @@ -468,18 +745,117 @@ wxFontEncoding wxFont::GetEncoding() const return M_FONTDATA->m_encoding; } +bool wxFont::GetNoAntiAliasing() +{ + wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") ); + + return M_FONTDATA->m_noAA; +} + wxNativeFontInfo *wxFont::GetNativeFontInfo() const { wxCHECK_MSG( Ok(), (wxNativeFontInfo *)NULL, wxT("invalid font") ); - if(M_FONTDATA->m_nativeFontInfo.GetXFontName().IsEmpty()) +#if wxUSE_UNICODE +#else + if ( M_FONTDATA->m_nativeFontInfo.GetXFontName().empty() ) GetInternalFont(); +#endif return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo); } +bool wxFont::IsFixedWidth() const +{ + wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") ); + +#if wxUSE_UNICODE +#else + if ( M_FONTDATA->HasNativeFont() ) + { + // the monospace fonts are supposed to have "M" in the spacing field + wxString spacing = M_FONTDATA-> + m_nativeFontInfo.GetXFontComponent(wxXLFD_SPACING); + + return spacing.Upper() == _T('M'); + } +#endif + + return wxFontBase::IsFixedWidth(); +} + // ---------------------------------------------------------------------------- -// real implementation +// change font attributes +// ---------------------------------------------------------------------------- + +void wxFont::SetPointSize(int pointSize) +{ + Unshare(); + + M_FONTDATA->SetPointSize(pointSize); +} + +void wxFont::SetFamily(int family) +{ + Unshare(); + + M_FONTDATA->SetFamily(family); +} + +void wxFont::SetStyle(int style) +{ + Unshare(); + + M_FONTDATA->SetStyle(style); +} + +void wxFont::SetWeight(int weight) +{ + Unshare(); + + M_FONTDATA->SetWeight(weight); +} + +void wxFont::SetFaceName(const wxString& faceName) +{ + Unshare(); + + M_FONTDATA->SetFaceName(faceName); +} + +void wxFont::SetUnderlined(bool underlined) +{ + Unshare(); + + M_FONTDATA->SetUnderlined(underlined); +} + +void wxFont::SetEncoding(wxFontEncoding encoding) +{ + Unshare(); + + M_FONTDATA->SetEncoding(encoding); +} + +void wxFont::SetNativeFontInfo( const wxNativeFontInfo& info ) +{ + Unshare(); + + M_FONTDATA->SetNativeFontInfo( info ); +} + +void wxFont::SetNoAntiAliasing( bool no ) +{ + Unshare(); + + M_FONTDATA->SetNoAntiAliasing( no ); +} + +#if wxUSE_UNICODE +#else + +// ---------------------------------------------------------------------------- +// X11 implementation // ---------------------------------------------------------------------------- // Find an existing, or create a new, XFontStruct @@ -536,3 +912,4 @@ WXFontStructPtr wxFont::GetFontStruct(double scale, WXDisplay* display) const return (f ? f->m_fontStruct : (WXFontStructPtr) 0); } +#endif diff --git a/src/x11/pangox11.cpp b/src/x11/pangox11.cpp new file mode 100644 index 0000000000..17108cf60b --- /dev/null +++ b/src/x11/pangox11.cpp @@ -0,0 +1,276 @@ +/** + * This file gets included from dcclient.cpp and implements + * the X11 interface to Pango. + * Copyright (C) Owen Taylor and Robert Roebling. + */ + +/* Declaration */ + +void +x11_draw_glyphs( Drawable drawable, + GC gc, + PangoFont *font, + int x, + int y, + PangoGlyphString *glyphs); + +void +x11_draw_layout_line_with_colors( Drawable drawable, + GC gc, + int x, + int y, + PangoLayoutLine *line, + XColor *foreground, + XColor *background); + +void +x11_draw_layout_with_colors( Drawable drawable, + GC gc, + int x, + int y, + PangoLayout *layout, + XColor *foreground, + XColor *background); + +void +x11_draw_layout( Drawable drawable, + GC gc, + int x, + int y, + PangoLayout *layout); + +void +x11_pango_get_item_properties( PangoItem *item, + PangoUnderline *uline, + gboolean *strikethrough, + gint *rise, + PangoColor *fg_color, + gboolean *fg_set, + PangoColor *bg_color, + gboolean *bg_set, + gboolean *shape_set, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + +/* Implementation */ + +void +x11_draw_glyphs( Drawable drawable, + GC gc, + PangoFont *font, + int x, + int y, + PangoGlyphString *glyphs) +{ + if (PANGO_XFT_IS_FONT (font)) + { + pango_xft_picture_render( wxGlobalDisplay(), drawable, drawable, font, glyphs, x, y ); + } + else + { + pango_x_render( wxGlobalDisplay(), drawable, gc, font, glyphs, x, y ); + } +} + +void +x11_draw_layout_line_with_colors( Drawable drawable, + GC gc, + int x, + int y, + PangoLayoutLine *line, + XColor *foreground, + XColor *background) +{ + PangoRectangle overall_rect; + PangoRectangle logical_rect; + PangoRectangle ink_rect; + PangoContext *context; + gint x_off = 0; + gint rise = 0; + + context = pango_layout_get_context (line->layout); + + pango_layout_line_get_extents (line,NULL, &overall_rect); + + GSList *tmp_list = line->runs; + while (tmp_list) + { + PangoUnderline uline = PANGO_UNDERLINE_NONE; + PangoLayoutRun *run = (PangoLayoutRun *) tmp_list->data; + PangoColor fg_color, bg_color; + gboolean strike, fg_set, bg_set, shape_set; + gint risen_y; + + tmp_list = tmp_list->next; + + x11_pango_get_item_properties (run->item, &uline, + &strike, &rise, &fg_color, &fg_set, &bg_color, &bg_set, + &shape_set, &ink_rect, &logical_rect); + + /* we subtract the rise because X coordinates are upside down */ + risen_y = y - rise / PANGO_SCALE; + + if (!shape_set) + { + if (uline == PANGO_UNDERLINE_NONE) + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, NULL, &logical_rect); + else + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, &ink_rect, &logical_rect); + } + +#if 0 + XDrawRectangle( drawable, gc, TRUE, + x + (x_off + logical_rect.x) / PANGO_SCALE, + risen_y + overall_rect.y / PANGO_SCALE, + logical_rect.width / PANGO_SCALE, + overall_rect.height / PANGO_SCALE); +#endif + + if (!shape_set) + { + int gx = x + x_off / PANGO_SCALE; + int gy = risen_y; + + x11_draw_glyphs( drawable, gc, run->item->analysis.font, gx, gy, run->glyphs); + } + + if (uline == PANGO_UNDERLINE_SINGLE) + { + XDrawLine( wxGlobalDisplay(), drawable, gc, + x + (x_off + ink_rect.x) / PANGO_SCALE - 1, + risen_y + 1, + x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, + risen_y + 1); + } + + x_off += logical_rect.width; + } +} + +void +x11_draw_layout_with_colors( Drawable drawable, + GC gc, + int x, + int y, + PangoLayout *layout, + XColor *foreground, + XColor *background) +{ + PangoLayoutIter *iter = pango_layout_get_iter (layout); + + do + { + PangoLayoutLine *line = pango_layout_iter_get_line (iter); + + PangoRectangle logical_rect; + pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); + + int baseline = pango_layout_iter_get_baseline (iter); + + x11_draw_layout_line_with_colors( drawable, gc, + x + logical_rect.x / PANGO_SCALE, + y + baseline / PANGO_SCALE, + line, + foreground, + background); + + } while (pango_layout_iter_next_line (iter)); + + pango_layout_iter_free (iter); +} + +void +x11_draw_layout( Drawable drawable, + GC gc, + int x, + int y, + PangoLayout *layout) +{ + wxCHECK_RET( layout, wxT("No layout") ); + + x11_draw_layout_with_colors (drawable, gc, x, y, layout, NULL, NULL); +} + +void +x11_pango_get_item_properties( PangoItem *item, + PangoUnderline *uline, + gboolean *strikethrough, + gint *rise, + PangoColor *fg_color, + gboolean *fg_set, + PangoColor *bg_color, + gboolean *bg_set, + gboolean *shape_set, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + GSList *tmp_list = item->analysis.extra_attrs; + + if (strikethrough) + *strikethrough = FALSE; + + if (fg_set) + *fg_set = FALSE; + + if (bg_set) + *bg_set = FALSE; + + if (shape_set) + *shape_set = FALSE; + + if (rise) + *rise = 0; + + while (tmp_list) + { + PangoAttribute *attr = (PangoAttribute *) tmp_list->data; + + switch (attr->klass->type) + { + case PANGO_ATTR_UNDERLINE: + if (uline) + *uline = (PangoUnderline) ((PangoAttrInt *)attr)->value; + break; + + case PANGO_ATTR_STRIKETHROUGH: + if (strikethrough) + *strikethrough = ((PangoAttrInt *)attr)->value; + break; + + case PANGO_ATTR_FOREGROUND: + if (fg_color) + *fg_color = ((PangoAttrColor *)attr)->color; + if (fg_set) + *fg_set = TRUE; + + break; + + case PANGO_ATTR_BACKGROUND: + if (bg_color) + *bg_color = ((PangoAttrColor *)attr)->color; + if (bg_set) + *bg_set = TRUE; + + break; + + case PANGO_ATTR_SHAPE: + if (shape_set) + *shape_set = TRUE; + if (logical_rect) + *logical_rect = ((PangoAttrShape *)attr)->logical_rect; + if (ink_rect) + *ink_rect = ((PangoAttrShape *)attr)->ink_rect; + break; + + case PANGO_ATTR_RISE: + if (rise) + *rise = ((PangoAttrInt *)attr)->value; + break; + + default: + break; + } + tmp_list = tmp_list->next; + } +} + diff --git a/src/x11/window.cpp b/src/x11/window.cpp index 857132a3ee..0b26998fbe 100644 --- a/src/x11/window.cpp +++ b/src/x11/window.cpp @@ -40,6 +40,7 @@ #include "wx/module.h" #include "wx/menuitem.h" #include "wx/log.h" +#include "wx/fontutil.h" #include "wx/univ/renderer.h" #if wxUSE_DRAG_AND_DROP @@ -987,6 +988,17 @@ int wxWindowX11::GetCharHeight() const { wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" ); +#if wxUSE_UNICODE + // There should be an easier way. + PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() ); + pango_layout_set_font_description( layout, GetFont().GetNativeFontInfo()->description ); + pango_layout_set_text(layout, "H", 1 ); + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + g_object_unref( G_OBJECT( layout ) ); + + return h; +#else WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, wxGlobalDisplay()); int direction, ascent, descent; @@ -996,12 +1008,24 @@ int wxWindowX11::GetCharHeight() const // return (overall.ascent + overall.descent); return (ascent + descent); +#endif } int wxWindowX11::GetCharWidth() const { wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" ); +#if wxUSE_UNICODE + // There should be an easier way. + PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() ); + pango_layout_set_font_description( layout, GetFont().GetNativeFontInfo()->description ); + pango_layout_set_text(layout, "H", 1 ); + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + g_object_unref( G_OBJECT( layout ) ); + + return w; +#else WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, wxGlobalDisplay()); int direction, ascent, descent; @@ -1010,6 +1034,7 @@ int wxWindowX11::GetCharWidth() const &descent, &overall); return overall.width; +#endif } void wxWindowX11::GetTextExtent(const wxString& string, @@ -1022,18 +1047,45 @@ void wxWindowX11::GetTextExtent(const wxString& string, wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") ); + if (string.IsEmpty()) + { + if (x) (*x) = 0; + if (y) (*y) = 0; + return; + } + +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() ); + + PangoFontDescription *desc = fontToUse.GetNativeFontInfo()->description; + pango_layout_set_font_description(layout, desc); + + const wxCharBuffer data = wxConvUTF8.cWC2MB( string ); + pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); + + PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data; + + + PangoRectangle rect; + pango_layout_line_get_extents(line, NULL, &rect); + + if (x) (*x) = (wxCoord) (rect.width / PANGO_SCALE); + if (y) (*y) = (wxCoord) (rect.height / PANGO_SCALE); + if (descent) + { + // Do something about metrics here + (*descent) = 0; + } + if (externalLeading) (*externalLeading) = 0; // ?? + + g_object_unref( G_OBJECT( layout ) ); +#else WXFontStructPtr pFontStruct = fontToUse.GetFontStruct(1.0, wxGlobalDisplay()); int direction, ascent, descent2; XCharStruct overall; int slen = string.Len(); -#if 0 - if (use16) - XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction, - &ascent, &descent2, &overall); -#endif - XTextExtents((XFontStruct*) pFontStruct, (char*) string.c_str(), slen, &direction, &ascent, &descent2, &overall); @@ -1045,7 +1097,7 @@ void wxWindowX11::GetTextExtent(const wxString& string, *descent = descent2; if (externalLeading) *externalLeading = 0; - +#endif } // ---------------------------------------------------------------------------- @@ -1477,7 +1529,9 @@ bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win // id may be WXK_xxx code - these are outside ASCII range, so we // can't just use toupper() on id if (id >= 'a' && id <= 'z') - id = toupper(id); + { + id = id + 'A' - 'a'; + } wxevent.m_shiftDown = XKeyEventShiftIsDown(xevent); wxevent.m_controlDown = XKeyEventCtrlIsDown(xevent);