X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e23d0e958e1776cf9e7a8c61a41dbf57e16b4b60..434d2cb3c67c7afc1637e867e47010d13ee8903f:/src/gtk1/dcclient.cpp diff --git a/src/gtk1/dcclient.cpp b/src/gtk1/dcclient.cpp index 8fdd39e4ce..2cdeb7137a 100644 --- a/src/gtk1/dcclient.cpp +++ b/src/gtk1/dcclient.cpp @@ -13,8 +13,12 @@ #include "wx/dcclient.h" #include "wx/dcmemory.h" +#include "wx/image.h" #include +#include "gdk/gdk.h" +#include "gtk/gtk.h" + //----------------------------------------------------------------------------- // local data //----------------------------------------------------------------------------- @@ -79,12 +83,12 @@ void gdk_draw_bitmap (GdkDrawable *drawable, } //----------------------------------------------------------------------------- -// wxPaintDC +// wxWindowDC //----------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxPaintDC,wxDC) +IMPLEMENT_DYNAMIC_CLASS(wxWindowDC,wxDC) -wxPaintDC::wxPaintDC(void) +wxWindowDC::wxWindowDC() { m_penGC = (GdkGC *) NULL; m_brushGC = (GdkGC *) NULL; @@ -92,15 +96,17 @@ wxPaintDC::wxPaintDC(void) m_bgGC = (GdkGC *) NULL; m_cmap = (GdkColormap *) NULL; m_isMemDC = FALSE; + m_owner = (wxWindow *)NULL; } -wxPaintDC::wxPaintDC( wxWindow *window ) +wxWindowDC::wxWindowDC( wxWindow *window ) { m_penGC = (GdkGC *) NULL; m_brushGC = (GdkGC *) NULL; m_textGC = (GdkGC *) NULL; m_bgGC = (GdkGC *) NULL; m_cmap = (GdkColormap *) NULL; + m_owner = (wxWindow *)NULL; if (!window) return; GtkWidget *widget = window->m_wxwindow; @@ -115,42 +121,51 @@ wxPaintDC::wxPaintDC( 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; } -wxPaintDC::~wxPaintDC(void) +wxWindowDC::~wxWindowDC() { Destroy(); } -void wxPaintDC::FloodFill( long WXUNUSED(x1), long WXUNUSED(y1), - wxColour *WXUNUSED(col), int WXUNUSED(style) ) +void wxWindowDC::FloodFill( long WXUNUSED(x), long WXUNUSED(y), + const wxColour &WXUNUSED(col), int WXUNUSED(style) ) { - wxFAIL_MSG( "wxPaintDC::FloodFill not implemented" ); + wxFAIL_MSG( _T("wxWindowDC::FloodFill not implemented") ); } -bool wxPaintDC::GetPixel( long WXUNUSED(x1), long WXUNUSED(y1), wxColour *WXUNUSED(col) ) const +bool wxWindowDC::GetPixel( long WXUNUSED(x1), long WXUNUSED(y1), wxColour *WXUNUSED(col) ) const { - wxFAIL_MSG( "wxPaintDC::GetPixel not implemented" ); + wxFAIL_MSG( _T("wxWindowDC::GetPixel not implemented") ); return FALSE; } -void wxPaintDC::DrawLine( long x1, long y1, long x2, long y2 ) +void wxWindowDC::DrawLine( long x1, long y1, long x2, long y2 ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (m_pen.GetStyle() != wxTRANSPARENT) { gdk_draw_line( m_window, m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) ); + + CalcBoundingBox(x1, y1); + CalcBoundingBox(x2, y2); } - - CalcBoundingBox(x1, y1); - CalcBoundingBox(x2, y2); } -void wxPaintDC::CrossHair( long x, long y ) +void wxWindowDC::CrossHair( long x, long y ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (m_pen.GetStyle() != wxTRANSPARENT) { @@ -164,9 +179,9 @@ void wxPaintDC::CrossHair( long x, long y ) } } -void wxPaintDC::DrawArc( long x1, long y1, long x2, long y2, double xc, double yc ) +void wxWindowDC::DrawArc( long x1, long y1, long x2, long y2, double xc, double yc ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); long xx1 = XLOG2DEV(x1); long yy1 = YLOG2DEV(y1); @@ -214,9 +229,9 @@ void wxPaintDC::DrawArc( long x1, long y1, long x2, long y2, double xc, double y CalcBoundingBox (x2, y2); } -void wxPaintDC::DrawEllipticArc( long x, long y, long width, long height, double sa, double ea ) +void wxWindowDC::DrawEllipticArc( long x, long y, long width, long height, double sa, double ea ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); long xx = XLOG2DEV(x); long yy = YLOG2DEV(y); @@ -239,9 +254,9 @@ void wxPaintDC::DrawEllipticArc( long x, long y, long width, long height, double CalcBoundingBox (x + width, y + height); } -void wxPaintDC::DrawPoint( long x, long y ) +void wxWindowDC::DrawPoint( long x, long y ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (m_pen.GetStyle() != wxTRANSPARENT) gdk_draw_point( m_window, m_penGC, XLOG2DEV(x), YLOG2DEV(y) ); @@ -249,9 +264,9 @@ void wxPaintDC::DrawPoint( long x, long y ) CalcBoundingBox (x, y); } -void wxPaintDC::DrawLines( int n, wxPoint points[], long xoffset, long yoffset ) +void wxWindowDC::DrawLines( int n, wxPoint points[], long xoffset, long yoffset ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (m_pen.GetStyle() == wxTRANSPARENT) return; if (n <= 0) return; @@ -270,9 +285,9 @@ void wxPaintDC::DrawLines( int n, wxPoint points[], long xoffset, long yoffset ) } } -void wxPaintDC::DrawLines( wxList *points, long xoffset, long yoffset ) +void wxWindowDC::DrawLines( wxList *points, long xoffset, long yoffset ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (m_pen.GetStyle() == wxTRANSPARENT) return; @@ -297,11 +312,11 @@ void wxPaintDC::DrawLines( wxList *points, long xoffset, long yoffset ) } } -void wxPaintDC::DrawPolygon( int n, wxPoint points[], long xoffset, long yoffset, int WXUNUSED(fillStyle) ) +void wxWindowDC::DrawPolygon( int n, wxPoint points[], long xoffset, long yoffset, int WXUNUSED(fillStyle) ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); - if (!n) return; + if (n <= 0) return; GdkPoint *gdkpoints = new GdkPoint[n+1]; int i; @@ -331,12 +346,12 @@ void wxPaintDC::DrawPolygon( int n, wxPoint points[], long xoffset, long yoffset delete[] gdkpoints; } -void wxPaintDC::DrawPolygon( wxList *lines, long xoffset, long yoffset, int WXUNUSED(fillStyle)) +void wxWindowDC::DrawPolygon( wxList *lines, long xoffset, long yoffset, int WXUNUSED(fillStyle)) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); int n = lines->Number(); - if (!n) return; + if (n <= 0) return; GdkPoint *gdkpoints = new GdkPoint[n]; wxNode *node = lines->First(); @@ -372,9 +387,9 @@ void wxPaintDC::DrawPolygon( wxList *lines, long xoffset, long yoffset, int WXUN delete[] gdkpoints; } -void wxPaintDC::DrawRectangle( long x, long y, long width, long height ) +void wxWindowDC::DrawRectangle( long x, long y, long width, long height ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); long xx = XLOG2DEV(x); long yy = YLOG2DEV(y); @@ -398,9 +413,9 @@ void wxPaintDC::DrawRectangle( long x, long y, long width, long height ) CalcBoundingBox( x + width, y + height ); } -void wxPaintDC::DrawRoundedRectangle( long x, long y, long width, long height, double radius ) +void wxWindowDC::DrawRoundedRectangle( long x, long y, long width, long height, double radius ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (radius < 0.0) radius = - radius * ((width < height) ? width : height); @@ -467,9 +482,9 @@ void wxPaintDC::DrawRoundedRectangle( long x, long y, long width, long height, d CalcBoundingBox( x + width, y + height ); } -void wxPaintDC::DrawEllipse( long x, long y, long width, long height ) +void wxWindowDC::DrawEllipse( long x, long y, long width, long height ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); long xx = XLOG2DEV(x); long yy = YLOG2DEV(y); @@ -486,26 +501,57 @@ void wxPaintDC::DrawEllipse( long x, long y, long width, long height ) if (m_pen.GetStyle() != wxTRANSPARENT) gdk_draw_arc( m_window, m_penGC, FALSE, xx, yy, ww, hh, 0, 360*64 ); - CalcBoundingBox( x, y ); + CalcBoundingBox( x - width, y - height ); CalcBoundingBox( x + width, y + height ); } -bool wxPaintDC::CanDrawBitmap(void) const +bool wxWindowDC::CanDrawBitmap() const { - return TRUE; + return TRUE; } -void wxPaintDC::DrawIcon( const wxIcon &icon, long x, long y, bool useMask ) +void wxWindowDC::DrawIcon( const wxIcon &icon, long x, long y ) { - if (!Ok()) return; + DrawBitmap( icon, x, y, TRUE ); +} + +void wxWindowDC::DrawBitmap( const wxBitmap &bitmap, long x, long y, bool useMask ) +{ + wxCHECK_RET( Ok(), _T("invalid window dc") ); - if (!icon.Ok()) return; + if (!bitmap.Ok()) return; + + /* scale/translate size and position */ int xx = XLOG2DEV(x); int yy = YLOG2DEV(y); + int w = bitmap.GetWidth(); + int h = bitmap.GetHeight(); + + int ww = XLOG2DEVREL(w); + int hh = YLOG2DEVREL(h); + + /* scale bitmap if required */ + + wxBitmap use_bitmap; + + if ((w != ww) || (h != hh)) + { + wxImage image( bitmap ); + image = image.Scale( ww, hh ); + + use_bitmap = image.ConvertToBitmap(); + } + else + { + use_bitmap = bitmap; + } + + /* apply mask if any */ + GdkBitmap *mask = (GdkBitmap *) NULL; - if (icon.GetMask()) mask = icon.GetMask()->GetBitmap(); + if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); if (useMask && mask) { @@ -513,9 +559,24 @@ void wxPaintDC::DrawIcon( const wxIcon &icon, long x, long y, bool useMask ) gdk_gc_set_clip_origin( m_penGC, xx, yy ); } - GdkPixmap *pm = icon.GetPixmap(); - gdk_draw_pixmap( m_window, m_penGC, pm, 0, 0, xx, yy, -1, -1 ); - + /* 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, 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 ); @@ -523,134 +584,227 @@ void wxPaintDC::DrawIcon( const wxIcon &icon, long x, long y, bool useMask ) } CalcBoundingBox( x, y ); - int width = icon.GetWidth(); - int height = icon.GetHeight(); - CalcBoundingBox( x + width, y + height ); + CalcBoundingBox( x + w, y + h ); } -bool wxPaintDC::Blit( long xdest, long ydest, long width, long height, - wxDC *source, long xsrc, long ysrc, int WXUNUSED(logical_func), bool useMask ) +bool wxWindowDC::Blit( long xdest, long ydest, long width, long height, + wxDC *source, long xsrc, long ysrc, int logical_func, bool useMask ) { - if (!Ok()) return FALSE; + /* 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, _T("invalid window dc") ); + + wxCHECK_MSG( source, FALSE, _T("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 ); - wxClientDC *csrc = (wxClientDC*)source; - - if (csrc->m_isMemDC) + int old_logical_func = m_logicalFunction; + SetLogicalFunction( logical_func ); + + 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)) + { + wxImage image( memDC->m_selected ); + image = image.Scale( bm_ww, bm_hh ); + + use_bitmap = image.ConvertToBitmap(); + } + else { - long xx = XLOG2DEV(xdest); - long yy = YLOG2DEV(ydest); + 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 ); - } - - 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) { - long xx = XLOG2DEV(xdest); - long yy = YLOG2DEV(ydest); + gdk_draw_pixmap( m_window, m_penGC, pm, xsrc, ysrc, xx, yy, ww, hh ); + } + else + { + 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_penGC, 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 ); - } - - return TRUE; + if (useMask && mask) + { + gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); + gdk_gc_set_clip_origin( m_penGC, 0, 0 ); } } + 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 ); + } + } - 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) ); - -/* - gdk_window_copy_area ( m_window, m_penGC, - XLOG2DEV(xdest), YLOG2DEV(ydest), - csrc->GetWindow(), - xsrc, ysrc, - width, height ); -*/ - - return TRUE; + SetLogicalFunction( old_logical_func ); + return TRUE; } -void wxPaintDC::DrawText( const wxString &text, long x, long y, bool WXUNUSED(use16) ) +void wxWindowDC::DrawText( const wxString &text, long x, long y, bool WXUNUSED(use16) ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); GdkFont *font = m_font.GetInternalFont( m_scaleY ); 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 ); + long width = gdk_string_width( font, text.mbc_str() ); long height = font->ascent + font->descent; gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() ); gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height ); gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() ); } - gdk_draw_string( m_window, font, m_textGC, x, y + font->ascent, text ); + gdk_draw_string( m_window, font, m_textGC, x, y + font->ascent, text.mbc_str() ); - // 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 ); + long width = gdk_string_width( font, text.mbc_str() ); long ul_y = y + font->ascent; if (font->descent > 0) ul_y++; gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y); @@ -662,70 +816,82 @@ void wxPaintDC::DrawText( const wxString &text, long x, long y, bool WXUNUSED(us CalcBoundingBox (x, y); } -bool wxPaintDC::CanGetTextExtent(void) const +bool wxWindowDC::CanGetTextExtent() const { return TRUE; } -void wxPaintDC::GetTextExtent( const wxString &string, long *width, long *height, +void wxWindowDC::GetTextExtent( const wxString &string, long *width, long *height, long *descent, long *externalLeading, wxFont *theFont, bool WXUNUSED(use16) ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); wxFont fontToUse = m_font; if (theFont) fontToUse = *theFont; GdkFont *font = fontToUse.GetInternalFont( m_scaleY ); - if (width) (*width) = long(gdk_string_width( font, string ) / m_scaleX); + if (width) (*width) = long(gdk_string_width( font, string.mbc_str() ) / m_scaleX); if (height) (*height) = long((font->ascent + font->descent) / m_scaleY); if (descent) (*descent) = long(font->descent / m_scaleY); if (externalLeading) (*externalLeading) = 0; // ?? } -long wxPaintDC::GetCharWidth(void) +long wxWindowDC::GetCharWidth() { - if (!Ok()) return 0; + wxCHECK_MSG( Ok(), 0, _T("invalid window dc") ); GdkFont *font = m_font.GetInternalFont( m_scaleY ); return long(gdk_string_width( font, "H" ) / m_scaleX); } -long wxPaintDC::GetCharHeight(void) +long wxWindowDC::GetCharHeight() { - if (!Ok()) return 0; + wxCHECK_MSG( Ok(), 0, _T("invalid window dc") ); GdkFont *font = m_font.GetInternalFont( m_scaleY ); return long((font->ascent + font->descent) / m_scaleY); } -void wxPaintDC::Clear(void) +void wxWindowDC::Clear() { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("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; } } -void wxPaintDC::SetFont( const wxFont &font ) +void wxWindowDC::SetFont( const wxFont &font ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); m_font = font; } -void wxPaintDC::SetPen( const wxPen &pen ) +void wxWindowDC::SetPen( const wxPen &pen ) { - if (!Ok()) return; - + wxCHECK_RET( Ok(), _T("invalid window dc") ); + if (m_pen == pen) return; m_pen = pen; @@ -778,9 +944,9 @@ void wxPaintDC::SetPen( const wxPen &pen ) gdk_gc_set_foreground( m_penGC, m_pen.GetColour().GetColor() ); } -void wxPaintDC::SetBrush( const wxBrush &brush ) +void wxWindowDC::SetBrush( const wxBrush &brush ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (m_brush == brush) return; @@ -803,9 +969,12 @@ void wxPaintDC::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())) @@ -815,11 +984,12 @@ void wxPaintDC::SetBrush( const wxBrush &brush ) } } -// CMB 21/7/98: Added SetBackground. Sets background brush -// for Clear() and bg colour for shapes filled with cross-hatch brush -void wxPaintDC::SetBackground( const wxBrush &brush ) +void wxWindowDC::SetBackground( const wxBrush &brush ) { - if (!Ok()) return; + /* CMB 21/7/98: Added SetBackground. Sets background brush + * for Clear() and bg colour for shapes filled with cross-hatch brush */ + + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (m_backgroundBrush == brush) return; @@ -829,16 +999,18 @@ void wxPaintDC::SetBackground( const wxBrush &brush ) 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() ); 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 ); @@ -852,27 +1024,45 @@ void wxPaintDC::SetBackground( const wxBrush &brush ) { int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH; gdk_gc_set_stipple( m_bgGC, hatches[num] ); - } + } } -void wxPaintDC::SetLogicalFunction( int function ) +void wxWindowDC::SetLogicalFunction( int function ) { + wxCHECK_RET( Ok(), _T("invalid window dc") ); + if (m_logicalFunction == function) return; + GdkFunction mode = GDK_COPY; switch (function) { - case wxXOR: mode = GDK_INVERT; break; - case wxINVERT: mode = GDK_INVERT; break; + case wxXOR: mode = GDK_INVERT; break; + case wxINVERT: mode = GDK_INVERT; break; +#if (GDK_MINOR_VERSION > 0) + case wxOR_REVERSE: mode = GDK_OR_REVERSE; break; + case wxAND_REVERSE: mode = GDK_AND_REVERSE; break; + case wxCLEAR: mode = GDK_CLEAR; break; + case wxSET: mode = GDK_SET; break; + case wxOR_INVERT: mode = GDK_OR_INVERT; break; + case wxAND: mode = GDK_AND; break; + case wxOR: mode = GDK_OR; break; + case wxEQUIV: mode = GDK_EQUIV; break; + case wxNAND: mode = GDK_NAND; break; + case wxAND_INVERT: mode = GDK_AND_INVERT; break; +/* ? wxSRC_INVERT GDK_AND_REVERSE, GDK_OR_REVERSE, GDK_OR_INVERT */ +#endif default: break; } + m_logicalFunction = function; gdk_gc_set_function( m_penGC, mode ); gdk_gc_set_function( m_brushGC, mode ); + gdk_gc_set_function( m_textGC, mode ); } -void wxPaintDC::SetTextForeground( const wxColour &col ) +void wxWindowDC::SetTextForeground( const wxColour &col ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (m_textForegroundColour == col) return; @@ -883,9 +1073,9 @@ void wxPaintDC::SetTextForeground( const wxColour &col ) gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() ); } -void wxPaintDC::SetTextBackground( const wxColour &col ) +void wxWindowDC::SetTextBackground( const wxColour &col ) { - if (!Ok()) return; + wxCHECK_RET( Ok(), _T("invalid window dc") ); if (m_textBackgroundColour == col) return; @@ -896,12 +1086,15 @@ void wxPaintDC::SetTextBackground( const wxColour &col ) gdk_gc_set_background( m_textGC, m_textBackgroundColour.GetColor() ); } -void wxPaintDC::SetBackgroundMode( int mode ) +void wxWindowDC::SetBackgroundMode( int mode ) { + wxCHECK_RET( Ok(), _T("invalid window dc") ); + m_backgroundMode = mode; // 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, @@ -909,12 +1102,15 @@ void wxPaintDC::SetBackgroundMode( int mode ) } } -void wxPaintDC::SetPalette( const wxPalette& WXUNUSED(palette) ) +void wxWindowDC::SetPalette( const wxPalette& WXUNUSED(palette) ) { + wxFAIL_MSG( _T("wxWindowDC::SetPalette not implemented") ); } -void wxPaintDC::SetClippingRegion( long x, long y, long width, long height ) +void wxWindowDC::SetClippingRegion( long x, long y, long width, long height ) { + wxCHECK_RET( Ok(), _T("invalid window dc") ); + wxDC::SetClippingRegion( x, y, width, height ); GdkRectangle rect; @@ -928,8 +1124,26 @@ void wxPaintDC::SetClippingRegion( long x, long y, long width, long height ) gdk_gc_set_clip_rectangle( m_bgGC, &rect ); } -void wxPaintDC::DestroyClippingRegion(void) +void wxWindowDC::SetClippingRegion( const wxRegion ®ion ) +{ + wxCHECK_RET( Ok(), _T("invalid window dc") ); + + if (region.Empty()) + { + DestroyClippingRegion(); + return; + } + + gdk_gc_set_clip_region( m_penGC, region.GetRegion() ); + gdk_gc_set_clip_region( m_brushGC, region.GetRegion() ); + gdk_gc_set_clip_region( m_textGC, region.GetRegion() ); + gdk_gc_set_clip_region( m_bgGC, region.GetRegion() ); +} + +void wxWindowDC::DestroyClippingRegion() { + wxCHECK_RET( Ok(), _T("invalid window dc") ); + wxDC::DestroyClippingRegion(); gdk_gc_set_clip_rectangle( m_penGC, (GdkRectangle *) NULL ); @@ -938,7 +1152,7 @@ void wxPaintDC::DestroyClippingRegion(void) gdk_gc_set_clip_rectangle( m_bgGC, (GdkRectangle *) NULL ); } -void wxPaintDC::SetUpDC(void) +void wxWindowDC::SetUpDC() { Destroy(); m_ok = TRUE; @@ -947,13 +1161,29 @@ void wxPaintDC::SetUpDC(void) m_brushGC = gdk_gc_new( m_window ); m_textGC = gdk_gc_new( m_window ); m_bgGC = gdk_gc_new( m_window ); - SetTextForeground( m_textForegroundColour ); - SetTextBackground( m_textBackgroundColour ); - SetPen( m_pen ); - SetFont( m_font ); - SetBrush( m_brush ); - - gdk_gc_set_background( m_penGC, wxWHITE->GetColor() ); + + wxColour tmp_col( m_textForegroundColour ); + m_textForegroundColour = wxNullColour; + SetTextForeground( tmp_col ); + tmp_col = m_textBackgroundColour; + m_textBackgroundColour = wxNullColour; + SetTextBackground( tmp_col ); + + wxPen tmp_pen( m_pen ); + m_pen = wxNullPen; + SetPen( tmp_pen ); + + wxFont tmp_font( m_font ); + m_font = wxNullFont; + SetFont( tmp_font ); + + wxBrush tmp_brush( m_brush ); + m_brush = wxNullBrush; + SetBrush( tmp_brush ); + + tmp_brush = m_backgroundBrush; + m_backgroundBrush = wxNullBrush; + SetBackground( tmp_brush ); if (!hatch_bitmap) { @@ -967,7 +1197,7 @@ void wxPaintDC::SetUpDC(void) } } -void wxPaintDC::Destroy(void) +void wxWindowDC::Destroy() { if (m_penGC) gdk_gc_unref( m_penGC ); m_penGC = (GdkGC*) NULL; @@ -979,7 +1209,7 @@ void wxPaintDC::Destroy(void) m_bgGC = (GdkGC*) NULL; } -GdkWindow *wxPaintDC::GetWindow(void) +GdkWindow *wxWindowDC::GetWindow() { return m_window; } @@ -988,7 +1218,7 @@ GdkWindow *wxPaintDC::GetWindow(void) void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4, double b4); -void wx_clear_stack(void); +void wx_clear_stack(); int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3, double *y3, double *x4, double *y4); void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, @@ -1039,7 +1269,7 @@ static Stack wx_spline_stack[SPLINE_STACK_DEPTH]; static Stack *wx_stack_top; static int wx_stack_count; -void wx_clear_stack(void) +void wx_clear_stack() { wx_stack_top = wx_spline_stack; wx_stack_count = 0; @@ -1099,8 +1329,10 @@ static void wx_spline_draw_point_array(wxDC *dc) } } -void wxPaintDC::DrawSpline( wxList *points ) +void wxWindowDC::DrawSpline( wxList *points ) { + wxCHECK_RET( Ok(), _T("invalid window dc") ); + wxPoint *p; double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4; double x1, y1, x2, y2; @@ -1148,3 +1380,42 @@ void wxPaintDC::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 +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxPaintDC,wxWindowDC) + +wxPaintDC::wxPaintDC() + : wxWindowDC() +{ +} + +wxPaintDC::wxPaintDC( wxWindow *win ) + : wxWindowDC( win ) +{ +} + +//----------------------------------------------------------------------------- +// wxClientDC +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxClientDC,wxWindowDC) + +wxClientDC::wxClientDC() + : wxWindowDC() +{ +} + +wxClientDC::wxClientDC( wxWindow *win ) + : wxWindowDC( win ) +{ +} +