/////////////////////////////////////////////////////////////////////////////
// Name: src/gtk/dcclient.cpp
-// Purpose:
+// Purpose: wxWindowDCImpl implementation
// Author: Robert Roebling
// RCS-ID: $Id$
// Copyright: (c) 1998 Robert Roebling, Chris Breeze
const int i = style - wxBRUSHSTYLE_FIRST_HATCH;
if (hatches[i] == NULL)
{
+ // This macro creates a bitmap from an XBM file included above. Notice
+ // the need for the cast because gdk_bitmap_create_from_data() doesn't
+ // accept unsigned data but the arrays in XBM need to be unsigned to
+ // avoid warnings (and even errors in C+0x mode) from g++.
+#define CREATE_FROM_XBM_DATA(name) \
+ gdk_bitmap_create_from_data \
+ ( \
+ NULL, \
+ reinterpret_cast<gchar *>(name ## _bits), \
+ name ## _width, \
+ name ## _height \
+ )
+
switch (style)
{
case wxBRUSHSTYLE_BDIAGONAL_HATCH:
- hatches[i] = gdk_bitmap_create_from_data(NULL, bdiag_bits, bdiag_width, bdiag_height);
+ hatches[i] = CREATE_FROM_XBM_DATA(bdiag);
break;
case wxBRUSHSTYLE_CROSSDIAG_HATCH:
- hatches[i] = gdk_bitmap_create_from_data(NULL, cdiag_bits, cdiag_width, cdiag_height);
+ hatches[i] = CREATE_FROM_XBM_DATA(cdiag);
break;
case wxBRUSHSTYLE_CROSS_HATCH:
- hatches[i] = gdk_bitmap_create_from_data(NULL, cross_bits, cross_width, cross_height);
+ hatches[i] = CREATE_FROM_XBM_DATA(cross);
break;
case wxBRUSHSTYLE_FDIAGONAL_HATCH:
- hatches[i] = gdk_bitmap_create_from_data(NULL, fdiag_bits, fdiag_width, fdiag_height);
+ hatches[i] = CREATE_FROM_XBM_DATA(fdiag);
break;
case wxBRUSHSTYLE_HORIZONTAL_HATCH:
- hatches[i] = gdk_bitmap_create_from_data(NULL, horiz_bits, horiz_width, horiz_height);
+ hatches[i] = CREATE_FROM_XBM_DATA(horiz);
break;
case wxBRUSHSTYLE_VERTICAL_HATCH:
- hatches[i] = gdk_bitmap_create_from_data(NULL, verti_bits, verti_width, verti_height);
+ hatches[i] = CREATE_FROM_XBM_DATA(verti);
break;
}
+
+#undef CREATE_FROM_XBM_DATA
}
return hatches[i];
}
// The realloc failed. Fall through to error.
wxFAIL_MSG( wxT("No GC available") );
- return (GdkGC*) NULL;
+ return NULL;
}
static void wxFreePoolGC( GdkGC *gc )
wxWindowDCImpl::wxWindowDCImpl( wxDC *owner ) :
wxGTKDCImpl( owner )
{
- m_gdkwindow = (GdkWindow*) NULL;
- m_penGC = (GdkGC *) NULL;
- m_brushGC = (GdkGC *) NULL;
- m_textGC = (GdkGC *) NULL;
- m_bgGC = (GdkGC *) NULL;
- m_cmap = (GdkColormap *) NULL;
+ m_gdkwindow = NULL;
+ m_penGC = NULL;
+ m_brushGC = NULL;
+ m_textGC = NULL;
+ m_bgGC = NULL;
+ m_cmap = NULL;
m_isScreenDC = false;
- m_context = (PangoContext *)NULL;
- m_layout = (PangoLayout *)NULL;
- m_fontdesc = (PangoFontDescription *)NULL;
+ m_context = NULL;
+ m_layout = NULL;
+ m_fontdesc = NULL;
}
wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window ) :
{
wxASSERT_MSG( window, wxT("DC needs a window") );
- m_gdkwindow = (GdkWindow*) NULL;
- m_penGC = (GdkGC *) NULL;
- m_brushGC = (GdkGC *) NULL;
- m_textGC = (GdkGC *) NULL;
- m_bgGC = (GdkGC *) NULL;
- m_cmap = (GdkColormap *) NULL;
+ m_gdkwindow = NULL;
+ m_penGC = NULL;
+ m_brushGC = NULL;
+ m_textGC = NULL;
+ m_bgGC = NULL;
+ m_cmap = NULL;
m_isScreenDC = false;
m_font = window->GetFont();
GtkWidget *widget = window->m_wxwindow;
+ m_gdkwindow = window->GTKGetDrawingWindow();
// Some controls don't have m_wxwindow - like wxStaticBox, but the user
- // code should still be able to create wxClientDCs for them, so we will
- // use the parent window here then.
+ // code should still be able to create wxClientDCs for them
if ( !widget )
{
- window = window->GetParent();
- widget = window->m_wxwindow;
- }
+ widget = window->m_widget;
+
+ wxCHECK_RET(widget, "DC needs a widget");
- wxASSERT_MSG( widget, wxT("DC needs a widget") );
+ m_gdkwindow = widget->window;
+ if (!gtk_widget_get_has_window(widget))
+ SetDeviceLocalOrigin(widget->allocation.x, widget->allocation.y);
+ }
- m_context = window->GtkGetPangoDefaultContext();
+ m_context = window->GTKGetPangoDefaultContext();
m_layout = pango_layout_new( m_context );
m_fontdesc = pango_font_description_copy( widget->style->font_desc );
- m_gdkwindow = widget->window;
-
// Window not realized ?
if (!m_gdkwindow)
{
return;
}
- m_cmap = gtk_widget_get_colormap( widget ? widget : window->m_widget );
+ m_cmap = gtk_widget_get_colormap(widget);
SetUpDC();
m_window = window;
- if (m_window && m_window->m_wxwindow &&
+ if (m_window && m_window->m_wxwindow &&
(m_window->GetLayoutDirection() == wxLayout_RightToLeft))
{
// reverse sense
}
if (!done)
- {
+ {
if (m_isScreenDC)
{
m_penGC = wxGetPoolGC( m_gdkwindow, wxPEN_SCREEN );
gdk_gc_set_function( m_penGC, GDK_COPY );
/* clipping */
- gdk_gc_set_clip_rectangle( m_penGC, (GdkRectangle *) NULL );
- gdk_gc_set_clip_rectangle( m_brushGC, (GdkRectangle *) NULL );
- gdk_gc_set_clip_rectangle( m_textGC, (GdkRectangle *) NULL );
- gdk_gc_set_clip_rectangle( m_bgGC, (GdkRectangle *) NULL );
+ gdk_gc_set_clip_rectangle( m_penGC, NULL );
+ gdk_gc_set_clip_rectangle( m_brushGC, NULL );
+ gdk_gc_set_clip_rectangle( m_textGC, NULL );
+ gdk_gc_set_clip_rectangle( m_bgGC, NULL );
}
void wxWindowDCImpl::DoGetSize( int* width, int* height ) const
{
- wxCHECK_RET( m_window, _T("GetSize() doesn't work without window") );
+ wxCHECK_RET( m_window, wxT("GetSize() doesn't work without window") );
m_window->GetSize(width, height);
}
bool wxWindowDCImpl::DoFloodFill(wxCoord x, wxCoord y,
- const wxColour& col, int style)
+ const wxColour& col, wxFloodFillStyle style)
{
#if wxUSE_IMAGE
extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
- const wxColour & col, int style);
+ const wxColour & col, wxFloodFillStyle style);
return wxDoFloodFill( GetOwner(), x, y, col, style);
#else
void wxWindowDCImpl::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
{
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
-
- if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT)
+
+ if ( m_pen.IsNonTransparent() )
{
if (m_gdkwindow)
gdk_draw_line( m_gdkwindow, m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
{
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
- if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT)
+ if ( m_pen.IsNonTransparent() )
{
int w = 0;
int h = 0;
if (m_gdkwindow)
{
- if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT)
+ if ( m_brush.IsNonTransparent() )
{
GdkGC* gc;
bool originChanged;
gdk_gc_set_ts_origin(gc, 0, 0);
}
- if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT)
+ if ( m_pen.IsNonTransparent() )
{
gdk_draw_arc( m_gdkwindow, m_penGC, FALSE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
- if ((m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT) && (alpha2 - alpha1 != 360*64))
+ if ( m_brush.IsNonTransparent() && (alpha2 - alpha1 != 360*64) )
{
gdk_draw_line( m_gdkwindow, m_penGC, xx1, yy1, xxc, yyc );
gdk_draw_line( m_gdkwindow, m_penGC, xxc, yyc, xx2, yy2 );
wxCoord start = wxCoord(sa * 64.0);
wxCoord end = wxCoord((ea-sa) * 64.0);
- if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT)
+ if ( m_brush.IsNonTransparent() )
{
GdkGC* gc;
bool originChanged;
gdk_gc_set_ts_origin(gc, 0, 0);
}
- if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT)
+ if ( m_pen.IsNonTransparent() )
gdk_draw_arc( m_gdkwindow, m_penGC, FALSE, xx, yy, ww, hh, start, end );
}
{
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
- if ((m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT) && m_gdkwindow)
+ if ( m_pen.IsNonTransparent() && m_gdkwindow )
gdk_draw_point( m_gdkwindow, m_penGC, XLOG2DEV(x), YLOG2DEV(y) );
CalcBoundingBox (x, y);
{
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
- if (m_pen.GetStyle() == wxPENSTYLE_TRANSPARENT) return;
if (n <= 0) return;
+ if ( m_pen.IsTransparent() )
+ return;
+
//Check, if scaling is necessary
const bool doScale =
xoffset != 0 || yoffset != 0 || XLOG2DEV(10) != 10 || YLOG2DEV(10) != 10;
delete[] gpts;
}
-void wxWindowDCImpl::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int WXUNUSED(fillStyle) )
+void wxWindowDCImpl::DoDrawPolygon( int n, wxPoint points[],
+ wxCoord xoffset, wxCoord yoffset,
+ wxPolygonFillMode WXUNUSED(fillStyle) )
{
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
if (m_gdkwindow)
{
- if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT)
+ if ( m_brush.IsNonTransparent() )
{
GdkGC* gc;
bool originChanged;
gdk_gc_set_ts_origin(gc, 0, 0);
}
- if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT)
+ if ( m_pen.IsNonTransparent() )
{
/*
for (i = 0 ; i < n ; i++)
if (m_gdkwindow)
{
- if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT)
+ if ( m_brush.IsNonTransparent() )
{
GdkGC* gc;
bool originChanged;
gdk_gc_set_ts_origin(gc, 0, 0);
}
- if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT)
+ if ( m_pen.IsNonTransparent() )
{
-#if 1
if ((m_pen.GetWidth() == 2) && (m_pen.GetCap() == wxCAP_ROUND) &&
(m_pen.GetJoin() == wxJOIN_ROUND) && (m_pen.GetStyle() == wxPENSTYLE_SOLID))
{
gdk_gc_set_line_attributes( m_penGC, 2, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND );
}
else
-#endif
{
// Just use X11 for other cases
gdk_draw_rectangle( m_gdkwindow, m_penGC, FALSE, xx, yy, ww-1, hh-1 );
// CMB: adjust size if outline is drawn otherwise the result is
// 1 pixel too wide and high
- if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT)
+ if ( m_pen.IsNonTransparent() )
{
ww--;
hh--;
if (dd > hh) dd = hh;
rr = dd / 2;
- if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT)
+ if ( m_brush.IsNonTransparent() )
{
GdkGC* gc;
bool originChanged;
gdk_gc_set_ts_origin(gc, 0, 0);
}
- if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT)
+ if ( m_pen.IsNonTransparent() )
{
gdk_draw_line( m_gdkwindow, m_penGC, xx+rr+1, yy, xx+ww-rr, yy );
gdk_draw_line( m_gdkwindow, m_penGC, xx+rr+1, yy+hh, xx+ww-rr, yy+hh );
if (m_gdkwindow)
{
- if (m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT)
+ if ( m_brush.IsNonTransparent() )
{
GdkGC* gc;
bool originChanged;
// If the pen is transparent pen we increase the size
// for better compatibility with other platforms.
- if (m_pen.GetStyle() == wxPENSTYLE_TRANSPARENT)
+ if ( m_pen.IsNonTransparent() )
{
++ww;
++hh;
gdk_gc_set_ts_origin(gc, 0, 0);
}
- if (m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT)
+ if ( m_pen.IsNonTransparent() )
gdk_draw_arc( m_gdkwindow, m_penGC, false, xx, yy, ww, hh, 0, 360*64 );
}
// Make a new mask from part of a mask and a clip region.
// Return new mask, unref old one.
static GdkPixmap*
-ClipMask(GdkPixmap* mask, const GdkRegion* clipRegion, int x, int y, int dst_x, int dst_y, int w, int h)
+ClipMask(GdkPixmap* mask, GdkRegion* clipRegion, int x, int y, int dst_x, int dst_y, int w, int h)
{
GdkGCValues gcValues;
gcValues.foreground.pixel = 0;
const int w = bitmap.GetWidth();
const int h = bitmap.GetHeight();
+ // notice that as the bitmap is not drawn upside down (or right to left)
+ // even if the corresponding axis direction is inversed, we need to take it
+ // into account when calculating its bounding box
CalcBoundingBox(x, y);
- CalcBoundingBox(x + w, y + h);
+ CalcBoundingBox(x + m_signX*w, y + m_signY*h);
// device coords
int xx = LogicalToDeviceX(x);
if (m_window && m_window->GetLayoutDirection() == wxLayout_RightToLeft)
xx -= ww;
- const GdkRegion* const clipRegion = m_currentClippingRegion.GetRegion();
+ GdkRegion* const clipRegion = m_currentClippingRegion.GetRegion();
// determine clip region overlap
int overlap = wxInRegion;
if (clipRegion)
wxCoord width, wxCoord height,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
- int logical_func,
+ wxRasterOperationMode logical_func,
bool useMask,
wxCoord xsrcMask, wxCoord ysrcMask )
{
const int dst_w = LogicalToDeviceXRel(width);
const int dst_h = LogicalToDeviceYRel(height);
- const GdkRegion* const clipRegion = m_currentClippingRegion.GetRegion();
+ GdkRegion* const clipRegion = m_currentClippingRegion.GetRegion();
// determine dest clip region overlap
int overlap = wxInRegion;
if (clipRegion)
src_y = 0;
}
- const int logical_func_save = m_logicalFunction;
+ const wxRasterOperationMode logical_func_save = m_logicalFunction;
SetLogicalFunction(logical_func);
if (memDC == NULL)
gdk_gc_set_subwindow(use_gc, GDK_INCLUDE_INFERIORS);
return true;
}
-void wxWindowDCImpl::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
+void wxWindowDCImpl::DoDrawText(const wxString& text,
+ wxCoord xLogical,
+ wxCoord yLogical)
{
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
if (text.empty()) return;
- x = XLOG2DEV(x);
- y = YLOG2DEV(y);
+ wxCoord x = XLOG2DEV(xLogical),
+ y = YLOG2DEV(yLogical);
wxCHECK_RET( m_context, wxT("no Pango context") );
wxCHECK_RET( m_layout, wxT("no Pango layout") );
x_rtl -= w;
const GdkColor* bg_col = NULL;
- if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
+ if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
bg_col = m_textBackgroundColour.GetColor();
-
+
gdk_draw_layout_with_colors(m_gdkwindow, m_textGC, x_rtl, y, m_layout, NULL, bg_col);
if (isScaled)
pango_layout_set_attributes(m_layout, NULL);
}
- CalcBoundingBox(x + int(w / m_scaleX), y + int(h / m_scaleY));
- CalcBoundingBox(x, y);
+ CalcBoundingBox(xLogical + int(w / m_scaleX), yLogical + int(h / m_scaleY));
+ CalcBoundingBox(xLogical, yLogical);
}
-// TODO: When GTK2.6 is required, merge DoDrawText and DoDrawRotatedText to
+// TODO: When GTK2.6 is required, merge DoDrawText and DoDrawRotatedText to
// avoid code duplication
void wxWindowDCImpl::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
{
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
-#if __WXGTK26__
+#ifdef __WXGTK26__
if (!gtk_check_version(2,6,0))
{
x = XLOG2DEV(x);
pango_layout_get_pixel_size(m_layout, &w, &h);
const GdkColor* bg_col = NULL;
- if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
+ if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
bg_col = m_textBackgroundColour.GetColor();
// rotate the text
pango_context_set_matrix (m_context, &matrix);
pango_layout_context_changed (m_layout);
- // To be compatible with MSW, the rotation axis must be in the old
+ // To be compatible with MSW, the rotation axis must be in the old
// top-left corner.
- // Calculate the vertices of the rotated rectangle containing the text,
+ // Calculate the vertices of the rotated rectangle containing the text,
// relative to the old top-left vertex.
- // We could use the matrix for this, but it's simpler with trignonometry.
+ // We could use the matrix for this, but it's simpler with trignonometry.
double rad = DegToRad(angle);
- // the rectangle vertices are counted clockwise with the first one
+ // the rectangle vertices are counted clockwise with the first one
// being at (0, 0)
double x2 = w * cos(rad);
double y2 = -w * sin(rad); // y axis points to the bottom, hence minus
minX = (wxCoord)(dmin(dmin(0, x2), dmin(x3, x4)) - 0.5),
minY = (wxCoord)(dmin(dmin(0, y2), dmin(y3, y4)) - 0.5);
- gdk_draw_layout_with_colors(m_gdkwindow, m_textGC, x+minX, y+minY,
+ gdk_draw_layout_with_colors(m_gdkwindow, m_textGC, x+minX, y+minY,
m_layout, NULL, bg_col);
if (m_font.GetUnderlined())
wxCoord wxWindowDCImpl::GetCharHeight() const
{
PangoFontMetrics *metrics = pango_context_get_metrics (m_context, m_fontdesc, pango_context_get_language(m_context));
- wxCHECK_MSG( metrics, -1, _T("failed to get pango font metrics") );
+ wxCHECK_MSG( metrics, -1, wxT("failed to get pango font metrics") );
wxCoord h = PANGO_PIXELS (pango_font_metrics_get_descent (metrics) +
- pango_font_metrics_get_ascent (metrics));
+ pango_font_metrics_get_ascent (metrics));
pango_font_metrics_unref (metrics);
return h;
}
{
PangoContext *oldContext = m_context;
- m_context = m_window->GtkGetPangoDefaultContext();
+ m_context = m_window->GTKGetPangoDefaultContext();
// If we switch back/forth between different contexts
// we also have to create a new layout. I think so,
case wxPENSTYLE_SOLID:
default:
lineStyle = GDK_LINE_SOLID;
- req_dash = (wxGTKDash*)NULL;
+ req_dash = NULL;
req_nb_dash = 0;
break;
}
}
}
-void wxWindowDCImpl::SetLogicalFunction( int function )
+void wxWindowDCImpl::SetLogicalFunction( wxRasterOperationMode function )
{
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
case wxSRC_INVERT: mode = GDK_COPY_INVERT; break;
case wxNOR: mode = GDK_NOR; break;
default:
- wxFAIL_MSG( wxT("unsupported logical function") );
- mode = GDK_COPY;
+ wxFAIL_MSG("unknown mode");
+ return;
}
m_logicalFunction = function;
rect.width = XLOG2DEVREL(width);
rect.height = YLOG2DEVREL(height);
- if (m_window && m_window->m_wxwindow &&
+ if (m_window && m_window->m_wxwindow &&
(m_window->GetLayoutDirection() == wxLayout_RightToLeft))
{
rect.x -= rect.width;
void wxWindowDCImpl::Destroy()
{
if (m_penGC) wxFreePoolGC( m_penGC );
- m_penGC = (GdkGC*) NULL;
+ m_penGC = NULL;
if (m_brushGC) wxFreePoolGC( m_brushGC );
- m_brushGC = (GdkGC*) NULL;
+ m_brushGC = NULL;
if (m_textGC) wxFreePoolGC( m_textGC );
- m_textGC = (GdkGC*) NULL;
+ m_textGC = NULL;
if (m_bgGC) wxFreePoolGC( m_bgGC );
- m_bgGC = (GdkGC*) NULL;
+ m_bgGC = NULL;
}
void wxWindowDCImpl::SetDeviceOrigin( wxCoord x, wxCoord y )
m_signX = (xLeftRight ? 1 : -1);
m_signY = (yBottomUp ? -1 : 1);
- if (m_window && m_window->m_wxwindow &&
+ if (m_window && m_window->m_wxwindow &&
(m_window->GetLayoutDirection() == wxLayout_RightToLeft))
m_signX = -m_signX;
wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *win )
: wxWindowDCImpl( owner, win )
{
- wxCHECK_RET( win, _T("NULL window in wxClientDCImpl::wxClientDC") );
+ wxCHECK_RET( win, wxT("NULL window in wxClientDCImpl::wxClientDC") );
#ifdef __WXUNIVERSAL__
wxPoint ptOrigin = win->GetClientAreaOrigin();
SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
wxSize size = win->GetClientSize();
DoSetClippingRegion(0, 0, size.x, size.y);
-#endif
+#endif
// __WXUNIVERSAL__
}
void wxClientDCImpl::DoGetSize(int *width, int *height) const
{
- wxCHECK_RET( m_window, _T("GetSize() doesn't work without window") );
+ wxCHECK_RET( m_window, wxT("GetSize() doesn't work without window") );
m_window->GetClientSize( width, height );
}
gdk_gc_set_clip_region( m_textGC, region );
gdk_gc_set_clip_region( m_bgGC, region );
}
-#endif
+#endif
}
// ----------------------------------------------------------------------------