X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ea3a345f1cfb510f49a3aca5d8fb38a0a3edde3d..ae3b14872bca4ee65d1adf3c6d75ef66c5438aac:/src/gtk/dcclient.cpp diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index 656136d385..7c647971b0 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -28,6 +28,7 @@ #include "wx/fontutil.h" #include "wx/gtk/private.h" +#include "wx/gtk/private/object.h" #include @@ -53,7 +54,7 @@ #include "verti.xbm" #include "cross.xbm" -static GdkPixmap* hatches[wxLAST_HATCH - wxFIRST_HATCH + 1]; +static GdkPixmap* hatches[wxBRUSHSTYLE_LAST_HATCH - wxBRUSHSTYLE_FIRST_HATCH + 1]; extern GtkWidget *wxGetRootWindow(); @@ -74,28 +75,28 @@ static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } static GdkPixmap* GetHatch(int style) { - wxASSERT(style >= wxFIRST_HATCH && style <= wxLAST_HATCH); - const int i = style - wxFIRST_HATCH; + wxASSERT(style >= wxBRUSHSTYLE_FIRST_HATCH && style <= wxBRUSHSTYLE_LAST_HATCH); + const int i = style - wxBRUSHSTYLE_FIRST_HATCH; if (hatches[i] == NULL) { switch (style) { - case wxBDIAGONAL_HATCH: + case wxBRUSHSTYLE_BDIAGONAL_HATCH: hatches[i] = gdk_bitmap_create_from_data(NULL, bdiag_bits, bdiag_width, bdiag_height); break; - case wxCROSSDIAG_HATCH: + case wxBRUSHSTYLE_CROSSDIAG_HATCH: hatches[i] = gdk_bitmap_create_from_data(NULL, cdiag_bits, cdiag_width, cdiag_height); break; - case wxCROSS_HATCH: + case wxBRUSHSTYLE_CROSS_HATCH: hatches[i] = gdk_bitmap_create_from_data(NULL, cross_bits, cross_width, cross_height); break; - case wxFDIAGONAL_HATCH: + case wxBRUSHSTYLE_FDIAGONAL_HATCH: hatches[i] = gdk_bitmap_create_from_data(NULL, fdiag_bits, fdiag_width, fdiag_height); break; - case wxHORIZONTAL_HATCH: + case wxBRUSHSTYLE_HORIZONTAL_HATCH: hatches[i] = gdk_bitmap_create_from_data(NULL, horiz_bits, horiz_width, horiz_height); break; - case wxVERTICAL_HATCH: + case wxBRUSHSTYLE_VERTICAL_HATCH: hatches[i] = gdk_bitmap_create_from_data(NULL, verti_bits, verti_width, verti_height); break; } @@ -502,8 +503,8 @@ bool wxWindowDCImpl::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const void wxWindowDCImpl::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) { wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - - if (m_pen.GetStyle() != wxTRANSPARENT) + + if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) { if (m_gdkwindow) gdk_draw_line( m_gdkwindow, m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) ); @@ -517,7 +518,7 @@ void wxWindowDCImpl::DoCrossHair( wxCoord x, wxCoord y ) { wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - if (m_pen.GetStyle() != wxTRANSPARENT) + if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) { int w = 0; int h = 0; @@ -538,12 +539,12 @@ void wxWindowDCImpl::DrawingSetup(GdkGC*& gc, bool& originChanged) GdkPixmap* pixmap = NULL; const int style = m_brush.GetStyle(); - if (style == wxSTIPPLE || style == wxSTIPPLE_MASK_OPAQUE) + if (style == wxBRUSHSTYLE_STIPPLE || style == wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE) { const wxBitmap* stipple = m_brush.GetStipple(); if (stipple->IsOk()) { - if (style == wxSTIPPLE) + if (style == wxBRUSHSTYLE_STIPPLE) pixmap = stipple->GetPixmap(); else if (stipple->GetMask()) { @@ -615,7 +616,7 @@ void wxWindowDCImpl::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, if (m_gdkwindow) { - if (m_brush.GetStyle() != wxTRANSPARENT) + if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT) { GdkGC* gc; bool originChanged; @@ -627,11 +628,11 @@ void wxWindowDCImpl::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, gdk_gc_set_ts_origin(gc, 0, 0); } - if (m_pen.GetStyle() != wxTRANSPARENT) + if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) { gdk_draw_arc( m_gdkwindow, m_penGC, FALSE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); - if ((m_brush.GetStyle() != wxTRANSPARENT) && (alpha2 - alpha1 != 360*64)) + if ((m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT) && (alpha2 - alpha1 != 360*64)) { gdk_draw_line( m_gdkwindow, m_penGC, xx1, yy1, xxc, yyc ); gdk_draw_line( m_gdkwindow, m_penGC, xxc, yyc, xx2, yy2 ); @@ -661,7 +662,7 @@ void wxWindowDCImpl::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxC wxCoord start = wxCoord(sa * 64.0); wxCoord end = wxCoord((ea-sa) * 64.0); - if (m_brush.GetStyle() != wxTRANSPARENT) + if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT) { GdkGC* gc; bool originChanged; @@ -673,7 +674,7 @@ void wxWindowDCImpl::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxC gdk_gc_set_ts_origin(gc, 0, 0); } - if (m_pen.GetStyle() != wxTRANSPARENT) + if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) gdk_draw_arc( m_gdkwindow, m_penGC, FALSE, xx, yy, ww, hh, start, end ); } @@ -685,7 +686,7 @@ void wxWindowDCImpl::DoDrawPoint( wxCoord x, wxCoord y ) { wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - if ((m_pen.GetStyle() != wxTRANSPARENT) && m_gdkwindow) + if ((m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) && m_gdkwindow) gdk_draw_point( m_gdkwindow, m_penGC, XLOG2DEV(x), YLOG2DEV(y) ); CalcBoundingBox (x, y); @@ -695,7 +696,7 @@ void wxWindowDCImpl::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCo { wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - if (m_pen.GetStyle() == wxTRANSPARENT) return; + if (m_pen.GetStyle() == wxPENSTYLE_TRANSPARENT) return; if (n <= 0) return; //Check, if scaling is necessary @@ -754,7 +755,7 @@ void wxWindowDCImpl::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wx if (m_gdkwindow) { - if (m_brush.GetStyle() != wxTRANSPARENT) + if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT) { GdkGC* gc; bool originChanged; @@ -766,7 +767,7 @@ void wxWindowDCImpl::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wx gdk_gc_set_ts_origin(gc, 0, 0); } - if (m_pen.GetStyle() != wxTRANSPARENT) + if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) { /* for (i = 0 ; i < n ; i++) @@ -805,7 +806,7 @@ void wxWindowDCImpl::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoo if (m_gdkwindow) { - if (m_brush.GetStyle() != wxTRANSPARENT) + if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT) { GdkGC* gc; bool originChanged; @@ -817,11 +818,11 @@ void wxWindowDCImpl::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoo gdk_gc_set_ts_origin(gc, 0, 0); } - if (m_pen.GetStyle() != wxTRANSPARENT) + if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) { #if 1 if ((m_pen.GetWidth() == 2) && (m_pen.GetCap() == wxCAP_ROUND) && - (m_pen.GetJoin() == wxJOIN_ROUND) && (m_pen.GetStyle() == wxSOLID)) + (m_pen.GetJoin() == wxJOIN_ROUND) && (m_pen.GetStyle() == wxPENSTYLE_SOLID)) { // Use 2 1-line rects instead gdk_gc_set_line_attributes( m_penGC, 1, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND ); @@ -883,7 +884,7 @@ void wxWindowDCImpl::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width // CMB: adjust size if outline is drawn otherwise the result is // 1 pixel too wide and high - if (m_pen.GetStyle() != wxTRANSPARENT) + if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) { ww--; hh--; @@ -898,7 +899,7 @@ void wxWindowDCImpl::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width if (dd > hh) dd = hh; rr = dd / 2; - if (m_brush.GetStyle() != wxTRANSPARENT) + if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT) { GdkGC* gc; bool originChanged; @@ -915,7 +916,7 @@ void wxWindowDCImpl::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width gdk_gc_set_ts_origin(gc, 0, 0); } - if (m_pen.GetStyle() != wxTRANSPARENT) + if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) { gdk_draw_line( m_gdkwindow, m_penGC, xx+rr+1, yy, xx+ww-rr, yy ); gdk_draw_line( m_gdkwindow, m_penGC, xx+rr+1, yy+hh, xx+ww-rr, yy+hh ); @@ -948,20 +949,28 @@ void wxWindowDCImpl::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord if (m_gdkwindow) { - if (m_brush.GetStyle() != wxTRANSPARENT) + if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT) { GdkGC* gc; bool originChanged; DrawingSetup(gc, originChanged); + // If the pen is transparent pen we increase the size + // for better compatibility with other platforms. + if (m_pen.GetStyle() == wxPENSTYLE_TRANSPARENT) + { + ++ww; + ++hh; + } + gdk_draw_arc(m_gdkwindow, gc, true, xx, yy, ww, hh, 0, 360*64); if (originChanged) gdk_gc_set_ts_origin(gc, 0, 0); } - if (m_pen.GetStyle() != wxTRANSPARENT) - gdk_draw_arc( m_gdkwindow, m_penGC, FALSE, xx, yy, ww, hh, 0, 360*64 ); + if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) + gdk_draw_arc( m_gdkwindow, m_penGC, false, xx, yy, ww, hh, 0, 360*64 ); } CalcBoundingBox( x, y ); @@ -974,6 +983,76 @@ void wxWindowDCImpl::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y ) DoDrawBitmap( (const wxBitmap&)icon, x, y, true ); } +// compare to current clipping region +bool wxWindowDCImpl::IsOutsideOfClippingRegion(int x, int y, int w, int h) +{ + if (m_currentClippingRegion.IsNull()) + return false; + + wxRegion region(x, y, w, h); + region.Intersect( m_currentClippingRegion ); + return region.IsEmpty(); +} + +void wxWindowDCImpl::RemoveClipMask(GdkGC *gc) +{ + gdk_gc_set_clip_mask(gc, NULL); + gdk_gc_set_clip_origin(gc, 0, 0); + if (!m_currentClippingRegion.IsNull()) + gdk_gc_set_clip_region(gc, m_currentClippingRegion.GetRegion()); +} + +// For drawing a mono-bitmap (XBitmap) we use the current text GC +void wxWindowDCImpl::DoDrawMonoBitmap(const wxBitmap& bitmap, + int bmp_w, int bmp_h, + int xsrc, int ysrc, + int xdest, int ydest, + int width, int height) +{ + wxGtkObject + bitmap2(gdk_pixmap_new( wxGetRootWindow()->window, bmp_w, bmp_h, -1 )); + wxGtkObject gc(gdk_gc_new( bitmap2 )); + gdk_gc_set_foreground( gc, m_textForegroundColour.GetColor() ); + gdk_gc_set_background( gc, m_textBackgroundColour.GetColor() ); + gdk_wx_draw_bitmap(bitmap2, gc, bitmap.GetPixmap(), 0, 0); + + gdk_draw_drawable(m_gdkwindow, m_textGC, bitmap2, xsrc, ysrc, xdest, ydest, + width, height); +} + +// Returns a new mask that is the intersection of the old mask +// and m_currentClippingRegion with proper offsets +GdkBitmap* wxWindowDCImpl::GetClippedMask(GdkBitmap* mask, int w, int h, + int x, int y, + int xsrcMask, int ysrcMask) +{ + // create monochrome bitmap that will be used as the new mask + GdkBitmap *new_mask = gdk_pixmap_new( wxGetRootWindow()->window, w, h, 1 ); + + GdkColor c0, c1; + c0.pixel = 0; + c1.pixel = 1; + wxGtkObject gc(gdk_gc_new( new_mask )); + + // zero-ing new_mask + gdk_gc_set_foreground( gc, &c0 ); + gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, w, h ); + + // clipping region + gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() ); + gdk_gc_set_clip_origin( gc, -x, -y ); + + // copy the old mask to the new_mask in the clip region area + gdk_gc_set_background( gc, &c0 ); + gdk_gc_set_foreground( gc, &c1 ); + gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED ); + gdk_gc_set_ts_origin( gc, -xsrcMask, -ysrcMask ); + gdk_gc_set_stipple( gc, mask ); + gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, w, h ); + + return new_mask; +} + void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap, wxCoord x, wxCoord y, bool useMask ) @@ -1002,70 +1081,40 @@ void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap, int ww = XLOG2DEVREL(w); int hh = YLOG2DEVREL(h); - // compare to current clipping region - if (!m_currentClippingRegion.IsNull()) - { - wxRegion tmp( xx,yy,ww,hh ); - tmp.Intersect( m_currentClippingRegion ); - if (tmp.IsEmpty()) - return; - } + if (IsOutsideOfClippingRegion( xx,yy,ww,hh )) + return; // scale bitmap if required wxBitmap use_bitmap = bitmap; if ((w != ww) || (h != hh)) - use_bitmap = use_bitmap.Rescale( 0, 0, ww, hh, ww, hh ); + use_bitmap = use_bitmap.Rescale( 0, 0, w, h, ww, hh ); - // apply mask if any + // get mask if any GdkBitmap *mask = (GdkBitmap *) NULL; if (useMask && use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); + // for drawing a mono-bitmap we use the current text GC GdkGC* use_gc = is_mono ? m_textGC : m_penGC; - GdkBitmap *new_mask = (GdkBitmap*) NULL; + bool mask_owned = false; if (mask != NULL) { if (!m_currentClippingRegion.IsNull()) { - GdkColor col; - new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 ); - GdkGC *gc = gdk_gc_new( new_mask ); - col.pixel = 0; - gdk_gc_set_foreground( gc, &col ); - gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh ); - col.pixel = 0; - gdk_gc_set_background( gc, &col ); - col.pixel = 1; - gdk_gc_set_foreground( gc, &col ); - gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_origin( gc, -xx, -yy ); - gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED ); - gdk_gc_set_stipple( gc, mask ); - gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh ); - mask = new_mask; - g_object_unref (gc); + mask = GetClippedMask(mask, ww, hh, xx, yy, 0, 0); + mask_owned = true; } gdk_gc_set_clip_mask(use_gc, mask); gdk_gc_set_clip_origin(use_gc, xx, yy); } - // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For - // drawing a mono-bitmap (XBitmap) we use the current text GC + // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. if (is_mono) { - GdkPixmap *bitmap2 = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, -1 ); - GdkGC *gc = gdk_gc_new( bitmap2 ); - gdk_gc_set_foreground( gc, m_textForegroundColour.GetColor() ); - gdk_gc_set_background( gc, m_textBackgroundColour.GetColor() ); - gdk_wx_draw_bitmap(bitmap2, gc, use_bitmap.GetPixmap(), 0, 0); - - gdk_draw_drawable(m_gdkwindow, use_gc, bitmap2, 0, 0, xx, yy, -1, -1); - - g_object_unref (bitmap2); - g_object_unref (gc); + DoDrawMonoBitmap(use_bitmap, ww, hh, 0, 0, xx, yy, -1, -1); } else { @@ -1087,12 +1136,9 @@ void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap, // remove mask again if any if (mask != NULL) { - gdk_gc_set_clip_mask(use_gc, NULL); - gdk_gc_set_clip_origin(use_gc, 0, 0); - if (!m_currentClippingRegion.IsNull()) - gdk_gc_set_clip_region(use_gc, m_currentClippingRegion.GetRegion()); - if (new_mask != NULL) - g_object_unref(new_mask); + RemoveClipMask(use_gc); + if (mask_owned) + g_object_unref(mask); } } @@ -1179,13 +1225,8 @@ bool wxWindowDCImpl::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord hh = YLOG2DEVREL(height); // compare to current clipping region - if (!m_currentClippingRegion.IsNull()) - { - wxRegion tmp( xx,yy,ww,hh ); - tmp.Intersect( m_currentClippingRegion ); - if (tmp.IsEmpty()) - return true; - } + if (IsOutsideOfClippingRegion( xx,yy,ww,hh )) + return true; int old_logical_func = m_logicalFunction; SetLogicalFunction( logical_func ); @@ -1237,55 +1278,29 @@ bool wxWindowDCImpl::DoBlit( wxCoord xdest, wxCoord ydest, GdkGC* use_gc = is_mono ? m_textGC : m_penGC; - GdkBitmap *new_mask = (GdkBitmap*) NULL; + bool mask_owned = false; if (mask != NULL) { if (!m_currentClippingRegion.IsNull()) { - GdkColor col; - new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 ); - GdkGC *gc = gdk_gc_new( new_mask ); - col.pixel = 0; - gdk_gc_set_foreground( gc, &col ); - gdk_gc_set_ts_origin( gc, -xsrcMask, -ysrcMask); - gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); - col.pixel = 0; - gdk_gc_set_background( gc, &col ); - col.pixel = 1; - gdk_gc_set_foreground( gc, &col ); - gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() ); - // was: gdk_gc_set_clip_origin( gc, -xx, -yy ); - gdk_gc_set_clip_origin( gc, -cx, -cy ); - gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED ); - gdk_gc_set_stipple( gc, mask ); - gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); - mask = new_mask; - g_object_unref (gc); + mask = GetClippedMask(mask, bm_ww, bm_hh, cx, cy, + xsrcMask, ysrcMask); + mask_owned = true; } gdk_gc_set_clip_mask(use_gc, mask); - if (new_mask != NULL) + if (mask_owned) gdk_gc_set_clip_origin(use_gc, cx, cy); else gdk_gc_set_clip_origin(use_gc, cx - xsrcMask, cy - ysrcMask); } - // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For - // drawing a mono-bitmap (XBitmap) we use the current text GC - + // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. if (is_mono) { - GdkPixmap *bitmap = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, -1 ); - GdkGC *gc = gdk_gc_new( bitmap ); - gdk_gc_set_foreground( gc, m_textForegroundColour.GetColor() ); - gdk_gc_set_background( gc, m_textBackgroundColour.GetColor() ); - gdk_wx_draw_bitmap(bitmap, gc, use_bitmap.GetPixmap(), 0, 0); - - gdk_draw_drawable(m_gdkwindow, use_gc, bitmap, xsrc, ysrc, cx, cy, cw, ch); - - g_object_unref (bitmap); - g_object_unref (gc); + DoDrawMonoBitmap(use_bitmap, bm_ww, bm_hh, + xsrc, ysrc, cx, cy, cw, ch); } else { @@ -1296,31 +1311,18 @@ bool wxWindowDCImpl::DoBlit( wxCoord xdest, wxCoord ydest, // remove mask again if any if (mask != NULL) { - gdk_gc_set_clip_mask(use_gc, NULL); - gdk_gc_set_clip_origin(use_gc, 0, 0); - if (!m_currentClippingRegion.IsNull()) - gdk_gc_set_clip_region(use_gc, m_currentClippingRegion.GetRegion()); + RemoveClipMask(use_gc); + if (mask_owned) + g_object_unref (mask); } - - if (new_mask) - g_object_unref (new_mask); } else // use_bitmap_method { if (selected.IsOk() && ((width != ww) || (height != hh))) { - // get clip coords - wxRegion tmp( xx,yy,ww,hh ); - tmp.Intersect( m_currentClippingRegion ); - wxCoord cx,cy,cw,ch; - tmp.GetBox(cx,cy,cw,ch); - - // rescale bitmap - wxBitmap bitmap = selected.Rescale( cx-xx, cy-yy, cw, ch, ww, hh ); - + wxBitmap bitmap = selected.Rescale( xsrc, ysrc, width, height, ww, hh ); // draw scaled bitmap - // was: gdk_draw_drawable( m_gdkwindow, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); - gdk_draw_drawable( m_gdkwindow, m_penGC, bitmap.GetPixmap(), 0, 0, cx, cy, -1, -1 ); + gdk_draw_drawable( m_gdkwindow, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); } else { @@ -1366,7 +1368,7 @@ void wxWindowDCImpl::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") ); - gdk_pango_context_set_colormap( m_context, m_cmap ); + gdk_pango_context_set_colormap( m_context, m_cmap ); // not needed in gtk+ >= 2.6 bool underlined = m_font.IsOk() && m_font.GetUnderlined(); @@ -1436,31 +1438,30 @@ void wxWindowDCImpl::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) 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. + // If there is a user or actually any scale applied to + // the device context, scale the font. - // scale font description + // 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 ); + // 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); - if (m_backgroundMode == wxSOLID) - { - gdk_gc_set_foreground(m_textGC, m_textBackgroundColour.GetColor()); - gdk_draw_rectangle(m_gdkwindow, m_textGC, true, x, y, w, h); - gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); - } // Draw layout. int x_rtl = x; if (m_window && m_window->GetLayoutDirection() == wxLayout_RightToLeft) x_rtl -= w; - gdk_draw_layout(m_gdkwindow, m_textGC, x_rtl, y, m_layout); + + 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) { @@ -1480,19 +1481,106 @@ void wxWindowDCImpl::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) CalcBoundingBox(x, y); } - -// TODO: There is an example of rotating text with GTK2 that would probably be -// a better approach here: -// http://www.daa.com.au/pipermail/pygtk/2003-April/005052.html - +// 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 ) { -#if wxUSE_IMAGE if (!m_gdkwindow || text.empty()) return; wxCHECK_RET( IsOk(), wxT("invalid window dc") ); +#if __WXGTK26__ + if (!gtk_check_version(2,6,0)) + { + x = XLOG2DEV(x); + y = YLOG2DEV(y); + + pango_layout_set_text(m_layout, wxGTK_CONV(text), -1); + + if (m_font.GetUnderlined()) + { + PangoAttrList *attrs = pango_attr_list_new(); + PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); + pango_attr_list_insert(attrs, a); + pango_layout_set_attributes(m_layout, attrs); + pango_attr_list_unref(attrs); + } + + 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 (m_font.GetUnderlined()) + pango_layout_set_attributes(m_layout, NULL); + + // clean up the transformation matrix + pango_context_set_matrix(m_context, NULL); + + 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 ); + } + + CalcBoundingBox(x+minX, y+minY); + CalcBoundingBox(x+maxX, y+maxY); + } + else +#endif //__WXGTK26__ + { +#if wxUSE_IMAGE if ( wxIsNullDouble(angle) ) { DoDrawText(text, x, y); @@ -1592,6 +1680,7 @@ void wxWindowDCImpl::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord wxUnusedVar(y); wxUnusedVar(angle); #endif // wxUSE_IMAGE/!wxUSE_IMAGE + } } void wxWindowDCImpl::DoGetTextExtent(const wxString &string, @@ -1613,7 +1702,7 @@ void wxWindowDCImpl::DoGetTextExtent(const wxString &string, // ensure that theFont is always non-NULL if ( !theFont || !theFont->IsOk() ) - theFont = wx_const_cast(wxFont *, &m_font); + theFont = &m_font; // and use it if it's valid if ( theFont->IsOk() ) @@ -1633,24 +1722,19 @@ void wxWindowDCImpl::DoGetTextExtent(const wxString &string, return; } - pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) ); + pango_layout_set_text(m_layout, dataUTF8, -1); + int h; + pango_layout_get_pixel_size(m_layout, width, &h); if (descent) { - int h; - pango_layout_get_pixel_size( m_layout, width, &h ); 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 (height) - *height = (wxCoord) h; - } - else - { - pango_layout_get_pixel_size( m_layout, width, height ); } + if (height) + *height = h; // Reset old font description if (theFont->IsOk()) @@ -1677,7 +1761,7 @@ bool wxWindowDCImpl::DoGetPartialTextExtents(const wxString& text, return false; } - pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) ); + pango_layout_set_text(m_layout, dataUTF8, -1); // Calculate the position of each character based on the widths of // the previous characters @@ -1809,57 +1893,39 @@ void wxWindowDCImpl::SetPen( const wxPen &pen ) int req_nb_dash; const wxGTKDash *req_dash; - GdkLineStyle lineStyle = GDK_LINE_SOLID; + GdkLineStyle lineStyle = GDK_LINE_ON_OFF_DASH; switch (m_pen.GetStyle()) { - case wxUSER_DASH: - { - lineStyle = GDK_LINE_ON_OFF_DASH; + case wxPENSTYLE_USER_DASH: req_nb_dash = m_pen.GetDashCount(); req_dash = (wxGTKDash*)m_pen.GetDash(); break; - } - case wxDOT: - { - lineStyle = GDK_LINE_ON_OFF_DASH; + case wxPENSTYLE_DOT: req_nb_dash = 2; req_dash = dotted; break; - } - case wxLONG_DASH: - { - lineStyle = GDK_LINE_ON_OFF_DASH; + case wxPENSTYLE_LONG_DASH: req_nb_dash = 2; req_dash = wxCoord_dashed; break; - } - case wxSHORT_DASH: - { - lineStyle = GDK_LINE_ON_OFF_DASH; + case wxPENSTYLE_SHORT_DASH: req_nb_dash = 2; req_dash = short_dashed; break; - } - case wxDOT_DASH: - { -// lineStyle = GDK_LINE_DOUBLE_DASH; - lineStyle = GDK_LINE_ON_OFF_DASH; + case wxPENSTYLE_DOT_DASH: req_nb_dash = 4; req_dash = dotted_dashed; break; - } - case wxTRANSPARENT: - case wxSTIPPLE_MASK_OPAQUE: - case wxSTIPPLE: - case wxSOLID: + case wxPENSTYLE_TRANSPARENT: + case wxPENSTYLE_STIPPLE_MASK_OPAQUE: + case wxPENSTYLE_STIPPLE: + case wxPENSTYLE_SOLID: default: - { lineStyle = GDK_LINE_SOLID; req_dash = (wxGTKDash*)NULL; req_nb_dash = 0; break; - } } if (req_dash && req_nb_dash) @@ -1886,18 +1952,12 @@ void wxWindowDCImpl::SetPen( const wxPen &pen ) case wxCAP_BUTT: { capStyle = GDK_CAP_BUTT; break; } case wxCAP_ROUND: default: - { if (width <= 1) { width = 0; capStyle = GDK_CAP_NOT_LAST; } - else - { - capStyle = GDK_CAP_ROUND; - } break; - } } GdkJoinStyle joinStyle = GDK_JOIN_ROUND; @@ -1932,7 +1992,7 @@ void wxWindowDCImpl::SetBrush( const wxBrush &brush ) gdk_gc_set_fill( m_brushGC, GDK_SOLID ); - if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->IsOk())) + if ((m_brush.GetStyle() == wxBRUSHSTYLE_STIPPLE) && (m_brush.GetStipple()->IsOk())) { if (m_brush.GetStipple()->GetDepth() != 1) { @@ -1946,7 +2006,7 @@ void wxWindowDCImpl::SetBrush( const wxBrush &brush ) } } - if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + if ((m_brush.GetStyle() == wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) { gdk_gc_set_fill( m_textGC, GDK_OPAQUE_STIPPLED); gdk_gc_set_stipple( m_textGC, m_brush.GetStipple()->GetMask()->GetBitmap() ); @@ -1974,29 +2034,35 @@ void wxWindowDCImpl::SetBackground( const wxBrush &brush ) if (!m_gdkwindow) return; - m_backgroundBrush.GetColour().CalcPixel( m_cmap ); - gdk_gc_set_background( m_brushGC, m_backgroundBrush.GetColour().GetColor() ); - gdk_gc_set_background( m_penGC, m_backgroundBrush.GetColour().GetColor() ); - gdk_gc_set_background( m_bgGC, m_backgroundBrush.GetColour().GetColor() ); - gdk_gc_set_foreground( m_bgGC, m_backgroundBrush.GetColour().GetColor() ); + wxColor color = m_backgroundBrush.GetColour(); + color.CalcPixel(m_cmap); + const GdkColor* gdkColor = color.GetColor(); + gdk_gc_set_background(m_brushGC, gdkColor); + gdk_gc_set_background(m_penGC, gdkColor); + gdk_gc_set_background(m_bgGC, gdkColor); + gdk_gc_set_foreground(m_bgGC, gdkColor); + gdk_gc_set_fill( m_bgGC, GDK_SOLID ); - if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->IsOk())) + if (m_backgroundBrush.GetStyle() == wxBRUSHSTYLE_STIPPLE) { - if (m_backgroundBrush.GetStipple()->GetDepth() != 1) - { - gdk_gc_set_fill( m_bgGC, GDK_TILED ); - gdk_gc_set_tile( m_bgGC, m_backgroundBrush.GetStipple()->GetPixmap() ); - } - else + const wxBitmap* stipple = m_backgroundBrush.GetStipple(); + if (stipple->IsOk()) { - gdk_gc_set_fill( m_bgGC, GDK_STIPPLED ); - gdk_gc_set_stipple( m_bgGC, m_backgroundBrush.GetStipple()->GetPixmap() ); + if (stipple->GetDepth() != 1) + { + gdk_gc_set_fill(m_bgGC, GDK_TILED); + gdk_gc_set_tile(m_bgGC, stipple->GetPixmap()); + } + else + { + gdk_gc_set_fill(m_bgGC, GDK_STIPPLED); + gdk_gc_set_stipple(m_bgGC, stipple->GetPixmap()); + } } } - - if (m_backgroundBrush.IsHatch()) + else if (m_backgroundBrush.IsHatch()) { gdk_gc_set_fill( m_bgGC, GDK_STIPPLED ); gdk_gc_set_stipple(m_bgGC, GetHatch(m_backgroundBrush.GetStyle())); @@ -2032,9 +2098,7 @@ void wxWindowDCImpl::SetLogicalFunction( int function ) case wxCOPY: mode = GDK_COPY; break; case wxNO_OP: mode = GDK_NOOP; break; case wxSRC_INVERT: mode = GDK_COPY_INVERT; break; - - // unsupported by GTK - case wxNOR: mode = GDK_COPY; break; + case wxNOR: mode = GDK_NOR; break; default: wxFAIL_MSG( wxT("unsupported logical function") ); mode = GDK_COPY; @@ -2092,17 +2156,6 @@ void wxWindowDCImpl::SetBackgroundMode( int mode ) wxCHECK_RET( IsOk(), wxT("invalid window dc") ); m_backgroundMode = mode; - - if (!m_gdkwindow) return; - - // CMB 21/7/98: fill style of cross-hatch brushes is affected by - // transparent/solid background mode - - if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT) - { - gdk_gc_set_fill( m_brushGC, - (m_backgroundMode == wxTRANSPARENT) ? GDK_STIPPLED : GDK_OPAQUE_STIPPLED); - } } void wxWindowDCImpl::SetPalette( const wxPalette& WXUNUSED(palette) ) @@ -2128,31 +2181,10 @@ void wxWindowDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, w rect.x -= rect.width; } - if (!m_currentClippingRegion.IsNull()) - m_currentClippingRegion.Intersect( rect ); - else - m_currentClippingRegion.Union( rect ); - -#if USE_PAINT_REGION - if (!m_paintClippingRegion.IsNull()) - m_currentClippingRegion.Intersect( m_paintClippingRegion ); -#endif - - wxCoord xx, yy, ww, hh; - m_currentClippingRegion.GetBox( xx, yy, ww, hh ); -#if wxUSE_NEW_DC - wxGTKDCImpl::DoSetClippingRegion( xx, yy, ww, hh ); -#else - wxDC::DoSetClippingRegion( xx, yy, ww, hh ); -#endif - - gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_region( m_brushGC, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_region( m_bgGC, m_currentClippingRegion.GetRegion() ); + DoSetDeviceClippingRegion(wxRegion(rect)); } -void wxWindowDCImpl::DoSetClippingRegionAsRegion( const wxRegion ®ion ) +void wxWindowDCImpl::DoSetDeviceClippingRegion( const wxRegion ®ion ) { wxCHECK_RET( IsOk(), wxT("invalid window dc") ); @@ -2176,27 +2208,20 @@ void wxWindowDCImpl::DoSetClippingRegionAsRegion( const wxRegion ®ion ) wxCoord xx, yy, ww, hh; m_currentClippingRegion.GetBox( xx, yy, ww, hh ); -#if wxUSE_NEW_DC wxGTKDCImpl::DoSetClippingRegion( xx, yy, ww, hh ); -#else - wxDC::DoSetClippingRegion( xx, yy, ww, hh ); -#endif - gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_region( m_brushGC, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_region( m_bgGC, m_currentClippingRegion.GetRegion() ); + GdkRegion* gdkRegion = m_currentClippingRegion.GetRegion(); + gdk_gc_set_clip_region(m_penGC, gdkRegion); + gdk_gc_set_clip_region(m_brushGC, gdkRegion); + gdk_gc_set_clip_region(m_textGC, gdkRegion); + gdk_gc_set_clip_region(m_bgGC, gdkRegion); } void wxWindowDCImpl::DestroyClippingRegion() { wxCHECK_RET( IsOk(), wxT("invalid window dc") ); -#if wxUSE_NEW_DC wxDCImpl::DestroyClippingRegion(); -#else - wxDC::DestroyClippingRegion(); -#endif m_currentClippingRegion.Clear(); @@ -2207,20 +2232,14 @@ void wxWindowDCImpl::DestroyClippingRegion() if (!m_gdkwindow) return; - if (m_currentClippingRegion.IsEmpty()) - { - gdk_gc_set_clip_rectangle( m_penGC, (GdkRectangle *) NULL ); - gdk_gc_set_clip_rectangle( m_brushGC, (GdkRectangle *) NULL ); - gdk_gc_set_clip_rectangle( m_textGC, (GdkRectangle *) NULL ); - gdk_gc_set_clip_rectangle( m_bgGC, (GdkRectangle *) NULL ); - } - else - { - gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_region( m_brushGC, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() ); - gdk_gc_set_clip_region( m_bgGC, m_currentClippingRegion.GetRegion() ); - } + GdkRegion* gdkRegion = NULL; + if (!m_currentClippingRegion.IsEmpty()) + gdkRegion = m_currentClippingRegion.GetRegion(); + + gdk_gc_set_clip_region(m_penGC, gdkRegion); + gdk_gc_set_clip_region(m_brushGC, gdkRegion); + gdk_gc_set_clip_region(m_textGC, gdkRegion); + gdk_gc_set_clip_region(m_bgGC, gdkRegion); } void wxWindowDCImpl::Destroy() @@ -2259,11 +2278,7 @@ void wxWindowDCImpl::ComputeScaleAndOrigin() { const wxRealPoint origScale(m_scaleX, m_scaleY); -#if wxUSE_NEW_DC wxDCImpl::ComputeScaleAndOrigin(); -#else - wxDC::ComputeScaleAndOrigin(); -#endif // if scale has changed call SetPen to recalulate the line width if ( wxRealPoint(m_scaleX, m_scaleY) != origScale && m_pen.IsOk() ) @@ -2404,7 +2419,7 @@ void wxDCModule::OnExit() { wxCleanUpGCPool(); - for (int i = wxLAST_HATCH - wxFIRST_HATCH; i--; ) + for (int i = wxBRUSHSTYLE_LAST_HATCH - wxBRUSHSTYLE_FIRST_HATCH; i--; ) { if (hatches[i]) g_object_unref(hatches[i]);