X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4bc67cc550bcd9d5f93f88ae22a4f6ac7fafb5f7..16bcc879d96712f9acf4bcc1236096251a1b7586:/src/gtk/dcclient.cpp diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index 0b2a1391cd..b6044d4b6c 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -16,6 +16,9 @@ #include "wx/image.h" #include +#include "gdk/gdk.h" +#include "gtk/gtk.h" + //----------------------------------------------------------------------------- // local data //----------------------------------------------------------------------------- @@ -93,6 +96,7 @@ wxWindowDC::wxWindowDC() m_bgGC = (GdkGC *) NULL; m_cmap = (GdkColormap *) NULL; m_isMemDC = FALSE; + m_owner = (wxWindow *)NULL; } wxWindowDC::wxWindowDC( wxWindow *window ) @@ -102,6 +106,7 @@ wxWindowDC::wxWindowDC( wxWindow *window ) m_textGC = (GdkGC *) NULL; m_bgGC = (GdkGC *) NULL; m_cmap = (GdkColormap *) NULL; + m_owner = (wxWindow *)NULL; if (!window) return; GtkWidget *widget = window->m_wxwindow; @@ -116,7 +121,15 @@ wxWindowDC::wxWindowDC( wxWindow *window ) m_isMemDC = FALSE; SetUpDC(); + + /* this must be done after SetUpDC, bacause SetUpDC calls the + repective SetBrush, SetPen, SetBackground etc functions + to set up the DC. SetBackground call m_owner->SetBackground + and this might not be desired as the standard dc background + is white whereas a window might assume gray to be the + standard (as e.g. wxStatusBar) */ + m_owner = window; } wxWindowDC::~wxWindowDC() @@ -507,6 +520,8 @@ void wxWindowDC::DrawBitmap( const wxBitmap &bitmap, long x, long y, bool useMas wxCHECK_RET( Ok(), "invalid window dc" ); if (!bitmap.Ok()) return; + + /* scale/translate size and position */ int xx = XLOG2DEV(x); int yy = YLOG2DEV(y); @@ -517,6 +532,8 @@ void wxWindowDC::DrawBitmap( const wxBitmap &bitmap, long x, long y, bool useMas int ww = XLOG2DEVREL(w); int hh = YLOG2DEVREL(h); + /* scale bitmap if required */ + wxBitmap use_bitmap; if ((w != ww) || (h != hh)) @@ -531,6 +548,8 @@ void wxWindowDC::DrawBitmap( const wxBitmap &bitmap, long x, long y, bool useMas use_bitmap = bitmap; } + /* apply mask if any */ + GdkBitmap *mask = (GdkBitmap *) NULL; if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); @@ -540,9 +559,24 @@ void wxWindowDC::DrawBitmap( const wxBitmap &bitmap, long x, long y, bool useMas gdk_gc_set_clip_origin( m_penGC, xx, yy ); } + /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */ + GdkPixmap *pm = use_bitmap.GetPixmap(); - gdk_draw_pixmap( m_window, m_penGC, pm, 0, 0, xx, yy, -1, -1 ); - + if (pm) + { + gdk_draw_pixmap( m_window, m_penGC, pm, 0, 0, xx, yy, -1, -1 ); + } + else + { + GdkBitmap *bm = use_bitmap.GetBitmap(); + if (bm) + { + gdk_draw_bitmap( m_window, m_penGC, bm, 0, 0, xx, yy, -1, -1 ); + } + } + + /* remove mask again if any */ + if (useMask && mask) { gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); @@ -556,93 +590,192 @@ void wxWindowDC::DrawBitmap( const wxBitmap &bitmap, long x, long y, bool useMas bool wxWindowDC::Blit( long xdest, long ydest, long width, long height, wxDC *source, long xsrc, long ysrc, int logical_func, bool useMask ) { + /* this is the nth try to get this utterly useless function to + work. it now completely ignores the scaling or translation + of the source dc, but scales correctly on the target dc and + knows about possible mask information in a memory dc. */ + wxCHECK_MSG( Ok(), FALSE, "invalid window dc" ); + wxCHECK_MSG( source, FALSE, "invalid source dc" ); + + wxClientDC *srcDC = (wxClientDC*)source; + wxMemoryDC *memDC = (wxMemoryDC*)source; + + bool use_bitmap_method = FALSE; + + if (srcDC->m_isMemDC) + { + if (!memDC->m_selected.Ok()) return FALSE; + + /* we use the "XCopyArea" way to copy a memory dc into + y different window if the memory dc BOTH + a) doesn't have any mask or its mask isn't used + b) it is clipped + c) is not 1-bit */ + + if (useMask && (memDC->m_selected.GetMask())) + { + /* we HAVE TO use the direct way for memory dcs + that have mask since the XCopyArea doesn't know + about masks and */ + use_bitmap_method = TRUE; + } + else if (memDC->m_selected.GetDepth() == 1) + { + /* we HAVE TO use the direct way for memory dcs + that are bitmaps because XCopyArea doesn't copy + with different bit depths */ + use_bitmap_method = TRUE; + } + else if ((xsrc == 0) && (ysrc == 0) && + (width == memDC->m_selected.GetWidth()) && + (height == memDC->m_selected.GetHeight())) + { + /* we SHOULD use the direct way if all of the bitmap + 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; + } + else + { + use_bitmap_method = FALSE; + } + } + CalcBoundingBox( xdest, ydest ); CalcBoundingBox( xdest + width, ydest + height ); int old_logical_func = m_logicalFunction; SetLogicalFunction( logical_func ); - wxClientDC *csrc = (wxClientDC*)source; - - if (csrc->m_isMemDC) + if (use_bitmap_method) { - wxMemoryDC* srcDC = (wxMemoryDC*)source; - GdkPixmap* pmap = srcDC->m_selected.GetPixmap(); - if (pmap) + /* scale/translate bitmap size */ + + long bm_width = memDC->m_selected.GetWidth(); + long bm_height = memDC->m_selected.GetHeight(); + + long bm_ww = XLOG2DEVREL( bm_width ); + long bm_hh = YLOG2DEVREL( bm_height ); + + /* scale bitmap if required */ + + wxBitmap use_bitmap; + + if ((bm_width != bm_ww) || (bm_height != bm_hh)) { - long xx = XLOG2DEV(xdest); - long yy = YLOG2DEV(ydest); + printf( "scaling.\n" ); + + wxImage image( memDC->m_selected ); + image = image.Scale( bm_ww, bm_hh ); + + use_bitmap = image.ConvertToBitmap(); + } + else + { + use_bitmap = memDC->m_selected; + } + + /* scale/translate size and position */ + + long xx = XLOG2DEV(xdest); + long yy = YLOG2DEV(ydest); + + long ww = XLOG2DEVREL(width); + long hh = YLOG2DEVREL(height); + + /* apply mask if any */ - GdkBitmap *mask = (GdkBitmap *) NULL; - if (srcDC->m_selected.GetMask()) mask = srcDC->m_selected.GetMask()->GetBitmap(); + GdkBitmap *mask = (GdkBitmap *) NULL; + if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); - if (useMask && mask) - { - gdk_gc_set_clip_mask( m_penGC, mask ); - gdk_gc_set_clip_origin( m_penGC, xx, yy ); - } - - gdk_draw_pixmap( m_window, m_penGC, pmap, - source->DeviceToLogicalX(xsrc), - source->DeviceToLogicalY(ysrc), - xx, - yy, - source->DeviceToLogicalXRel(width), - source->DeviceToLogicalYRel(height) ); - - if (useMask && mask) - { - gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_penGC, 0, 0 ); - } - - SetLogicalFunction( old_logical_func ); - return TRUE; + if (useMask && mask) + { + gdk_gc_set_clip_mask( m_penGC, mask ); + gdk_gc_set_clip_origin( m_penGC, xx, yy ); } - GdkBitmap* bmap = srcDC->m_selected.GetBitmap(); - if (bmap) + /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */ + + GdkPixmap *pm = use_bitmap.GetPixmap(); + if (pm) + { + gdk_draw_pixmap( m_window, m_penGC, pm, xsrc, ysrc, xx, yy, ww, hh ); + } + else { - long xx = XLOG2DEV(xdest); - long yy = YLOG2DEV(ydest); + GdkBitmap *bm = use_bitmap.GetBitmap(); + if (bm) + { + /* we use the textGC here because blitting a bitmap is done + using the current text colour */ + gdk_draw_bitmap( m_window, m_textGC, bm, xsrc, ysrc, xx, yy, ww, hh ); + } + } - GdkBitmap *mask = (GdkBitmap *) NULL; - if (srcDC->m_selected.GetMask()) mask = srcDC->m_selected.GetMask()->GetBitmap(); + /* remove mask again if any */ - if (useMask && mask) - { - gdk_gc_set_clip_mask( m_penGC, mask ); - gdk_gc_set_clip_origin( m_penGC, xx, yy ); - } - - gdk_draw_bitmap( m_window, m_textGC, bmap, - source->DeviceToLogicalX(xsrc), - source->DeviceToLogicalY(ysrc), - xx, - yy, - source->DeviceToLogicalXRel(width), - source->DeviceToLogicalYRel(height) ); - - if (useMask && mask) - { - gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_penGC, 0, 0 ); - } - - SetLogicalFunction( old_logical_func ); - return TRUE; + if (useMask && mask) + { + gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); + gdk_gc_set_clip_origin( m_penGC, 0, 0 ); } } - - gdk_window_copy_area ( m_window, m_penGC, - XLOG2DEV(xdest), YLOG2DEV(ydest), - csrc->GetWindow(), - source->DeviceToLogicalX(xsrc), - source->DeviceToLogicalY(ysrc), - source->DeviceToLogicalXRel(width), - source->DeviceToLogicalYRel(height) ); + else /* use_bitmap_method */ + { + /* scale/translate size and position */ + + long xx = XLOG2DEV(xdest); + long yy = YLOG2DEV(ydest); + + long ww = XLOG2DEVREL(width); + long hh = YLOG2DEVREL(height); + + if ((width != ww) || (height != hh)) + { + /* draw source window into a bitmap as we cannot scale + a window in contrast to a bitmap. this would actually + work with memory dcs as well, but we'd lose the mask + information and waste one step in this process since + a memory already has a bitmap. all this is slightly + inefficient as we could take an XImage directly from + an X window, but we'd then also have to care that + the window is not outside the screen (in which case + we'd get a BadMatch or what not). + Is a double XGetImage and combined XGetPixel and + XPutPixel really faster? I'm not sure. look at wxXt + for a different implementation of the same problem. */ + + wxBitmap bitmap( width, height ); + gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0, + srcDC->GetWindow(), + xsrc, ysrc, width, height ); + + /* scale image */ + + wxImage image( bitmap ); + image = image.Scale( ww, hh ); + + /* convert to bitmap */ + + bitmap = image.ConvertToBitmap(); + + /* draw scaled bitmap */ + + gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); + + } + else + { + /* no scaling and not a memory dc with a mask either */ + + gdk_window_copy_area( m_window, m_penGC, xx, yy, + srcDC->GetWindow(), + xsrc, ysrc, width, height ); + } + } SetLogicalFunction( old_logical_func ); return TRUE; @@ -657,7 +790,7 @@ void wxWindowDC::DrawText( const wxString &text, long x, long y, bool WXUNUSED(u x = XLOG2DEV(x); y = YLOG2DEV(y); - // CMB 21/5/98: draw text background if mode is wxSOLID + /* CMB 21/5/98: draw text background if mode is wxSOLID */ if (m_backgroundMode == wxSOLID) { long width = gdk_string_width( font, text ); @@ -668,9 +801,9 @@ void wxWindowDC::DrawText( const wxString &text, long x, long y, bool WXUNUSED(u } gdk_draw_string( m_window, font, m_textGC, x, y + font->ascent, text ); - // CMB 17/7/98: simple underline: ignores scaling and underlying - // X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS - // properties (see wxXt implementation) + /* CMB 17/7/98: simple underline: ignores scaling and underlying + X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS + properties (see wxXt implementation) */ if (m_font.GetUnderlined()) { long width = gdk_string_width( font, text ); @@ -726,15 +859,27 @@ void wxWindowDC::Clear() { wxCHECK_RET( Ok(), "invalid window dc" ); - if (!m_isMemDC) + /* - we either are a memory dc or have a window as the + owner. anything else shouldn't happen. + - we don't use gdk_window_clear() as we don't set + the window's background colour anymore. it is too + much pain to keep the DC's and the window's back- + ground colour in synch. */ + + if (m_owner) { - gdk_window_clear( m_window ); + int width,height; + m_owner->GetSize( &width, &height ); + gdk_draw_rectangle( m_window, m_bgGC, TRUE, 0, 0, width, height ); + return; } - else + + if (m_isMemDC) { int width,height; GetSize( &width, &height ); gdk_draw_rectangle( m_window, m_bgGC, TRUE, 0, 0, width, height ); + return; } } @@ -826,9 +971,12 @@ void wxWindowDC::SetBrush( const wxBrush &brush ) gdk_gc_set_fill( m_brushGC, fillStyle ); - if (m_brush.GetStyle() == wxSTIPPLE) + if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok())) { - gdk_gc_set_stipple( m_brushGC, m_brush.GetStipple()->GetPixmap() ); + if (m_brush.GetStipple()->GetPixmap()) + gdk_gc_set_stipple( m_brushGC, m_brush.GetStipple()->GetPixmap() ); + else + gdk_gc_set_stipple( m_brushGC, m_brush.GetStipple()->GetBitmap() ); } if (IS_HATCH(m_brush.GetStyle())) @@ -840,8 +988,8 @@ void wxWindowDC::SetBrush( const wxBrush &brush ) void wxWindowDC::SetBackground( const wxBrush &brush ) { - // CMB 21/7/98: Added SetBackground. Sets background brush - // for Clear() and bg colour for shapes filled with cross-hatch brush + /* CMB 21/7/98: Added SetBackground. Sets background brush + * for Clear() and bg colour for shapes filled with cross-hatch brush */ wxCHECK_RET( Ok(), "invalid window dc" ); @@ -860,11 +1008,11 @@ void wxWindowDC::SetBackground( const wxBrush &brush ) GdkFill fillStyle = GDK_SOLID; switch (m_backgroundBrush.GetStyle()) { - case wxSOLID: - case wxTRANSPARENT: - break; - default: - fillStyle = GDK_STIPPLED; + case wxSOLID: + case wxTRANSPARENT: + break; + default: + fillStyle = GDK_STIPPLED; } gdk_gc_set_fill( m_bgGC, fillStyle ); @@ -878,7 +1026,7 @@ void wxWindowDC::SetBackground( const wxBrush &brush ) { int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH; gdk_gc_set_stipple( m_bgGC, hatches[num] ); - } + } } void wxWindowDC::SetLogicalFunction( int function ) @@ -1222,6 +1370,11 @@ void wxWindowDC::DrawSpline( wxList *points ) wx_spline_draw_point_array( this ); } +// Resolution in pixels per logical inch +wxSize wxWindowDC::GetPPI(void) const +{ + return wxSize(100, 100); +} //----------------------------------------------------------------------------- // wxPaintDC