X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0a07a7d8528987ea635dbf111cf08f58c6d16090..2e6857fac2a88987fff1c63c8885252f679ac6ce:/src/gtk/dcclient.cpp?ds=sidebyside diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index 740f2b06da..92566a3da0 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -19,6 +19,7 @@ #include "wx/dcmemory.h" #include "wx/image.h" #include "wx/module.h" +#include "wx/log.h" #include "wx/gtk/win_gtk.h" @@ -54,7 +55,7 @@ static GdkPixmap *hatches[num_hatches]; static GdkPixmap **hatch_bitmap = (GdkPixmap **) NULL; -extern GtkWidget *wxRootWindow; +extern GtkWidget *wxGetRootWindow(); //----------------------------------------------------------------------------- // constants @@ -77,15 +78,15 @@ static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } #include "gdk/gdkprivate.h" -void gdk_wx_draw_bitmap (GdkDrawable *drawable, - GdkGC *gc, - GdkDrawable *src, - gint xsrc, - gint ysrc, - gint xdest, - gint ydest, - gint width, - gint height) +void gdk_wx_draw_bitmap(GdkDrawable *drawable, + GdkGC *gc, + GdkDrawable *src, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) { gint src_width, src_height; #ifndef __WXGTK20__ @@ -246,6 +247,8 @@ wxWindowDC::wxWindowDC() wxWindowDC::wxWindowDC( wxWindow *window ) { + wxASSERT_MSG( window, wxT("DC needs a window") ); + m_penGC = (GdkGC *) NULL; m_brushGC = (GdkGC *) NULL; m_textGC = (GdkGC *) NULL; @@ -256,8 +259,6 @@ wxWindowDC::wxWindowDC( wxWindow *window ) m_isScreenDC = FALSE; m_font = window->GetFont(); - wxASSERT_MSG( window, wxT("DC needs a window") ); - GtkWidget *widget = window->m_wxwindow; // some controls don't have m_wxwindow - like wxStaticBox, but the user @@ -400,10 +401,13 @@ void wxWindowDC::DoGetSize( int* width, int* height ) const m_owner->GetSize(width, height); } -void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), - const wxColour &WXUNUSED(col), int WXUNUSED(style) ) +extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, + const wxColour & col, int style); + +bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y, + const wxColour& col, int style) { - wxFAIL_MSG( wxT("wxWindowDC::DoFloodFill not implemented") ); + return wxDoFloodFill(this, x, y, col, style); } bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const @@ -415,8 +419,8 @@ bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const memdc.SelectObject(bitmap); memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1); memdc.SelectObject(wxNullBitmap); - - wxImage image(bitmap); + + wxImage image = bitmap.ConvertToImage(); col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0)); return TRUE; } @@ -951,7 +955,7 @@ void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord hei gdk_draw_arc( m_window, m_penGC, FALSE, xx, yy, ww, hh, 0, 360*64 ); } - CalcBoundingBox( x - width, y - height ); + CalcBoundingBox( x, y ); CalcBoundingBox( x + width, y + height ); } @@ -999,18 +1003,18 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, wxBitmap use_bitmap; if ((w != ww) || (h != hh)) { - wxImage image( bitmap ); + wxImage image = bitmap.ConvertToImage(); image.Rescale( ww, hh ); if (is_mono) - use_bitmap = image.ConvertToMonoBitmap(255,255,255); + use_bitmap = wxBitmap(image.ConvertToMono(255,255,255), 1); else - use_bitmap = image.ConvertToBitmap(); + use_bitmap = wxBitmap(image); } else { use_bitmap = bitmap; } - + /* apply mask if any */ GdkBitmap *mask = (GdkBitmap *) NULL; if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); @@ -1018,10 +1022,11 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, if (useMask && mask) { GdkBitmap *new_mask = (GdkBitmap*) NULL; +#ifndef __WXGTK20__ // TODO fix crash if (!m_currentClippingRegion.IsNull()) { GdkColor col; - new_mask = gdk_pixmap_new( wxRootWindow->window, ww, hh, 1 ); + 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 ); @@ -1037,7 +1042,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh ); gdk_gc_unref( gc ); } - +#endif if (is_mono) { if (new_mask) @@ -1054,6 +1059,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, gdk_gc_set_clip_mask( m_penGC, mask ); gdk_gc_set_clip_origin( m_penGC, xx, yy ); } + if (new_mask) gdk_bitmap_unref( new_mask ); } @@ -1085,9 +1091,13 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, } } -bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, - wxDC *source, wxCoord xsrc, wxCoord ysrc, - int logical_func, bool useMask ) +bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, + wxCoord width, wxCoord height, + wxDC *source, + wxCoord xsrc, wxCoord ysrc, + int logical_func, + bool useMask, + wxCoord xsrcMask, wxCoord ysrcMask ) { /* this is the nth try to get this utterly useless function to work. it now completely ignores the scaling or translation @@ -1100,12 +1110,24 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he if (!m_window) return FALSE; +#if 1 + // transform the source DC coords to the device ones + xsrc = source->XLOG2DEV(xsrc); + ysrc = source->YLOG2DEV(ysrc); +#endif + wxClientDC *srcDC = (wxClientDC*)source; wxMemoryDC *memDC = (wxMemoryDC*)source; bool use_bitmap_method = FALSE; bool is_mono = FALSE; + /* TODO: use the mask origin when drawing transparently */ + if (xsrcMask == -1 && ysrcMask == -1) + { + xsrcMask = xsrc; ysrcMask = ysrc; + } + if (srcDC->m_isMemDC) { if (!memDC->m_selected.Ok()) return FALSE; @@ -1183,13 +1205,13 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he if ((bm_width != bm_ww) || (bm_height != bm_hh)) { - wxImage image( memDC->m_selected ); + wxImage image = memDC->m_selected.ConvertToImage(); image = image.Scale( bm_ww, bm_hh ); if (is_mono) - use_bitmap = image.ConvertToMonoBitmap(255,255,255); + use_bitmap = wxBitmap(image.ConvertToMono(255,255,255), 1); else - use_bitmap = image.ConvertToBitmap(); + use_bitmap = wxBitmap(image); } else { @@ -1203,10 +1225,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he if (useMask && mask) { GdkBitmap *new_mask = (GdkBitmap*) NULL; +#ifndef __WXGTK20__ // TODO fix crash if (!m_currentClippingRegion.IsNull()) { GdkColor col; - new_mask = gdk_pixmap_new( wxRootWindow->window, bm_ww, bm_hh, 1 ); + 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 ); @@ -1222,7 +1245,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); gdk_gc_unref( gc ); } - +#endif if (is_mono) { if (new_mask) @@ -1297,11 +1320,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN ); /* scale image */ - wxImage image( bitmap ); + wxImage image = bitmap.ConvertToImage(); image = image.Scale( ww, hh ); /* convert to bitmap */ - bitmap = image.ConvertToBitmap(); + bitmap = wxBitmap(image); /* draw scaled bitmap */ gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); @@ -1334,19 +1357,19 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) wxCHECK_RET( font, wxT("invalid font") ); -#ifdef __WXGTK20__ +#if defined(__WXGTK20__) wxCHECK_RET( m_context, wxT("no Pango context") ); #endif x = XLOG2DEV(x); y = YLOG2DEV(y); -#ifdef __WXGTK20__ - /* FIXME: the layout engine should probably be abstracted at a higher level in wxDC... */ +#if defined(__WXGTK20__) && wxUSE_WCHAR_T + // TODO: the layout engine should be abstracted at a higher level! PangoLayout *layout = pango_layout_new(m_context); pango_layout_set_font_description(layout, m_fontdesc); { - wxWX2MBbuf data = text.mb_str(wxConvUTF8); + const wxWX2MBbuf data = text.mb_str(wxConvUTF8); pango_layout_set_text(layout, data, strlen(data)); } PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data; @@ -1355,18 +1378,18 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) wxCoord width = rect.width; wxCoord height = rect.height; gdk_draw_layout( m_window, m_textGC, x, y, layout ); -#else +#else // GTK+ 1.x wxCoord width = gdk_string_width( font, text.mbc_str() ); wxCoord height = font->ascent + font->descent; - /* CMB 21/5/98: draw text background if mode is wxSOLID */ - if (m_backgroundMode == wxSOLID) + + if ( m_backgroundMode == wxSOLID ) { 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.mbc_str() ); -#endif +#endif // GTK+ 2.0/1.x /* CMB 17/7/98: simple underline: ignores scaling and underlying X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS @@ -1378,7 +1401,7 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y); } -#ifdef __WXGTK20__ +#if defined(__WXGTK20__) && wxUSE_WCHAR_T g_object_unref( G_OBJECT( layout ) ); #endif @@ -1417,7 +1440,6 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, dc.SetBrush(*wxBLACK_BRUSH); dc.Clear(); dc.DrawText(text, 0, 0); - dc.SetFont(wxNullFont); dc.SelectObject(wxNullBitmap); // Calculate the size of the rotated bounding box. @@ -1441,7 +1463,7 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, minY = (wxCoord)(dmin(y2, dmin(y3, y4)) - 0.5); // prepare to blit-with-rotate the bitmap to the DC - wxImage image(src); + wxImage image = src.ConvertToImage(); GdkColor *colText = m_textForegroundColour.GetColor(), *colBack = m_textBackgroundColour.GetColor(); @@ -1547,9 +1569,7 @@ void wxWindowDC::Clear() if (m_owner) { - int width,height; - m_owner->GetSize( &width, &height ); - gdk_draw_rectangle( m_window, m_bgGC, TRUE, 0, 0, width, height ); + m_owner->Clear(); return; } @@ -1564,6 +1584,8 @@ void wxWindowDC::Clear() void wxWindowDC::SetFont( const wxFont &font ) { + wxCHECK_RET( font.Ok(), _T("invalid font in wxWindowDC::SetFont") ); + m_font = font; #ifdef __WXGTK20__ // fix fontdesc? @@ -1862,30 +1884,36 @@ void wxWindowDC::SetTextForeground( const wxColour &col ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); - if (m_textForegroundColour == col) return; + // don't set m_textForegroundColour to an invalid colour as we'd crash + // later then (we use m_textForegroundColour.GetColor() without checking + // in a few places) + if ( !col.Ok() || (m_textForegroundColour == col) ) + return; m_textForegroundColour = col; - if (!m_textForegroundColour.Ok()) return; - if (!m_window) return; - - m_textForegroundColour.CalcPixel( m_cmap ); - gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() ); + if ( m_window ) + { + m_textForegroundColour.CalcPixel( m_cmap ); + gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() ); + } } void wxWindowDC::SetTextBackground( const wxColour &col ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); - if (m_textBackgroundColour == col) return; + // same as above + if ( !col.Ok() || (m_textBackgroundColour == col) ) + return; m_textBackgroundColour = col; - if (!m_textBackgroundColour.Ok()) return; - - if (!m_window) return; - m_textBackgroundColour.CalcPixel( m_cmap ); - gdk_gc_set_background( m_textGC, m_textBackgroundColour.GetColor() ); + if ( m_window ) + { + m_textBackgroundColour.CalcPixel( m_cmap ); + gdk_gc_set_background( m_textGC, m_textBackgroundColour.GetColor() ); + } } void wxWindowDC::SetBackgroundMode( int mode ) @@ -2041,7 +2069,7 @@ void wxWindowDC::ComputeScaleAndOrigin() // Resolution in pixels per logical inch wxSize wxWindowDC::GetPPI() const { - return wxSize(100, 100); + return wxSize( (int) (m_mm_to_pix_x * 25.4 + 0.5), (int) (m_mm_to_pix_y * 25.4 + 0.5)); } int wxWindowDC::GetDepth() const @@ -2051,175 +2079,6 @@ int wxWindowDC::GetDepth() const return -1; } -#if wxUSE_SPLINES -// ----------------------------------- spline code ---------------------------------------- - -void wx_quadratic_spline(double a1, double b1, double a2, double b2, - double a3, double b3, double a4, double b4); -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, - double x4, double y4); -static bool wx_spline_add_point(double x, double y); -static void wx_spline_draw_point_array(wxDC *dc); - -wxList wx_spline_point_list; - -#define half(z1, z2) ((z1+z2)/2.0) -#define THRESHOLD 5 - -/* iterative version */ - -void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4, - double b4) -{ - register double xmid, ymid; - double x1, y1, x2, y2, x3, y3, x4, y4; - - wx_clear_stack(); - wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4); - - while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) { - xmid = (double)half(x2, x3); - ymid = (double)half(y2, y3); - if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD && - fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) { - wx_spline_add_point( x1, y1 ); - wx_spline_add_point( xmid, ymid ); - } else { - wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3), - (double)half(x3, x4), (double)half(y3, y4), x4, y4); - wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2), - (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid); - } - } -} - -/* utilities used by spline drawing routines */ - -typedef struct wx_spline_stack_struct { - double x1, y1, x2, y2, x3, y3, x4, y4; -} Stack; - -#define SPLINE_STACK_DEPTH 20 -static Stack wx_spline_stack[SPLINE_STACK_DEPTH]; -static Stack *wx_stack_top; -static int wx_stack_count; - -void wx_clear_stack() -{ - wx_stack_top = wx_spline_stack; - wx_stack_count = 0; -} - -void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) -{ - wx_stack_top->x1 = x1; - wx_stack_top->y1 = y1; - wx_stack_top->x2 = x2; - wx_stack_top->y2 = y2; - wx_stack_top->x3 = x3; - wx_stack_top->y3 = y3; - wx_stack_top->x4 = x4; - wx_stack_top->y4 = y4; - wx_stack_top++; - wx_stack_count++; -} - -int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, - double *x3, double *y3, double *x4, double *y4) -{ - if (wx_stack_count == 0) - return (0); - wx_stack_top--; - wx_stack_count--; - *x1 = wx_stack_top->x1; - *y1 = wx_stack_top->y1; - *x2 = wx_stack_top->x2; - *y2 = wx_stack_top->y2; - *x3 = wx_stack_top->x3; - *y3 = wx_stack_top->y3; - *x4 = wx_stack_top->x4; - *y4 = wx_stack_top->y4; - return (1); -} - -static bool wx_spline_add_point(double x, double y) -{ - wxPoint *point = new wxPoint ; - point->x = (int) x; - point->y = (int) y; - wx_spline_point_list.Append((wxObject*)point); - return TRUE; -} - -static void wx_spline_draw_point_array(wxDC *dc) -{ - dc->DrawLines(&wx_spline_point_list, 0, 0 ); - wxNode *node = wx_spline_point_list.First(); - while (node) - { - wxPoint *point = (wxPoint *)node->Data(); - delete point; - delete node; - node = wx_spline_point_list.First(); - } -} - -void wxWindowDC::DoDrawSpline( wxList *points ) -{ - wxCHECK_RET( Ok(), wxT("invalid window dc") ); - - wxPoint *p; - double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4; - double x1, y1, x2, y2; - - wxNode *node = points->First(); - p = (wxPoint *)node->Data(); - - x1 = p->x; - y1 = p->y; - - node = node->Next(); - p = (wxPoint *)node->Data(); - - x2 = p->x; - y2 = p->y; - cx1 = (double)((x1 + x2) / 2); - cy1 = (double)((y1 + y2) / 2); - cx2 = (double)((cx1 + x2) / 2); - cy2 = (double)((cy1 + y2) / 2); - - wx_spline_add_point(x1, y1); - - while ((node = node->Next()) != NULL) - { - p = (wxPoint *)node->Data(); - x1 = x2; - y1 = y2; - x2 = p->x; - y2 = p->y; - cx4 = (double)(x1 + x2) / 2; - cy4 = (double)(y1 + y2) / 2; - cx3 = (double)(x1 + cx4) / 2; - cy3 = (double)(y1 + cy4) / 2; - - wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4); - - cx1 = cx4; - cy1 = cy4; - cx2 = (double)(cx1 + x2) / 2; - cy2 = (double)(cy1 + y2) / 2; - } - - wx_spline_add_point( cx1, cy1 ); - wx_spline_add_point( x2, y2 ); - - wx_spline_draw_point_array( this ); -} - -#endif // wxUSE_SPLINE //----------------------------------------------------------------------------- // wxPaintDC @@ -2238,14 +2097,19 @@ wxPaintDC::wxPaintDC( wxWindow *win ) GdkRegion *region = m_paintClippingRegion.GetRegion(); if ( region ) { - m_currentClippingRegion.Union( m_paintClippingRegion ); + m_paintClippingRegion = win->GetUpdateRegion(); + GdkRegion *region = m_paintClippingRegion.GetRegion(); + if ( region ) + { + m_currentClippingRegion.Union( m_paintClippingRegion ); - 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 ); + 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 +#endif // USE_PAINT_REGION } //----------------------------------------------------------------------------- @@ -2257,6 +2121,14 @@ IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC) wxClientDC::wxClientDC( wxWindow *win ) : wxWindowDC( win ) { + wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") ); + +#ifdef __WXUNIVERSAL__ + wxPoint ptOrigin = win->GetClientAreaOrigin(); + SetDeviceOrigin(ptOrigin.x, ptOrigin.y); + wxSize size = win->GetClientSize(); + SetClippingRegion(wxPoint(0, 0), size); +#endif // __WXUNIVERSAL__ } void wxClientDC::DoGetSize(int *width, int *height) const