]> git.saurik.com Git - wxWidgets.git/blobdiff - src/x11/dcclient.cpp
use GetFont() instead of (possibly not initialized) m_font in GetCharWidth/Height()
[wxWidgets.git] / src / x11 / dcclient.cpp
index 8307fe264c847e11bceead70b8b456125282aa27..29fd42b652ee4be4fc805715a5924d63ae5aec57 100644 (file)
@@ -9,7 +9,7 @@
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
     #pragma implementation "dcclient.h"
 #endif
 
 #include "wx/window.h"
 #include "wx/app.h"
 #include "wx/image.h"
+#include "wx/module.h"
+#include "wx/fontutil.h"
 
 #include "wx/x11/private.h"
 
 #include <math.h>
 
+#if wxUSE_UNICODE
+#include "glib.h"
+#include "pango/pangox.h"
+#include "pango/pangoxft.h"
+
+#include "pango_x.cpp"
+#endif
+
 //-----------------------------------------------------------------------------
 // local defines
 //-----------------------------------------------------------------------------
@@ -162,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 )
@@ -192,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 );
 
@@ -313,10 +333,13 @@ void wxWindowDC::DoGetSize( int* width, int* height ) const
     m_owner->GetSize(width, height);
 }
 
-void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1),
-                           const wxColour& WXUNUSED(col), int WXUNUSED(style) )
+extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, 
+                          const wxColour & col, int style);
+
+bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y,
+                             const wxColour& col, int style)
 {
-    wxFAIL_MSG("not implemented");
+    return wxDoFloodFill(this, x, y, col, style);
 }
 
 bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
@@ -328,7 +351,7 @@ bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
     memdc.SelectObject(bitmap);
     memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1);
     memdc.SelectObject(wxNullBitmap);
-    wxImage image(bitmap);
+    wxImage image(bitmap.ConvertToImage());
     col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
     return TRUE;
 }
@@ -340,8 +363,19 @@ void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
     if (m_pen.GetStyle() != wxTRANSPARENT)
     {
         if (m_window)
-            XDrawLine( (Display*) m_display, (Window) m_window, 
-                (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
+        {
+            // This hack is for the iPaq: XDrawLine draws
+            // nothing, whereas XDrawLines works...
+            wxPoint points[2];
+            points[0].x = x1;
+            points[0].y = y1;
+            points[1].x = x2;
+            points[1].y = y2;
+            DrawLines( 2, points, 0, 0 );
+            
+            // XDrawLine( (Display*) m_display, (Window) m_window, 
+            //    (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
+        }
 
         CalcBoundingBox(x1, y1);
         CalcBoundingBox(x2, y2);
@@ -880,14 +914,14 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
     wxBitmap use_bitmap;
     if ((w != ww) || (h != hh))
     {
-        wxImage image( bitmap );
+        wxImage image( bitmap.ConvertToImage() );
         image.Rescale( ww, hh );
 #if 0
         if (is_mono)
             use_bitmap = image.ConvertToMonoBitmap(255,255,255);
         else
 #endif
-            use_bitmap = image.ConvertToBitmap();
+            use_bitmap = image;
     }
     else
     {
@@ -999,14 +1033,14 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
     wxBitmap use_bitmap;
     if ((w != ww) || (h != hh))
     {
-        wxImage image( bitmap );
+        wxImage image( bitmap.ConvertToImage() );
         image.Rescale( ww, hh );
 #if 0
         if (is_mono)
             use_bitmap = image.ConvertToMonoBitmap(255,255,255);
         else
 #endif
-            use_bitmap = image.ConvertToBitmap();
+            use_bitmap = image;
     }
     else
     {
@@ -1202,7 +1236,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
 
         if ((bm_width != bm_ww) || (bm_height != bm_hh))
         {
-            wxImage image( memDC->m_selected );
+            wxImage image( memDC->m_selected.ConvertToImage() );
             image = image.Scale( bm_ww, bm_hh );
 
 #if 0
@@ -1210,7 +1244,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
                 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
             else
 #endif
-                use_bitmap = image.ConvertToBitmap();
+                use_bitmap = image;
         }
         else
         {
@@ -1321,11 +1355,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
             XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
 
             // scale image
-            wxImage image( bitmap );
+            wxImage image( bitmap.ConvertToImage() );
             image = image.Scale( ww, hh );
 
             // convert to bitmap
-            bitmap = image.ConvertToBitmap();
+            bitmap = image;
 
             // draw scaled bitmap
             XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window, 
@@ -1354,13 +1388,34 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
 
     if (!m_window) return;
 
-    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, m_textForegroundColour );
+    
+    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))
@@ -1375,7 +1430,7 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
         slen = strlen(text);
         XCharStruct overall_return;
 
-        (void)XTextExtents(xfont, text.c_str(), slen, &direction,
+        (void)XTextExtents(xfont, (char*) text.c_str(), slen, &direction,
                                  &ascent, &descent, &overall_return);
 
         cx = overall_return.width;
@@ -1411,6 +1466,7 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
     CalcBoundingBox (x + width, y + height);
     CalcBoundingBox (x, y);
 #endif
+#endif
 }
 
 void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
@@ -1422,12 +1478,45 @@ void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoor
                                 wxCoord *descent, wxCoord *externalLeading,
                                 wxFont *font ) const
 {
-    wxCHECK_RET( Ok(), "invalid dc" );
+    wxCHECK_RET( Ok(), wxT("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;
 
-    wxCHECK_RET( fontToUse.Ok(), "invalid font" );
+    wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
 
     XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
 
@@ -1447,13 +1536,31 @@ 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" );
+    wxCHECK_MSG( Ok(), 0, wxT("invalid dc") );
     
-    wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
+#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, wxT("invalid font") );
 
     XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
 
@@ -1465,13 +1572,32 @@ 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" );
+    wxCHECK_MSG( Ok(), 0, wxT("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);
     
-    wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
+    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, wxT("invalid font") );
 
     XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
 
@@ -1483,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()
@@ -1517,7 +1644,7 @@ void wxWindowDC::Clear()
 
 void wxWindowDC::SetFont( const wxFont &font )
 {
-    wxCHECK_RET( Ok(), "invalid dc" );
+    wxCHECK_RET( Ok(), wxT("invalid dc") );
 
     m_font = font;
 }
@@ -1741,7 +1868,7 @@ void wxWindowDC::SetBackground( const wxBrush &brush )
 
 void wxWindowDC::SetLogicalFunction( int function )
 {
-    wxCHECK_RET( Ok(), "invalid dc" );
+    wxCHECK_RET( Ok(), wxT("invalid dc") );
 
     int x_function;
 
@@ -2030,64 +2157,63 @@ int wxWindowDC::GetDepth() const
     return -1;
 }
 
+//-----------------------------------------------------------------------------
+// wxClientDC
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
+
+wxClientDC::wxClientDC( wxWindow *window )
+          : wxWindowDC( window )
+{
+    wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
+    
+    m_window = (WXWindow*) window->GetClientAreaWindow();
+    
+    // Adjust the client area when the wxWindow is not using 2 X11 windows.
+    if (m_window == (WXWindow*) window->GetMainWindow())
+    {
+        wxPoint ptOrigin = window->GetClientAreaOrigin();
+        SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
+        wxSize size = window->GetClientSize();
+        SetClippingRegion(wxPoint(0, 0), size);
+    }
+}
+
+void wxClientDC::DoGetSize(int *width, int *height) const
+{
+    wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
+
+    m_owner->GetClientSize( width, height );
+}
+
 // ----------------------------------------------------------------------------
 // wxPaintDC
 // ----------------------------------------------------------------------------
 
 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
 
-wxPaintDC::wxPaintDC(wxWindow* win)
-  : wxClientDC(win)
+wxPaintDC::wxPaintDC(wxWindow* window)
+  : wxClientDC(window)
 {
 #if USE_PAINT_REGION
-    if (!win->GetClipPaintRegion())
+    if (!window->GetClipPaintRegion())
         return;
 
-    m_paintClippingRegion = win->GetUpdateRegion();
+    m_paintClippingRegion = window->GetUpdateRegion();
     Region region = (Region) m_paintClippingRegion.GetX11Region();
     if (region)
     {
-        m_paintClippingRegion = win->GetUpdateRegion();
-        Region region2 = (Region) m_paintClippingRegion.GetX11Region();
-        if (region2)
-        {
             m_currentClippingRegion.Union( m_paintClippingRegion );
 
-            XSetRegion( (Display*) m_display, (GC) m_penGC, region2 );
-            XSetRegion( (Display*) m_display, (GC) m_brushGC, region2 );
-            XSetRegion( (Display*) m_display, (GC) m_textGC, region2 );
-            XSetRegion( (Display*) m_display, (GC) m_bgGC, region2 );
-        }
+            XSetRegion( (Display*) m_display, (GC) m_penGC, region );
+            XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
+            XSetRegion( (Display*) m_display, (GC) m_textGC, region );
+            XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
     }
 #endif // USE_PAINT_REGION
 }
 
-//-----------------------------------------------------------------------------
-// wxClientDC
-//-----------------------------------------------------------------------------
-
-IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
-
-wxClientDC::wxClientDC( wxWindow *win )
-          : wxWindowDC( win )
-{
-    wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") );
-    
-#ifdef __WXUNIVERSAL__
-    wxPoint ptOrigin = win->GetClientAreaOrigin();
-    SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
-    wxSize size = win->GetClientSize();
-    SetClippingRegion(wxPoint(0, 0), size);
-#endif // __WXUNIVERSAL__
-}
-
-void wxClientDC::DoGetSize(int *width, int *height) const
-{
-    wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
-
-    m_owner->GetClientSize( width, height );
-}
-
 // ----------------------------------------------------------------------------
 // wxDCModule
 // ----------------------------------------------------------------------------