]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/dcclient.cpp
code cleanup for the pen width condition (patch 1034942 + more)
[wxWidgets.git] / src / gtk1 / dcclient.cpp
index 802358014e1c2ac4535748ec3848b1a5e8bee33d..e38f88b9981f9abc4210fae760cfda7545b85c2e 100644 (file)
@@ -191,7 +191,7 @@ static void wxInitGCPool()
         // If we cannot malloc, then fail with error
         // when debug is enabled.  If debug is not enabled,
         // the problem will eventually get caught
         // If we cannot malloc, then fail with error
         // when debug is enabled.  If debug is not enabled,
         // the problem will eventually get caught
-               // in wxGetPoolGC.
+        // in wxGetPoolGC.
         wxFAIL_MSG( wxT("Cannot allocate GC pool") );
         return;
     }
         wxFAIL_MSG( wxT("Cannot allocate GC pool") );
         return;
     }
@@ -237,13 +237,13 @@ static GdkGC* wxGetPoolGC( GdkWindow *window, wxPoolGCType type )
     // We did not find an available GC.
     // We need to grow the GC pool.
     pptr = (wxGC *)realloc(wxGCPool,
     // We did not find an available GC.
     // We need to grow the GC pool.
     pptr = (wxGC *)realloc(wxGCPool,
-               (wxGCPoolSize + GC_POOL_ALLOC_SIZE)*sizeof(wxGC));
+        (wxGCPoolSize + GC_POOL_ALLOC_SIZE)*sizeof(wxGC));
     if (pptr != NULL)
     {
         // Initialize newly allocated pool.
         wxGCPool = pptr;
     if (pptr != NULL)
     {
         // Initialize newly allocated pool.
         wxGCPool = pptr;
-       memset(&wxGCPool[wxGCPoolSize], 0,
-                       GC_POOL_ALLOC_SIZE*sizeof(wxGC));
+        memset(&wxGCPool[wxGCPoolSize], 0,
+            GC_POOL_ALLOC_SIZE*sizeof(wxGC));
     
         // Initialize entry we will return.    
         wxGCPool[wxGCPoolSize].m_gc = gdk_gc_new( window );
     
         // Initialize entry we will return.    
         wxGCPool[wxGCPoolSize].m_gc = gdk_gc_new( window );
@@ -773,6 +773,7 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoor
 
         if (m_pen.GetStyle() != wxTRANSPARENT)
         {
 
         if (m_pen.GetStyle() != wxTRANSPARENT)
         {
+/*
             for (i = 0 ; i < n ; i++)
             {
                 gdk_draw_line( m_window, m_penGC,
             for (i = 0 ; i < n ; i++)
             {
                 gdk_draw_line( m_window, m_penGC,
@@ -781,6 +782,9 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoor
                                gdkpoints[(i+1)%n].x,
                                gdkpoints[(i+1)%n].y);
             }
                                gdkpoints[(i+1)%n].x,
                                gdkpoints[(i+1)%n].y);
             }
+*/
+            gdk_draw_polygon( m_window, m_penGC, FALSE, gdkpoints, n );
+            
         }
     }
 
         }
     }
 
@@ -1143,7 +1147,21 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
     }
     else
     {
     }
     else
     {
-        gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
+#if GTK_CHECK_VERSION(2,2,0)
+        if (use_bitmap.HasPixbuf())
+        {
+            gdk_draw_pixbuf(m_window, m_penGC,
+                            use_bitmap.GetPixbuf(),
+                            0, 0, xx, yy, -1, -1,
+                            GDK_RGB_DITHER_NORMAL, xx, yy);
+        }
+        else
+#endif
+        {
+            gdk_draw_pixmap(m_window, m_penGC,
+                            use_bitmap.GetPixmap(),
+                            0, 0, xx, yy, -1, -1);
+        }
     }
 
     // remove mask again if any
     }
 
     // remove mask again if any
@@ -1270,11 +1288,14 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
         wxCoord bm_width = memDC->m_selected.GetWidth();
         wxCoord bm_height = memDC->m_selected.GetHeight();
 
         wxCoord bm_width = memDC->m_selected.GetWidth();
         wxCoord bm_height = memDC->m_selected.GetHeight();
 
-        // get clip coords
-        wxRegion tmp( xx,yy,ww,hh );
-        tmp.Intersect( m_currentClippingRegion );
-        wxCoord cx,cy,cw,ch;
-        tmp.GetBox(cx,cy,cw,ch);
+        // Get clip coords for the bitmap. If we don't
+        // use wxBitmap::Rescale(), which can clip the
+        // bitmap, these are the same as the original
+        // coordinates
+        wxCoord cx = xx;
+        wxCoord cy = yy;
+        wxCoord cw = ww;
+        wxCoord ch = hh;
         
         // interpret userscale of src too
         double xsc,ysc;
         
         // interpret userscale of src too
         double xsc,ysc;
@@ -1285,16 +1306,23 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
         wxCoord bm_ww = XLOG2DEVREL( bm_width );
         wxCoord bm_hh = YLOG2DEVREL( bm_height );
 
         wxCoord bm_ww = XLOG2DEVREL( bm_width );
         wxCoord bm_hh = YLOG2DEVREL( bm_height );
 
-        // scale bitmap if required
+        // Scale bitmap if required
         wxBitmap use_bitmap;
         wxBitmap use_bitmap;
-
         if ((bm_width != bm_ww) || (bm_height != bm_hh))
         {
         if ((bm_width != bm_ww) || (bm_height != bm_hh))
         {
-            use_bitmap = memDC->m_selected.Rescale(cx-xx,cy-yy,cw,ch,bm_ww,bm_hh);  
+            // This indicates that the blitting code below will get
+            // a clipped bitmap and therefore needs to move the origin
+            // accordingly
+            wxRegion tmp( xx,yy,ww,hh );
+            tmp.Intersect( m_currentClippingRegion );
+            tmp.GetBox(cx,cy,cw,ch);
+            
+            // Scale and clipped bitmap
+            use_bitmap = memDC->m_selected.Rescale(cx-xx,cy-yy,cw,ch,bm_ww,bm_hh);
         }
         else
         {
         }
         else
         {
-            // FIXME: use cx,cy,cw,ch here, too?
+            // Don't scale bitmap
             use_bitmap = memDC->m_selected;
         }
 
             use_bitmap = memDC->m_selected;
         }
 
@@ -1453,17 +1481,33 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
     wxCHECK_RET( m_layout, wxT("no Pango layout") );
     wxCHECK_RET( m_fontdesc, wxT("no Pango font description") );
 
     wxCHECK_RET( m_layout, wxT("no Pango layout") );
     wxCHECK_RET( m_fontdesc, wxT("no Pango font description") );
 
+    bool underlined = m_font.Ok() && m_font.GetUnderlined();
+
 #if wxUSE_UNICODE
     const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
 #else
     const wxWCharBuffer wdata = wxConvLocal.cMB2WC( text );
 #if wxUSE_UNICODE
     const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
 #else
     const wxWCharBuffer wdata = wxConvLocal.cMB2WC( text );
+    if ( !wdata )
+        return;
     const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
 #endif
     const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
 #endif
-    pango_layout_set_text( m_layout, (const char*) data, strlen( (const char*) data ));
+    size_t datalen = strlen((const char*)data);
+    pango_layout_set_text( m_layout, (const char*) data, datalen);
+    
+    if (underlined)
+    {
+        PangoAttrList *attrs = pango_attr_list_new();
+        PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
+        a->start_index = 0;
+        a->end_index = datalen;
+        pango_attr_list_insert(attrs, a);
+        pango_layout_set_attributes(m_layout, attrs);
+        pango_attr_list_unref(attrs);
+    }
 
     int w,h;
     
 
     int w,h;
     
-    if (abs(m_scaleY - 1.0) < 0.00001)
+    if (fabs(m_scaleY - 1.0) < 0.00001)
     {
          // If there is a user or actually any scale applied to
          // the device context, scale the font.
     {
          // If there is a user or actually any scale applied to
          // the device context, scale the font.
@@ -1506,6 +1550,12 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
         // Draw layout.
         gdk_draw_layout( m_window, m_textGC, x, y, m_layout );
     }
         // Draw layout.
         gdk_draw_layout( m_window, m_textGC, x, y, m_layout );
     }
+
+    if (underlined)
+    {
+        // undo underline attributes setting:
+        pango_layout_set_attributes(m_layout, NULL);
+    }
     
     wxCoord width = w;
     wxCoord height = h;
     
     wxCoord width = w;
     wxCoord height = h;
@@ -1661,10 +1711,17 @@ void wxWindowDC::DoGetTextExtent(const wxString &string,
                                  wxCoord *descent, wxCoord *externalLeading,
                                  wxFont *theFont) const
 {
                                  wxCoord *descent, wxCoord *externalLeading,
                                  wxFont *theFont) const
 {
+    if ( width )
+        *width = 0;
+    if ( height )
+        *height = 0;
+    if ( descent )
+        *descent = 0;
+    if ( externalLeading )
+        *externalLeading = 0;
+
     if (string.IsEmpty())
     {
     if (string.IsEmpty())
     {
-        if (width) (*width) = 0;
-        if (height) (*height) = 0;
         return;
     }
     
         return;
     }
     
@@ -1676,38 +1733,61 @@ void wxWindowDC::DoGetTextExtent(const wxString &string,
     // Set layout's text
 #if wxUSE_UNICODE
     const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
     // Set layout's text
 #if wxUSE_UNICODE
     const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
-    pango_layout_set_text( m_layout, (const char*) data, strlen( (const char*) data ));
+    const char *dataUTF8 = (const char *)data;
 #else
     const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string );
 #else
     const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string );
+    if ( !wdata )
+    {
+        if (width) (*width) = 0;
+        if (height) (*height) = 0;
+        return;
+    }
     const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
     const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
-    pango_layout_set_text( m_layout, (const char*) data, strlen( (const char*) data ));
+    const char *dataUTF8 = (const char *)data;
 #endif
 #endif
+
+    if ( !dataUTF8 )
+    {
+        // hardly ideal, but what else can we do if conversion failed?
+        return;
+    }
+
+    pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) );
  
     int w,h;
     pango_layout_get_pixel_size( m_layout, &w, &h );
     
  
     int w,h;
     pango_layout_get_pixel_size( m_layout, &w, &h );
     
-    if (width) (*width) = (wxCoord) w; 
-    if (height) (*height) = (wxCoord) h;
+    if (width)
+        *width = (wxCoord) w; 
+    if (height)
+        *height = (wxCoord) h;
     if (descent)
     {
     if (descent)
     {
-        // Do something about metrics here. TODO.
-        (*descent) = 0;
+        PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
+        int baseline = pango_layout_iter_get_baseline(iter);
+        pango_layout_iter_free(iter);
+        *descent = h - PANGO_PIXELS(baseline);
     }
     }
-    if (externalLeading) (*externalLeading) = 0;  // ??
     
     // Reset old font description
     if (theFont)
         pango_layout_set_font_description( m_layout, m_fontdesc );
     
     // Reset old font description
     if (theFont)
         pango_layout_set_font_description( m_layout, m_fontdesc );
-#else
+#else // GTK+ 1.x
     wxFont fontToUse = m_font;
     wxFont fontToUse = m_font;
-    if (theFont) fontToUse = *theFont;
+    if (theFont)
+        fontToUse = *theFont;
     
     GdkFont *font = fontToUse.GetInternalFont( m_scaleY );
     
     GdkFont *font = fontToUse.GetInternalFont( m_scaleY );
-    if (width) (*width) = wxCoord(gdk_string_width( font, string.mbc_str() ) / m_scaleX);
-    if (height) (*height) = wxCoord((font->ascent + font->descent) / m_scaleY);
-    if (descent) (*descent) = wxCoord(font->descent / m_scaleY);
-    if (externalLeading) (*externalLeading) = 0;  // ??
-#endif
+    if ( !font )
+        return;
+
+    if (width)
+        *width = wxCoord(gdk_string_width( font, string.mbc_str() ) / m_scaleX);
+    if (height)
+        *height = wxCoord((font->ascent + font->descent) / m_scaleY);
+    if (descent)
+        *descent = wxCoord(font->descent / m_scaleY);
+#endif // GTK+ 2/1
 }
 
 wxCoord wxWindowDC::GetCharWidth() const
 }
 
 wxCoord wxWindowDC::GetCharWidth() const
@@ -2317,6 +2397,25 @@ int wxWindowDC::GetDepth() const
 
 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
 
 
 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
 
+// Limit the paint region to the window size. Sometimes
+// the paint region is too big, and this risks X11 errors
+static void wxLimitRegionToSize(wxRegion& region, const wxSize& sz)
+{
+    wxRect originalRect = region.GetBox();
+    wxRect rect(originalRect);
+    if (rect.width + rect.x > sz.x)
+        rect.width = sz.x - rect.x;
+    if (rect.height + rect.y > sz.y)
+        rect.height = sz.y - rect.y;
+    if (rect != originalRect)
+    {
+        region = wxRegion(rect);
+        wxLogTrace(wxT("painting"), wxT("Limiting region from %d, %d, %d, %d to %d, %d, %d, %d\n"),
+                   originalRect.x, originalRect.y, originalRect.width, originalRect.height,
+                   rect.x, rect.y, rect.width, rect.height);
+    }
+}
+
 wxPaintDC::wxPaintDC( wxWindow *win )
          : wxClientDC( win )
 {
 wxPaintDC::wxPaintDC( wxWindow *win )
          : wxClientDC( win )
 {
@@ -2324,21 +2423,23 @@ wxPaintDC::wxPaintDC( wxWindow *win )
     if (!win->m_clipPaintRegion)
         return;
 
     if (!win->m_clipPaintRegion)
         return;
 
+    wxSize sz = win->GetSize();
     m_paintClippingRegion = win->GetUpdateRegion();
     m_paintClippingRegion = win->GetUpdateRegion();
+    wxLimitRegionToSize(m_paintClippingRegion, sz);
+    
     GdkRegion *region = m_paintClippingRegion.GetRegion();
     if ( region )
     {
     GdkRegion *region = m_paintClippingRegion.GetRegion();
     if ( region )
     {
-        m_paintClippingRegion = win->GetUpdateRegion();
-        GdkRegion *region = m_paintClippingRegion.GetRegion();
-        if ( region )
-        {
-            m_currentClippingRegion.Union( m_paintClippingRegion );
+        m_currentClippingRegion.Union( m_paintClippingRegion );
+        wxLimitRegionToSize(m_currentClippingRegion, sz);
 
 
-            gdk_gc_set_clip_region( m_penGC, region );
-            gdk_gc_set_clip_region( m_brushGC, region );
-            gdk_gc_set_clip_region( m_textGC, region );
-            gdk_gc_set_clip_region( m_bgGC, region );
-        }
+        if (sz.x <= 0 || sz.y <= 0)
+            return ;
+
+        gdk_gc_set_clip_region( m_penGC, region );
+        gdk_gc_set_clip_region( m_brushGC, region );
+        gdk_gc_set_clip_region( m_textGC, region );
+        gdk_gc_set_clip_region( m_bgGC, region );
     }
 #endif // USE_PAINT_REGION
 }
     }
 #endif // USE_PAINT_REGION
 }