X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8f48176bbfdf0216130e45c8aacb235c596b9629..76b0f8384ed211c5f6b48597a62da743b604e666:/src/gtk/dcclient.cpp?ds=sidebyside diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index c59d7642a7..a11615391e 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -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); @@ -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,