X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d90c9596c1476f4bb1c728dc0169ef16f4d622d4..ca86035f16f071d3f6b987bbac9fab174c6079c4:/src/gtk1/dcclient.cpp diff --git a/src/gtk1/dcclient.cpp b/src/gtk1/dcclient.cpp index 802358014e..c344069423 100644 --- a/src/gtk1/dcclient.cpp +++ b/src/gtk1/dcclient.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: gtk/dcclient.cpp +// Name: src/gtk1/dcclient.cpp // Purpose: // Author: Robert Roebling // RCS-ID: $Id$ @@ -7,10 +7,6 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "dcclient.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -19,15 +15,18 @@ #endif #include "wx/dcclient.h" -#include "wx/dcmemory.h" -#include "wx/image.h" -#include "wx/module.h" -#include "wx/log.h" -#include "wx/fontutil.h" -#include "wx/gtk/win_gtk.h" +#ifndef WX_PRECOMP + #include "wx/log.h" + #include "wx/dcmemory.h" + #include "wx/math.h" // for floating-point functions + #include "wx/image.h" + #include "wx/module.h" +#endif -#include // for floating-point functions +#include "wx/fontutil.h" + +#include "wx/gtk1/win_gtk.h" #include #include @@ -92,29 +91,14 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable, gint width, gint height) { - g_return_if_fail (drawable != NULL); - g_return_if_fail (src != NULL); - g_return_if_fail (gc != NULL); - -#ifdef __WXGTK20__ - gint src_width, src_height; - gdk_drawable_get_size(src, &src_width, &src_height); - if (width == -1) width = src_width; - if (height == -1) height = src_height; + wxCHECK_RET( drawable, _T("NULL drawable in gdk_wx_draw_bitmap") ); + wxCHECK_RET( src, _T("NULL src in gdk_wx_draw_bitmap") ); + wxCHECK_RET( gc, _T("NULL gc in gdk_wx_draw_bitmap") ); - XCopyPlane( GDK_WINDOW_XDISPLAY(drawable), - GDK_WINDOW_XID(src), - GDK_WINDOW_XID(drawable), - GDK_GC_XGC(gc), - xsrc, ysrc, - width, height, - 0, 0, - 1 ); -#else GdkWindowPrivate *drawable_private; GdkWindowPrivate *src_private; GdkGCPrivate *gc_private; - + drawable_private = (GdkWindowPrivate*) drawable; src_private = (GdkWindowPrivate*) src; if (drawable_private->destroyed || src_private->destroyed) @@ -124,10 +108,10 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable, gint src_height = src_private->height; gc_private = (GdkGCPrivate*) gc; - + if (width == -1) width = src_width; if (height == -1) height = src_height; - + XCopyPlane( drawable_private->xdisplay, src_private->xwindow, drawable_private->xwindow, @@ -136,15 +120,12 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable, width, height, xdest, ydest, 1 ); -#endif } //----------------------------------------------------------------------------- // Implement Pool of Graphic contexts. Creating them takes too much time. //----------------------------------------------------------------------------- -#define GC_POOL_SIZE 200 - enum wxPoolGCType { wxGC_ERROR = 0, @@ -180,10 +161,10 @@ static void wxInitGCPool() // This really could wait until the first call to // wxGetPoolGC, but we will make the first allocation // now when other initialization is being performed. - + // Set initial pool size. wxGCPoolSize = GC_POOL_ALLOC_SIZE; - + // Allocate initial pool. wxGCPool = (wxGC *)malloc(wxGCPoolSize * sizeof(wxGC)); if (wxGCPool == NULL) @@ -191,11 +172,11 @@ 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 - // in wxGetPoolGC. + // in wxGetPoolGC. wxFAIL_MSG( wxT("Cannot allocate GC pool") ); return; } - + // Zero initial pool. memset(wxGCPool, 0, wxGCPoolSize * sizeof(wxGC)); } @@ -216,7 +197,7 @@ static void wxCleanUpGCPool() static GdkGC* wxGetPoolGC( GdkWindow *window, wxPoolGCType type ) { wxGC *pptr; - + // Look for an available GC. for (int i = 0; i < wxGCPoolSize; i++) { @@ -225,11 +206,11 @@ static GdkGC* wxGetPoolGC( GdkWindow *window, wxPoolGCType type ) wxGCPool[i].m_gc = gdk_gc_new( window ); gdk_gc_set_exposures( wxGCPool[i].m_gc, FALSE ); wxGCPool[i].m_type = type; - wxGCPool[i].m_used = FALSE; + wxGCPool[i].m_used = false; } if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type)) { - wxGCPool[i].m_used = TRUE; + wxGCPool[i].m_used = true; return wxGCPool[i].m_gc; } } @@ -237,27 +218,27 @@ 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, - (wxGCPoolSize + GC_POOL_ALLOC_SIZE)*sizeof(wxGC)); + (wxGCPoolSize + GC_POOL_ALLOC_SIZE)*sizeof(wxGC)); if (pptr != NULL) { // Initialize newly allocated pool. wxGCPool = pptr; - memset(&wxGCPool[wxGCPoolSize], 0, - GC_POOL_ALLOC_SIZE*sizeof(wxGC)); - - // Initialize entry we will return. + memset(&wxGCPool[wxGCPoolSize], 0, + GC_POOL_ALLOC_SIZE*sizeof(wxGC)); + + // Initialize entry we will return. wxGCPool[wxGCPoolSize].m_gc = gdk_gc_new( window ); gdk_gc_set_exposures( wxGCPool[wxGCPoolSize].m_gc, FALSE ); wxGCPool[wxGCPoolSize].m_type = type; - wxGCPool[wxGCPoolSize].m_used = TRUE; - + wxGCPool[wxGCPoolSize].m_used = true; + // Set new value of pool size. wxGCPoolSize += GC_POOL_ALLOC_SIZE; - + // Return newly allocated entry. return wxGCPool[wxGCPoolSize-GC_POOL_ALLOC_SIZE].m_gc; } - + // The realloc failed. Fall through to error. wxFAIL_MSG( wxT("No GC available") ); @@ -270,7 +251,7 @@ static void wxFreePoolGC( GdkGC *gc ) { if (wxGCPool[i].m_gc == gc) { - wxGCPool[i].m_used = FALSE; + wxGCPool[i].m_used = false; return; } } @@ -291,14 +272,9 @@ wxWindowDC::wxWindowDC() m_textGC = (GdkGC *) NULL; m_bgGC = (GdkGC *) NULL; m_cmap = (GdkColormap *) NULL; - m_isMemDC = FALSE; - m_isScreenDC = FALSE; + m_isMemDC = false; + m_isScreenDC = false; m_owner = (wxWindow *)NULL; -#ifdef __WXGTK20__ - m_context = (PangoContext *)NULL; - m_layout = (PangoLayout *)NULL; - m_fontdesc = (PangoFontDescription *)NULL; -#endif } wxWindowDC::wxWindowDC( wxWindow *window ) @@ -311,8 +287,8 @@ wxWindowDC::wxWindowDC( wxWindow *window ) m_bgGC = (GdkGC *) NULL; m_cmap = (GdkColormap *) NULL; m_owner = (wxWindow *)NULL; - m_isMemDC = FALSE; - m_isScreenDC = FALSE; + m_isMemDC = false; + m_isScreenDC = false; m_font = window->GetFont(); GtkWidget *widget = window->m_wxwindow; @@ -328,12 +304,6 @@ wxWindowDC::wxWindowDC( wxWindow *window ) wxASSERT_MSG( widget, wxT("DC needs a widget") ); -#ifdef __WXGTK20__ - m_context = window->GtkGetPangoDefaultContext(); - m_layout = pango_layout_new( m_context ); - m_fontdesc = pango_font_description_copy( widget->style->font_desc ); -#endif - GtkPizza *pizza = GTK_PIZZA( widget ); m_window = pizza->bin_window; @@ -341,7 +311,7 @@ wxWindowDC::wxWindowDC( wxWindow *window ) if (!m_window) { // Don't report problems as per MSW. - m_ok = TRUE; + m_ok = true; return; } @@ -363,18 +333,11 @@ wxWindowDC::wxWindowDC( wxWindow *window ) wxWindowDC::~wxWindowDC() { Destroy(); - -#ifdef __WXGTK20__ - if (m_layout) - g_object_unref( G_OBJECT( m_layout ) ); - if (m_fontdesc) - pango_font_description_free( m_fontdesc ); -#endif } void wxWindowDC::SetUpDC() { - m_ok = TRUE; + m_ok = true; wxASSERT_MSG( !m_penGC, wxT("GCs already created") ); @@ -465,7 +428,7 @@ void wxWindowDC::DoGetSize( int* width, int* height ) const m_owner->GetSize(width, height); } -extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, +extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, const wxColour & col, int style); bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y, @@ -486,7 +449,7 @@ bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const wxImage image = bitmap.ConvertToImage(); col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0)); - return TRUE; + return true; } void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) @@ -544,10 +507,10 @@ void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, radius1 = 0.0; radius2 = 360.0; } - else - if (radius == 0.0) + else if ( wxIsNullDouble(radius) ) { - radius1 = radius2 = 0.0; + radius1 = + radius2 = 0.0; } else { @@ -693,14 +656,26 @@ void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord if (m_pen.GetStyle() == wxTRANSPARENT) return; if (n <= 0) return; - GdkPoint *gpts = new GdkPoint[n]; + //Check, if scaling is necessary + bool doScale(true); + long val(10); + if (!xoffset) + if (!yoffset) + if (XLOG2DEV(val)==val) + if (YLOG2DEV(val)==val) + doScale = false; + + GdkPoint *gpts = NULL; + + if (doScale){ + gpts = new GdkPoint[n]; if (! gpts) { wxFAIL_MSG( wxT("Cannot allocate PolyLine") ); return; } - for (int i = 0; i < n; i++) + for (int i = 0; i < n; i++) { wxCoord x1 = XLOG2DEV(points[i].x + xoffset); wxCoord y1 = YLOG2DEV(points[i].y + yoffset); @@ -710,10 +685,20 @@ void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord gpts[i].x = x1; gpts[i].y = y1; } + } + else { + for (int i = 0; i < n; i++) { + CalcBoundingBox( points[i].x, points[i].y ); + } + + //GdkPoint and wxPoint have the same memory allignment, so we can cast one into another + gpts = reinterpret_cast(points); + } if (m_window) gdk_draw_lines( m_window, m_penGC, gpts, n); + if (doScale) delete[] gpts; } @@ -723,7 +708,21 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoor if (n <= 0) return; - GdkPoint *gdkpoints = new GdkPoint[n+1]; + //Check, if scaling is necessary + bool doScale(true); + long val(10); + if (!xoffset) + if (!yoffset) + if (XLOG2DEV(val)==val) + if (YLOG2DEV(val)==val){ + doScale = false; + } + + GdkPoint *gdkpoints = NULL; + + if (doScale){ + gdkpoints = new GdkPoint[n+1]; //FIXME: Why the "+1" + int i; for (i = 0 ; i < n ; i++) { @@ -732,9 +731,24 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoor CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset ); } + } + else { + int i(0); + for (; i < n ; ++i) { + CalcBoundingBox( points[i].x, points[i].y ); + } + //GdkPoint and wxPoint have the same memory allignment, so we can cast one into another + gdkpoints = reinterpret_cast (points); + } if (m_window) { + //I think wxSOLID is the most often used style (it is for me), + //so I put it in front of the if ... ifelse's + if (m_brush.GetStyle() == wxSOLID) + { + gdk_draw_polygon( m_window, m_brushGC, TRUE, gdkpoints, n ); + }else if (m_brush.GetStyle() != wxTRANSPARENT) { if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) @@ -773,6 +787,7 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoor if (m_pen.GetStyle() != wxTRANSPARENT) { +/* for (i = 0 ; i < n ; i++) { gdk_draw_line( m_window, m_penGC, @@ -781,9 +796,13 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoor gdkpoints[(i+1)%n].x, gdkpoints[(i+1)%n].y); } +*/ + gdk_draw_polygon( m_window, m_penGC, FALSE, gdkpoints, n ); + } } + if (doScale) delete[] gdkpoints; } @@ -1034,7 +1053,7 @@ void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord hei void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y ) { // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why - DoDrawBitmap( (const wxBitmap&)icon, x, y, (bool)TRUE ); + DoDrawBitmap( (const wxBitmap&)icon, x, y, true ); } void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, @@ -1071,17 +1090,23 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, return; } - // scale bitmap if required + // scale bitmap if required wxBitmap use_bitmap = bitmap; if ((w != ww) || (h != hh)) use_bitmap = use_bitmap.Rescale( 0, 0, ww, hh, ww, hh ); - + + // NB: We can't render pixbufs with GTK+ < 2.2, we need to use pixmaps code. + // Pixbufs-based bitmaps with alpha channel don't have a mask, so we + // have to call GetPixmap() here -- it converts the pixbuf into pixmap + // and also creates the mask as a side-effect: + use_bitmap.GetPixmap(); + // apply mask if any GdkBitmap *mask = (GdkBitmap *) NULL; if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); GdkBitmap *new_mask = (GdkBitmap*) NULL; - + if (useMask && mask) { if (!m_currentClippingRegion.IsNull()) @@ -1103,7 +1128,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh ); gdk_gc_unref( gc ); } - + if (is_mono) { if (new_mask) @@ -1126,24 +1151,13 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, // drawing a mono-bitmap (XBitmap) we use the current text GC if (is_mono) { -#ifdef __WXGTK20__ - GdkPixmap *bitmap = gdk_pixmap_new( wxGetRootWindow()->window, ww, 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.GetBitmap(), 0, 0, 0, 0, -1, -1 ); - - gdk_draw_drawable( m_window, m_textGC, bitmap, 0, 0, xx, yy, -1, -1 ); - - gdk_bitmap_unref( bitmap ); - gdk_gc_unref( gc ); -#else gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), 0, 0, xx, yy, -1, -1 ); -#endif } else { - gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); + gdk_draw_pixmap(m_window, m_penGC, + use_bitmap.GetPixmap(), + 0, 0, xx, yy, -1, -1); } // remove mask again if any @@ -1164,7 +1178,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); } } - + if (new_mask) gdk_bitmap_unref( new_mask ); } @@ -1177,11 +1191,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, bool useMask, wxCoord xsrcMask, wxCoord ysrcMask ) { - wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") ); + wxCHECK_MSG( Ok(), false, wxT("invalid window dc") ); - wxCHECK_MSG( source, FALSE, wxT("invalid source dc") ); + wxCHECK_MSG( source, false, wxT("invalid source dc") ); - if (!m_window) return FALSE; + if (!m_window) return false; // transform the source DC coords to the device ones xsrc = source->XLOG2DEV(xsrc); @@ -1190,10 +1204,9 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxClientDC *srcDC = (wxClientDC*)source; wxMemoryDC *memDC = (wxMemoryDC*)source; - bool use_bitmap_method = FALSE; - bool is_mono = FALSE; + bool use_bitmap_method = false; + bool is_mono = false; - // TODO: use the mask origin when drawing transparently if (xsrcMask == -1 && ysrcMask == -1) { xsrcMask = xsrc; @@ -1202,7 +1215,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, if (srcDC->m_isMemDC) { - if (!memDC->m_selected.Ok()) return FALSE; + if (!memDC->m_selected.Ok()) return false; is_mono = (memDC->m_selected.GetDepth() == 1); @@ -1217,14 +1230,14 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, // we HAVE TO use the direct way for memory dcs // that have mask since the XCopyArea doesn't know // about masks - use_bitmap_method = TRUE; + use_bitmap_method = true; } else if (is_mono) { // we HAVE TO use the direct way for memory dcs // that are bitmaps because XCopyArea doesn't cope // with different bit depths - use_bitmap_method = TRUE; + use_bitmap_method = true; } else if ((xsrc == 0) && (ysrc == 0) && (width == memDC->m_selected.GetWidth()) && @@ -1234,11 +1247,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, // in the memory dc is copied in which case XCopyArea // wouldn't be able able to boost performace by reducing // the area to be scaled - use_bitmap_method = TRUE; + use_bitmap_method = true; } else { - use_bitmap_method = FALSE; + use_bitmap_method = false; } } @@ -1258,7 +1271,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxRegion tmp( xx,yy,ww,hh ); tmp.Intersect( m_currentClippingRegion ); if (tmp.IsEmpty()) - return TRUE; + return true; } int old_logical_func = m_logicalFunction; @@ -1270,12 +1283,15 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, 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; memDC->GetUserScale(&xsc,&ysc); @@ -1285,16 +1301,23 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord bm_ww = XLOG2DEVREL( bm_width ); wxCoord bm_hh = YLOG2DEVREL( bm_height ); - // scale bitmap if required + // Scale bitmap if required wxBitmap use_bitmap; - - if ((bm_width != bm_ww) || (bm_height != bm_hh)) + if ((memDC->m_selected.GetWidth()!= bm_ww) || ( memDC->m_selected.GetHeight()!= 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 { - // FIXME: use cx,cy,cw,ch here, too? + // Don't scale bitmap use_bitmap = memDC->m_selected; } @@ -1303,7 +1326,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); GdkBitmap *new_mask = (GdkBitmap*) NULL; - + if (useMask && mask) { if (!m_currentClippingRegion.IsNull()) @@ -1313,6 +1336,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, 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 ); @@ -1330,20 +1354,28 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, if (is_mono) { if (new_mask) + { gdk_gc_set_clip_mask( m_textGC, new_mask ); + gdk_gc_set_clip_origin( m_textGC, cx, cy ); + } else + { gdk_gc_set_clip_mask( m_textGC, mask ); - // was: gdk_gc_set_clip_origin( m_textGC, xx, yy ); - gdk_gc_set_clip_origin( m_textGC, cx, cy ); + gdk_gc_set_clip_origin( m_textGC, cx-xsrcMask, cy-ysrcMask ); + } } else { if (new_mask) + { gdk_gc_set_clip_mask( m_penGC, new_mask ); + gdk_gc_set_clip_origin( m_penGC, cx, cy ); + } else + { gdk_gc_set_clip_mask( m_penGC, mask ); - // was: gdk_gc_set_clip_origin( m_penGC, xx, yy ); - gdk_gc_set_clip_origin( m_penGC, cx, cy ); + gdk_gc_set_clip_origin( m_penGC, cx-xsrcMask, cy-ysrcMask ); + } } } @@ -1352,21 +1384,8 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, if (is_mono) { -#ifdef __WXGTK20__ - 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.GetBitmap(), 0, 0, 0, 0, -1, -1 ); - - gdk_draw_drawable( m_window, m_textGC, bitmap, xsrc, ysrc, cx, cy, cw, ch ); - - gdk_bitmap_unref( bitmap ); - gdk_gc_unref( gc ); -#else // was: gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh ); gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, cx, cy, cw, ch ); -#endif } else { @@ -1392,7 +1411,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); } } - + if (new_mask) gdk_bitmap_unref( new_mask ); } @@ -1405,8 +1424,8 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, tmp.Intersect( m_currentClippingRegion ); wxCoord cx,cy,cw,ch; tmp.GetBox(cx,cy,cw,ch); - - // rescale bitmap + + // rescale bitmap wxBitmap bitmap = memDC->m_selected.Rescale( cx-xx, cy-yy, cw, ch, ww, hh ); // draw scaled bitmap @@ -1415,7 +1434,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, } else { - // No scaling and not a memory dc with a mask either + // No scaling and not a memory dc with a mask either // copy including child window contents gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS ); @@ -1427,8 +1446,8 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, } SetLogicalFunction( old_logical_func ); - - return TRUE; + + return true; } void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) @@ -1436,81 +1455,16 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) wxCHECK_RET( Ok(), wxT("invalid window dc") ); if (!m_window) return; - + if (text.empty()) return; -#ifndef __WXGTK20__ GdkFont *font = m_font.GetInternalFont( m_scaleY ); wxCHECK_RET( font, wxT("invalid font") ); -#endif x = XLOG2DEV(x); y = YLOG2DEV(y); -#ifdef __WXGTK20__ - 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") ); - -#if wxUSE_UNICODE - const wxCharBuffer data = wxConvUTF8.cWC2MB( text ); -#else - const wxWCharBuffer wdata = wxConvLocal.cMB2WC( text ); - const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata ); -#endif - pango_layout_set_text( m_layout, (const char*) data, strlen( (const char*) data )); - - int w,h; - - if (abs(m_scaleY - 1.0) < 0.00001) - { - // If there is a user or actually any scale applied to - // the device context, scale the font. - - // scale font description - gint oldSize = pango_font_description_get_size( m_fontdesc ); - double size = oldSize; - size = size * m_scaleY; - pango_font_description_set_size( m_fontdesc, (gint)size ); - - // actually apply scaled font - pango_layout_set_font_description( m_layout, m_fontdesc ); - - 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_window, m_textGC, TRUE, x, y, w, h); - gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); - } - - // Draw layout. - gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); - - // reset unscaled size - pango_font_description_set_size( m_fontdesc, oldSize ); - - // actually apply unscaled font - pango_layout_set_font_description( m_layout, m_fontdesc ); - } - else - { - 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_window, m_textGC, TRUE, x, y, w, h); - gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); - } - // Draw layout. - gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); - } - - wxCoord width = w; - wxCoord height = h; - -#else // GTK+ 1.x wxCoord width = gdk_string_width( font, text.mbc_str() ); wxCoord height = font->ascent + font->descent; @@ -1531,7 +1485,6 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) if (font->descent > 0) ul_y++; gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y); } -#endif // GTK+ 2.0/1.x width = wxCoord(width / m_scaleX); height = wxCoord(height / m_scaleY); @@ -1539,9 +1492,14 @@ void wxWindowDC::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 + void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle ) { - if (angle == 0.0) + if ( wxIsNullDouble(angle) ) { DrawText(text, x, y); return; @@ -1551,26 +1509,26 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, if (!m_window) return; -#ifdef __WXGTK20__ - // implement later without GdkFont for GTK 2.0 - return; -#else + wxCoord w; + wxCoord h; + GdkFont *font = m_font.GetInternalFont( m_scaleY ); wxCHECK_RET( font, wxT("invalid font") ); // the size of the text - wxCoord w = gdk_string_width( font, text.mbc_str() ); - wxCoord h = font->ascent + font->descent; + w = gdk_string_width( font, text.mbc_str() ); + h = font->ascent + font->descent; // draw the string normally wxBitmap src(w, h); wxMemoryDC dc; dc.SelectObject(src); dc.SetFont(GetFont()); - dc.SetBackground(*wxWHITE_BRUSH); + dc.SetBackground(*wxBLACK_BRUSH); dc.SetBrush(*wxBLACK_BRUSH); dc.Clear(); + dc.SetTextForeground( *wxWHITE ); dc.DrawText(text, 0, 0); dc.SelectObject(wxNullBitmap); @@ -1594,47 +1552,40 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, minX = (wxCoord)(dmin(x2, dmin(x3, x4)) - 0.5), minY = (wxCoord)(dmin(y2, dmin(y3, y4)) - 0.5); - // prepare to blit-with-rotate the bitmap to the DC - wxImage image = src.ConvertToImage(); - - GdkColor *colText = m_textForegroundColour.GetColor(), - *colBack = m_textBackgroundColour.GetColor(); - - bool textColSet = TRUE; - unsigned char *data = image.GetData(); - - // paint pixel by pixel - for ( wxCoord srcX = 0; srcX < w; srcX++ ) - { - for ( wxCoord srcY = 0; srcY < h; srcY++ ) - { - // transform source coords to dest coords - double r = sqrt((double)srcX*srcX + srcY*srcY); - double angleOrig = atan2((double)srcY, (double)srcX) - rad; - wxCoord dstX = (wxCoord)(r*cos(angleOrig) + 0.5), - dstY = (wxCoord)(r*sin(angleOrig) + 0.5); - - // black pixel? - bool textPixel = data[(srcY*w + srcX)*3] == 0; - if ( textPixel || (m_backgroundMode == wxSOLID) ) - { - // change colour if needed - if ( textPixel != textColSet ) - { - gdk_gc_set_foreground( m_textGC, textPixel ? colText - : colBack ); + wxImage image = src.ConvertToImage(); - textColSet = textPixel; - } + image.ConvertColourToAlpha( m_textForegroundColour.Red(), + m_textForegroundColour.Green(), + m_textForegroundColour.Blue() ); + image = image.Rotate( rad, wxPoint(0,0) ); + + int i_angle = (int) angle; + i_angle = i_angle % 360; + if (i_angle < 0) + i_angle += 360; + int xoffset = 0; + if ((i_angle >= 90.0) && (i_angle < 270.0)) + xoffset = image.GetWidth(); + int yoffset = 0; + if ((i_angle >= 0.0) && (i_angle < 180.0)) + yoffset = image.GetHeight(); + + if ((i_angle >= 0) && (i_angle < 90)) + yoffset -= (int)( cos(rad)*h ); + if ((i_angle >= 90) && (i_angle < 180)) + xoffset -= (int)( sin(rad)*h ); + if ((i_angle >= 180) && (i_angle < 270)) + yoffset -= (int)( cos(rad)*h ); + if ((i_angle >= 270) && (i_angle < 360)) + xoffset -= (int)( sin(rad)*h ); + + int i_x = x - xoffset; + int i_y = y - yoffset; + + src = image; + DoDrawBitmap( src, i_x, i_y, true ); - // don't use DrawPoint() because it uses the current pen - // colour, and we don't need it here - gdk_draw_point( m_window, m_textGC, - XLOG2DEV(x) + dstX, YLOG2DEV(y) + dstY ); - } - } - } // it would be better to draw with non underlined font and draw the line // manually here (it would be more straight...) @@ -1647,97 +1598,60 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, } #endif // 0 - // restore the font colour - gdk_gc_set_foreground( m_textGC, colText ); - // update the bounding box CalcBoundingBox(x + minX, y + minY); CalcBoundingBox(x + maxX, y + maxY); -#endif } void wxWindowDC::DoGetTextExtent(const wxString &string, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading, - wxFont *theFont) const + const wxFont *theFont) const { - if (string.IsEmpty()) + if ( width ) + *width = 0; + if ( height ) + *height = 0; + if ( descent ) + *descent = 0; + if ( externalLeading ) + *externalLeading = 0; + + if (string.empty()) { - if (width) (*width) = 0; - if (height) (*height) = 0; return; } - -#ifdef __WXGTK20__ - // Set new font description - if (theFont) - pango_layout_set_font_description( m_layout, theFont->GetNativeFontInfo()->description ); - - // 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 )); -#else - const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string ); - const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata ); - pango_layout_set_text( m_layout, (const char*) data, strlen( (const char*) data )); -#endif - - int w,h; - pango_layout_get_pixel_size( m_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; // ?? - - // Reset old font description - if (theFont) - pango_layout_set_font_description( m_layout, m_fontdesc ); -#else + wxFont fontToUse = m_font; - if (theFont) fontToUse = *theFont; - + if (theFont) + fontToUse = *theFont; + 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); } wxCoord wxWindowDC::GetCharWidth() const { -#ifdef __WXGTK20__ - pango_layout_set_text( m_layout, "H", 1 ); - int w,h; - pango_layout_get_pixel_size( m_layout, &w, &h ); - return w; -#else GdkFont *font = m_font.GetInternalFont( m_scaleY ); wxCHECK_MSG( font, -1, wxT("invalid font") ); return wxCoord(gdk_string_width( font, "H" ) / m_scaleX); -#endif } wxCoord wxWindowDC::GetCharHeight() const { -#ifdef __WXGTK20__ - pango_layout_set_text( m_layout, "H", 1 ); - int w,h; - pango_layout_get_pixel_size( m_layout, &w, &h ); - return h; -#else GdkFont *font = m_font.GetInternalFont( m_scaleY ); wxCHECK_MSG( font, -1, wxT("invalid font") ); return wxCoord((font->ascent + font->descent) / m_scaleY); -#endif } void wxWindowDC::Clear() @@ -1781,42 +1695,6 @@ void wxWindowDC::Clear() void wxWindowDC::SetFont( const wxFont &font ) { m_font = font; - -#ifdef __WXGTK20__ - if (m_font.Ok()) - { - if (m_fontdesc) - pango_font_description_free( m_fontdesc ); - - m_fontdesc = pango_font_description_copy( m_font.GetNativeFontInfo()->description ); - - - if (m_owner) - { - PangoContext *oldContext = m_context; - - // We might want to use the X11 context for faster - // rendering on screen - if (m_font.GetNoAntiAliasing()) - m_context = m_owner->GtkGetPangoX11Context(); - else - m_context = m_owner->GtkGetPangoDefaultContext(); - - // If we switch back/forth between different contexts - // we also have to create a new layout. I think so, - // at least, and it doesn't hurt to do it. - if (oldContext != m_context) - { - if (m_layout) - g_object_unref( G_OBJECT( m_layout ) ); - - m_layout = pango_layout_new( m_context ); - } - } - - pango_layout_set_font_description( m_layout, m_fontdesc ); - } -#endif } void wxWindowDC::SetPen( const wxPen &pen ) @@ -1916,7 +1794,6 @@ void wxWindowDC::SetPen( const wxPen &pen ) } } -#if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1) if (req_dash && req_nb_dash) { wxGTKDash *real_req_dash = new wxGTKDash[req_nb_dash]; @@ -1933,7 +1810,6 @@ void wxWindowDC::SetPen( const wxPen &pen ) gdk_gc_set_dashes( m_penGC, 0, (wxGTKDash*)req_dash, req_nb_dash ); } } -#endif // GTK+ > 1.0 GdkCapStyle capStyle = GDK_CAP_ROUND; switch (m_pen.GetCap()) @@ -2008,7 +1884,7 @@ void wxWindowDC::SetBrush( const wxBrush &brush ) gdk_gc_set_stipple( m_textGC, m_brush.GetStipple()->GetMask()->GetBitmap() ); } - if (IS_HATCH(m_brush.GetStyle())) + if (m_brush.IsHatch()) { gdk_gc_set_fill( m_brushGC, GDK_STIPPLED ); int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH; @@ -2053,7 +1929,7 @@ void wxWindowDC::SetBackground( const wxBrush &brush ) } } - if (IS_HATCH(m_backgroundBrush.GetStyle())) + if (m_backgroundBrush.IsHatch()) { gdk_gc_set_fill( m_bgGC, GDK_STIPPLED ); int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH; @@ -2077,7 +1953,6 @@ void wxWindowDC::SetLogicalFunction( int function ) { case wxXOR: mode = GDK_XOR; break; case wxINVERT: mode = GDK_INVERT; break; -#if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1) case wxOR_REVERSE: mode = GDK_OR_REVERSE; break; case wxAND_REVERSE: mode = GDK_AND_REVERSE; break; case wxCLEAR: mode = GDK_CLEAR; break; @@ -2094,7 +1969,6 @@ void wxWindowDC::SetLogicalFunction( int function ) // unsupported by GTK case wxNOR: mode = GDK_COPY; break; -#endif // GTK+ > 1.0 default: wxFAIL_MSG( wxT("unsupported logical function") ); mode = GDK_COPY; @@ -2279,22 +2153,19 @@ void wxWindowDC::Destroy() void wxWindowDC::ComputeScaleAndOrigin() { - /* CMB: copy scale to see if it changes */ - double origScaleX = m_scaleX; - double origScaleY = m_scaleY; + const wxRealPoint origScale(m_scaleX, m_scaleY); wxDC::ComputeScaleAndOrigin(); - /* CMB: if scale has changed call SetPen to recalulate the line width */ - if ((m_scaleX != origScaleX || m_scaleY != origScaleY) && - (m_pen.Ok())) + // if scale has changed call SetPen to recalulate the line width + if ( wxRealPoint(m_scaleX, m_scaleY) != origScale && m_pen.Ok() ) { - /* this is a bit artificial, but we need to force wxDC to think - the pen has changed */ - wxPen pen = m_pen; - m_pen = wxNullPen; - SetPen( pen ); - } + // this is a bit artificial, but we need to force wxDC to think the pen + // has changed + wxPen pen = m_pen; + m_pen = wxNullPen; + SetPen( pen ); + } } // Resolution in pixels per logical inch @@ -2317,6 +2188,25 @@ int wxWindowDC::GetDepth() const 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 ) { @@ -2324,21 +2214,23 @@ wxPaintDC::wxPaintDC( wxWindow *win ) if (!win->m_clipPaintRegion) return; + wxSize sz = win->GetSize(); m_paintClippingRegion = win->GetUpdateRegion(); + wxLimitRegionToSize(m_paintClippingRegion, sz); + 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 } @@ -2388,7 +2280,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) bool wxDCModule::OnInit() { wxInitGCPool(); - return TRUE; + return true; } void wxDCModule::OnExit()