]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/dcclient.cpp
wxRTC: fixed guidelines overwriting adjacent cell borders; corrected capitalisation...
[wxWidgets.git] / src / gtk / dcclient.cpp
index dab19cc1986b125e317fa32b8fc0a210928d92f9..2c4a716964b22f66e61bc104cf8b00d4275ccb43 100644 (file)
@@ -2,7 +2,6 @@
 // Name:        src/gtk/dcclient.cpp
 // Purpose:     wxWindowDCImpl implementation
 // Author:      Robert Roebling
-// RCS-ID:      $Id$
 // Copyright:   (c) 1998 Robert Roebling, Chris Breeze
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
@@ -64,8 +63,6 @@ static const double RAD2DEG  = 180.0 / M_PI;
 static inline double dmax(double a, double b) { return a > b ? a : b; }
 static inline double dmin(double a, double b) { return a < b ? a : b; }
 
-static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
-
 static GdkPixmap* GetHatch(int style)
 {
     wxASSERT(style >= wxBRUSHSTYLE_FIRST_HATCH && style <= wxBRUSHSTYLE_LAST_HATCH);
@@ -731,7 +728,7 @@ void wxWindowDCImpl::DoDrawLines( int n, const wxPoint points[], wxCoord xoffset
     }
 
     if (m_gdkwindow)
-        gdk_draw_lines( m_gdkwindow, m_penGC, gpts, n);
+        gdk_draw_lines( m_gdkwindow, m_penGC, (GdkPoint*) gpts, n);
 
     delete[] gpts_alloc;
 }
@@ -777,7 +774,7 @@ void wxWindowDCImpl::DoDrawPolygon( int n, const wxPoint points[],
             bool originChanged;
             DrawingSetup(gc, originChanged);
 
-            gdk_draw_polygon(m_gdkwindow, gc, true, gdkpoints, n);
+            gdk_draw_polygon(m_gdkwindow, gc, true, (GdkPoint*) gdkpoints, n);
 
             if (originChanged)
                 gdk_gc_set_ts_origin(gc, 0, 0);
@@ -795,7 +792,7 @@ void wxWindowDCImpl::DoDrawPolygon( int n, const wxPoint points[],
                                gdkpoints[(i+1)%n].y);
             }
 */
-            gdk_draw_polygon( m_gdkwindow, m_penGC, FALSE, gdkpoints, n );
+            gdk_draw_polygon( m_gdkwindow, m_penGC, FALSE, (GdkPoint*) gdkpoints, n );
 
         }
     }
@@ -1132,9 +1129,10 @@ void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap,
         if (m)
             mask = *m;
     }
+
+    GdkPixmap* mask_new = NULL;
     if (mask)
     {
-        GdkPixmap* mask_new = NULL;
         if (isScaled)
         {
             mask = ScaleMask(mask, 0, 0, w, h, ww, hh, m_scaleX, m_scaleY);
@@ -1151,8 +1149,6 @@ void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap,
         }
         gdk_gc_set_clip_mask(use_gc, mask);
         gdk_gc_set_clip_origin(use_gc, xx, yy);
-        if (mask_new)
-            g_object_unref(mask_new);
     }
 
     // determine whether to use pixmap or pixbuf
@@ -1199,7 +1195,16 @@ void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap,
     if (pixmap_new)
         g_object_unref(pixmap_new);
     if (mask)
+    {
         gdk_gc_set_clip_region(use_gc, clipRegion);
+
+        // Notice that we can only release the mask now, we can't do it before
+        // the calls to gdk_draw_xxx() above as they crash with X error with
+        // GTK+ up to 2.20.1 (i.e. it works with 2.20 but is known to not work
+        // with 2.16.1 and below).
+        if (mask_new)
+            g_object_unref(mask_new);
+    }
 }
 
 bool wxWindowDCImpl::DoBlit( wxCoord xdest, wxCoord ydest,
@@ -1389,158 +1394,75 @@ void wxWindowDCImpl::DoDrawText(const wxString& text,
                                 wxCoord xLogical,
                                 wxCoord yLogical)
 {
-    wxCHECK_RET( IsOk(), wxT("invalid window dc") );
-
-    if (!m_gdkwindow) return;
-
-    if (text.empty()) return;
-
-    wxCoord x = XLOG2DEV(xLogical),
-            y = YLOG2DEV(yLogical);
-
-    wxCHECK_RET( m_context, wxT("no Pango context") );
-    wxCHECK_RET( m_layout, wxT("no Pango layout") );
-    wxCHECK_RET( m_fontdesc, wxT("no Pango font description") );
-
-    gdk_pango_context_set_colormap( m_context, m_cmap );  // not needed in gtk+ >= 2.6
-
-    wxCharBuffer data = wxGTK_CONV(text);
-    if ( !data )
-        return;
-
-    pango_layout_set_text(m_layout, data, data.length());
-    const bool setAttrs = m_font.GTKSetPangoAttrs(m_layout);
-
-    int oldSize = 0;
-    const bool isScaled = fabs(m_scaleY - 1.0) > 0.00001;
-    if (isScaled)
-    {
-        // If there is a user or actually any scale applied to
-        // the device context, scale the font.
-
-        // scale font description
-        oldSize = pango_font_description_get_size(m_fontdesc);
-        pango_font_description_set_size(m_fontdesc, int(oldSize * m_scaleY));
-
-        // actually apply scaled font
-        pango_layout_set_font_description( m_layout, m_fontdesc );
-    }
-
-    int w, h;
-    pango_layout_get_pixel_size(m_layout, &w, &h);
-
-    // Draw layout.
-    int x_rtl = x;
-    if (m_window && m_window->GetLayoutDirection() == wxLayout_RightToLeft)
-        x_rtl -= w;
-
-    const GdkColor* bg_col = NULL;
-    if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
-        bg_col = m_textBackgroundColour.GetColor();
-
-    gdk_draw_layout_with_colors(m_gdkwindow, m_textGC, x_rtl, y, m_layout, NULL, bg_col);
-
-    if (isScaled)
-    {
-         // reset unscaled size
-         pango_font_description_set_size( m_fontdesc, oldSize );
-
-         // actually apply unscaled font
-         pango_layout_set_font_description( m_layout, m_fontdesc );
-    }
-    if (setAttrs)
-    {
-        // undo underline attributes setting:
-        pango_layout_set_attributes(m_layout, NULL);
-    }
-
-    CalcBoundingBox(xLogical + int(w / m_scaleX), yLogical + int(h / m_scaleY));
-    CalcBoundingBox(xLogical, yLogical);
+    DoDrawRotatedText(text, xLogical, yLogical, 0);
 }
 
-// TODO: When GTK2.6 is required, merge DoDrawText and DoDrawRotatedText to
-// avoid code duplication
-void wxWindowDCImpl::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
+void wxWindowDCImpl::DoDrawRotatedText(const wxString& text, int xLogical, int yLogical, double angle)
 {
     if (!m_gdkwindow || text.empty())
         return;
 
     wxCHECK_RET( IsOk(), wxT("invalid window dc") );
 
-    x = XLOG2DEV(x);
-    y = YLOG2DEV(y);
-
     pango_layout_set_text(m_layout, wxGTK_CONV(text), -1);
     const bool setAttrs = m_font.GTKSetPangoAttrs(m_layout);
-    int oldSize = 0;
-    const bool isScaled = fabs(m_scaleY - 1.0) > 0.00001;
-    if (isScaled)
-    {
-        //TODO: when Pango >= 1.6 is required, use pango_matrix_scale()
-         // If there is a user or actually any scale applied to
-         // the device context, scale the font.
-
-         // scale font description
-        oldSize = pango_font_description_get_size(m_fontdesc);
-        pango_font_description_set_size(m_fontdesc, int(oldSize * m_scaleY));
-
-         // actually apply scaled font
-         pango_layout_set_font_description( m_layout, m_fontdesc );
-    }
-
-    int w, h;
-    pango_layout_get_pixel_size(m_layout, &w, &h);
 
     const GdkColor* bg_col = NULL;
     if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
         bg_col = m_textBackgroundColour.GetColor();
 
-    // rotate the text
     PangoMatrix matrix = PANGO_MATRIX_INIT;
-    pango_matrix_rotate (&matrix, angle);
-    pango_context_set_matrix (m_context, &matrix);
-    pango_layout_context_changed (m_layout);
-
-    // To be compatible with MSW, the rotation axis must be in the old
-    // top-left corner.
-    // Calculate the vertices of the rotated rectangle containing the text,
-    // relative to the old top-left vertex.
-    // We could use the matrix for this, but it's simpler with trignonometry.
-    double rad = DegToRad(angle);
-    // the rectangle vertices are counted clockwise with the first one
-    // being at (0, 0)
-    double x2 = w * cos(rad);
-    double y2 = -w * sin(rad);   // y axis points to the bottom, hence minus
-    double x4 = h * sin(rad);
-    double y4 = h * cos(rad);
-    double x3 = x4 + x2;
-    double y3 = y4 + y2;
-    // Then we calculate max and min of the rotated rectangle.
-    wxCoord maxX = (wxCoord)(dmax(dmax(0, x2), dmax(x3, x4)) + 0.5),
-            maxY = (wxCoord)(dmax(dmax(0, y2), dmax(y3, y4)) + 0.5),
-            minX = (wxCoord)(dmin(dmin(0, x2), dmin(x3, x4)) - 0.5),
-            minY = (wxCoord)(dmin(dmin(0, y2), dmin(y3, y4)) - 0.5);
-
-    gdk_draw_layout_with_colors(m_gdkwindow, m_textGC, x+minX, y+minY,
-                                m_layout, NULL, bg_col);
+    if (!wxIsSameDouble(m_scaleX, 1) || !wxIsSameDouble(m_scaleY, 1) || !wxIsNullDouble(angle))
+    {
+        pango_matrix_scale(&matrix, m_scaleX, m_scaleY);
+        pango_matrix_rotate(&matrix, angle);
+        pango_context_set_matrix(m_context, &matrix);
+        pango_layout_context_changed(m_layout);
+    }
 
-    if (setAttrs)
-        pango_layout_set_attributes(m_layout, NULL);
+    int w, h;
+    pango_layout_get_pixel_size(m_layout, &w, &h);
 
-    // clean up the transformation matrix
-    pango_context_set_matrix(m_context, NULL);
+    int x = LogicalToDeviceX(xLogical);
+    int y = LogicalToDeviceY(yLogical);
+    if (m_window && m_window->GetLayoutDirection() == wxLayout_RightToLeft)
+        x -= LogicalToDeviceXRel(w);
 
-    if (isScaled)
+    if (wxIsNullDouble(angle))
     {
-         // reset unscaled size
-         pango_font_description_set_size( m_fontdesc, oldSize );
-
-         // actually apply unscaled font
-         pango_layout_set_font_description( m_layout, m_fontdesc );
+        CalcBoundingBox(xLogical, yLogical);
+        CalcBoundingBox(xLogical + w, yLogical + h);
     }
+    else
+    {
+        // To be compatible with MSW, the rotation axis must be in the old
+        // top-left corner.
+        // Calculate the vertices of the rotated rectangle containing the text,
+        // relative to the old top-left vertex.
+        // the rectangle vertices are counted clockwise with the first one
+        // being at (0, 0)
+        double x2 = w * matrix.xx;
+        double y2 = w * matrix.yx;
+        double x4 = h * matrix.xy;
+        double y4 = h * matrix.yy;
+        double x3 = x4 + x2;
+        double y3 = y4 + y2;
+        // Then we calculate max and min of the rotated rectangle.
+        wxCoord maxX = (wxCoord)(dmax(dmax(0, x2), dmax(x3, x4)) + 0.5),
+                maxY = (wxCoord)(dmax(dmax(0, y2), dmax(y3, y4)) + 0.5),
+                minX = (wxCoord)(dmin(dmin(0, x2), dmin(x3, x4)) - 0.5),
+                minY = (wxCoord)(dmin(dmin(0, y2), dmin(y3, y4)) - 0.5);
+        x += minX;
+        y += minY;
+        CalcBoundingBox(DeviceToLogicalX(x), DeviceToLogicalY(y));
+        CalcBoundingBox(DeviceToLogicalX(x + maxX - minX), DeviceToLogicalY(y + maxY - minY));
+    }
+
+    gdk_draw_layout_with_colors(m_gdkwindow, m_textGC, x, y, m_layout, NULL, bg_col);
 
-    CalcBoundingBox(x+minX, y+minY);
-    CalcBoundingBox(x+maxX, y+maxY);
+    pango_context_set_matrix(m_context, NULL);
+    if (setAttrs)
+        pango_layout_set_attributes(m_layout, NULL);
 }
 
 void wxWindowDCImpl::DoGetTextExtent(const wxString &string,
@@ -2067,7 +1989,7 @@ void wxWindowDCImpl::ComputeScaleAndOrigin()
 
     wxDCImpl::ComputeScaleAndOrigin();
 
-    // if scale has changed call SetPen to recalulate the line width
+    // if scale has changed call SetPen to recalculate the line width
     if ( wxRealPoint(m_scaleX, m_scaleY) != origScale && m_pen.IsOk() )
     {
         // this is a bit artificial, but we need to force wxDC to think the pen