X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bc797f4cc8ffe36277ba8b7dd4b57e63a96bfcb5..94e0018723919fe2ca2f5b5f0a42804c16dbf3a1:/src/x11/dcclient.cpp?ds=sidebyside diff --git a/src/x11/dcclient.cpp b/src/x11/dcclient.cpp index 2bedcdb5b5..3f127c442b 100644 --- a/src/x11/dcclient.cpp +++ b/src/x11/dcclient.cpp @@ -1,65 +1,54 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: dcclient.cpp +// Name: src/x11/dcclient.cpp // Purpose: wxClientDC class -// Author: Julian Smart +// Author: Julian Smart, Robert Roebling // Modified by: // Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart +// Copyright: (c) Julian Smart, Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -/* - About pens, brushes, and the autoSetting flag: +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" - Under X, pens and brushes control some of the same X drawing parameters. - Therefore, it is impossible to independently maintain the current pen and the - current brush. Also, some settings depend on the current logical function. The - m_currentFill, etc. instance variables remember state across the brush and - pen. - - Since pens are used more than brushes, the autoSetting flag is used to - indicate that a brush was recently used, and SetPen must be called to - reinstall the current pen's parameters. If autoSetting includes 0x2, then the - pens color may need to be set based on XOR. - - There is, unfortunately, some confusion between setting the current pen/brush - and actually installing the brush/pen parameters. Both functionalies are - perform by SetPen and SetBrush. C'est la vie. -*/ - -// ============================================================================ -// declarations -// ============================================================================ - -// ---------------------------------------------------------------------------- -// headers -// ---------------------------------------------------------------------------- +#include "wx/dcclient.h" -#ifdef __GNUG__ - #pragma implementation "dcclient.h" +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/window.h" + #include "wx/math.h" + #include "wx/image.h" + #include "wx/module.h" #endif -#include "wx/dcclient.h" -#include "wx/dcmemory.h" -#include "wx/window.h" -#include "wx/app.h" -#include "wx/image.h" - -#include +#include "wx/fontutil.h" +#include "wx/vector.h" -#ifdef __VMS__ -#pragma message disable nosimpint +#include "wx/x11/private.h" +#include "wx/x11/dcclient.h" +#include "wx/x11/dcmemory.h" + +#if wxUSE_UNICODE +#include "glib.h" +#include "pango/pangox.h" +#ifdef HAVE_PANGO_XFT + #include "pango/pangoxft.h" #endif -#ifdef __VMS__ -#pragma message enable nosimpint + +#include "pango_x.cpp" #endif -#include "wx/x11/private.h" +//----------------------------------------------------------------------------- +// local defines +//----------------------------------------------------------------------------- -#ifdef __EMX__ - #include // for M_PI -#endif // __EMX__ +// VZ: what is this for exactly?? +#define USE_PAINT_REGION 0 + +//----------------------------------------------------------------------------- +// local data +//----------------------------------------------------------------------------- #include "bdiag.xbm" #include "fdiag.xbm" @@ -67,1963 +56,2012 @@ #include "horiz.xbm" #include "verti.xbm" #include "cross.xbm" +#define num_hatches 6 -static Pixmap bdiag, cdiag, fdiag, cross, horiz, verti; +#define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH) +#define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH) -// ---------------------------------------------------------------------------- +static Pixmap hatches[num_hatches]; +static Pixmap *hatch_bitmap = NULL; + +//----------------------------------------------------------------------------- // constants -// ---------------------------------------------------------------------------- +//----------------------------------------------------------------------------- -// Fudge factor (VZ: what??) -#define WX_GC_CF 1 +const double RAD2DEG = 180.0 / M_PI; // ---------------------------------------------------------------------------- -// macros +// private functions // ---------------------------------------------------------------------------- - IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC) - IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC) - IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC) +static inline double dmax(double a, double b) { return a > b ? a : b; } +static inline double dmin(double a, double b) { return a < b ? a : b; } -// ---------------------------------------------------------------------------- -// prototypes -// ---------------------------------------------------------------------------- +static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } -static void XCopyRemote(Display *src_display, Display *dest_display, - Drawable src, Drawable dest, - GC destgc, - int srcx, int srcy, - unsigned int w, unsigned int h, - int destx, int desty, - bool more, XImage **cache); - -// ============================================================================ -// implementation -// ============================================================================ - -/* - * compare two doubles and return the larger rounded - * to the nearest int - */ -static int roundmax(double a, double b) -{ - return (int)((a > b ? a : b) + 0.5); -} +//----------------------------------------------------------------------------- +// Implement Pool of Graphic contexts. Creating them takes too much time. +//----------------------------------------------------------------------------- -/* - * compare two doubles and return the smaller rounded - * to the nearest int - */ -static int roundmin(double a, double b) -{ - return (int)((a < b ? a : b) - 0.5); -} +#define GC_POOL_SIZE 200 +enum wxPoolGCType +{ + wxGC_ERROR = 0, + wxTEXT_MONO, + wxBG_MONO, + wxPEN_MONO, + wxBRUSH_MONO, + wxTEXT_COLOUR, + wxBG_COLOUR, + wxPEN_COLOUR, + wxBRUSH_COLOUR, + wxTEXT_SCREEN, + wxBG_SCREEN, + wxPEN_SCREEN, + wxBRUSH_SCREEN +}; + +struct wxGC +{ + GC m_gc; + wxPoolGCType m_type; + bool m_used; +}; -// ---------------------------------------------------------------------------- -// wxWindowDC -// ---------------------------------------------------------------------------- +static wxGC wxGCPool[GC_POOL_SIZE]; -wxWindowDC::wxWindowDC() +static void wxInitGCPool() { - m_gc = (WXGC) 0; - m_gcBacking = (WXGC) 0; - m_window = NULL; - m_backgroundPixel = -1; - m_currentPenWidth = 1; - m_currentPenJoin = -1; - m_currentPenDashCount = -1; - m_currentPenDash = (wxMOTIFDash*) NULL; - m_currentStyle = -1; - m_currentFill = -1; - // m_currentBkMode = wxTRANSPARENT; - m_colour = wxColourDisplay(); - m_display = (WXDisplay*) NULL; - m_currentRegion = (WXRegion) 0; - m_userRegion = (WXRegion) 0; - m_pixmap = (WXPixmap) 0; - m_autoSetting = 0; - m_oldFont = (WXFont) 0; + memset( wxGCPool, 0, GC_POOL_SIZE*sizeof(wxGC) ); } -wxWindowDC::wxWindowDC( wxWindow *window ) +static void wxCleanUpGCPool() { - wxASSERT_MSG( (window != (wxWindow*) NULL), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." ); - - m_window = window; - m_font = window->GetFont(); - m_gc = (WXGC) 0; - m_gcBacking = (WXGC) 0; - m_backgroundPixel = -1; - m_currentPenWidth = 1; - m_currentPenJoin = -1; - m_currentPenDashCount = -1; - m_currentPenDash = (wxMOTIFDash*) NULL; - m_currentStyle = -1; - m_currentFill = -1; - // m_currentBkMode = wxTRANSPARENT; - m_colour = wxColourDisplay(); - m_currentRegion = (WXRegion) 0; - m_userRegion = (WXRegion) 0; - m_ok = TRUE; - m_autoSetting = 0; - - m_display = window->GetXDisplay(); - m_pixmap = window->GetXWindow(); - Display* display = (Display*) m_display; - - XSetWindowColormap (display, (Pixmap) m_pixmap, (Colormap) wxTheApp->GetMainColormap(m_display)); - - XGCValues gcvalues; - gcvalues.foreground = BlackPixel (display, DefaultScreen (display)); - gcvalues.background = WhitePixel (display, DefaultScreen (display)); - gcvalues.graphics_exposures = False; - gcvalues.subwindow_mode = IncludeInferiors; - gcvalues.line_width = 1; - m_gc = (WXGC) XCreateGC (display, RootWindow (display, DefaultScreen (display)), - GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth | GCSubwindowMode, - &gcvalues); - - if (m_window->GetBackingPixmap()) - { - m_gcBacking = (WXGC) XCreateGC (display, RootWindow (display, - DefaultScreen (display)), - GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth | GCSubwindowMode, - &gcvalues); - } - - m_backgroundPixel = (int) gcvalues.background; - - // Get the current Font so we can set it back later - XGCValues valReturn; - XGetGCValues((Display*) m_display, (GC) m_gc, GCFont, &valReturn); - m_oldFont = (WXFont) valReturn.font; - - SetBackground(wxBrush(m_window->GetBackgroundColour(), wxSOLID)); + for (int i = 0; i < GC_POOL_SIZE; i++) + { + if (wxGCPool[i].m_gc) + XFreeGC( wxGlobalDisplay(), wxGCPool[i].m_gc ); + } } -wxWindowDC::~wxWindowDC() +static GC wxGetPoolGC( Window window, wxPoolGCType type ) { - if (m_gc && (m_oldFont != (WXFont) 0) && ((long) m_oldFont != -1)) + for (int i = 0; i < GC_POOL_SIZE; i++) { - XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont); - - if (m_window && m_window->GetBackingPixmap()) - XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont); + if (!wxGCPool[i].m_gc) + { + wxGCPool[i].m_gc = XCreateGC( wxGlobalDisplay(), window, 0, NULL ); + XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool[i].m_gc, FALSE ); + wxGCPool[i].m_type = type; + wxGCPool[i].m_used = false; + } + if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type)) + { + wxGCPool[i].m_used = true; + return wxGCPool[i].m_gc; + } } - if (m_gc) - XFreeGC ((Display*) m_display, (GC) m_gc); - m_gc = (WXGC) 0; - - if (m_gcBacking) - XFreeGC ((Display*) m_display, (GC) m_gcBacking); - m_gcBacking = (WXGC) 0; - - if (m_currentRegion) - XDestroyRegion ((Region) m_currentRegion); - m_currentRegion = (WXRegion) 0; + wxFAIL_MSG( wxT("No GC available") ); - if (m_userRegion) - XDestroyRegion ((Region) m_userRegion); - m_userRegion = (WXRegion) 0; + return (GC) NULL; } -void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1), - const wxColour& WXUNUSED(col), int WXUNUSED(style) ) +static void wxFreePoolGC( GC gc ) { - wxFAIL_MSG("not implemented"); + for (int i = 0; i < GC_POOL_SIZE; i++) + { + if (wxGCPool[i].m_gc == gc) + { + wxGCPool[i].m_used = false; + return; + } + } + + wxFAIL_MSG( wxT("Wrong GC") ); } -bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const +// ---------------------------------------------------------------------------- +// wxWindowDC +// ---------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl, wxX11DCImpl) + +wxWindowDCImpl::wxWindowDCImpl( wxDC *owner ) + : wxX11DCImpl( owner ) { - // Generic (and therefore rather inefficient) method. - // Could be improved. - wxMemoryDC memdc; - wxBitmap bitmap(1, 1); - memdc.SelectObject(bitmap); - memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1); - memdc.SelectObject(wxNullBitmap); - wxImage image(bitmap); - col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0)); - return TRUE; + Init(); } -void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) +wxWindowDCImpl::wxWindowDCImpl( wxDC* owner, wxWindow *window ) + : wxX11DCImpl( owner ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxASSERT_MSG( window, wxT("DC needs a window") ); + + Init(); + + m_font = window->GetFont(); + + m_x11window = (WXWindow*) window->X11GetMainWindow(); + + // not realized ? + if (!m_x11window) + { + // don't report problems + m_ok = true; - int x1d, y1d, x2d, y2d; + return; + } - // FreeGetPixelCache(); + m_display = (WXDisplay *) wxGlobalDisplay(); - x1d = XLOG2DEV(x1); - y1d = YLOG2DEV(y1); - x2d = XLOG2DEV(x2); - y2d = YLOG2DEV(y2); +#if wxUSE_UNICODE + m_fontdesc = window->GetFont().GetNativeFontInfo()->description; +#endif - if (m_autoSetting) - SetPen (m_pen); + int screen = DefaultScreen( (Display*) m_display ); + m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen ); - XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x1d, y1d, x2d, y2d); + SetUpDC(); - if (m_window && m_window->GetBackingPixmap()) - XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, - XLOG2DEV_2(x1), YLOG2DEV_2(y1), - XLOG2DEV_2(x2), YLOG2DEV_2(y2)); + /* this must be done after SetUpDC, bacause SetUpDC calls the + repective SetBrush, SetPen, SetBackground etc functions + to set up the DC. SetBackground call m_window->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) */ - CalcBoundingBox(x1, y1); - CalcBoundingBox(x2, y2); + m_window = window; } -void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y ) +wxWindowDCImpl::~wxWindowDCImpl() { - wxCHECK_RET( Ok(), "invalid dc" ); - - if (m_autoSetting) - SetPen (m_pen); - - int xx = XLOG2DEV (x); - int yy = YLOG2DEV (y); - int ww, hh; - wxDisplaySize (&ww, &hh); - XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, yy, - ww, yy); - XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xx, 0, - xx, hh); - - if (m_window && m_window->GetBackingPixmap()) - { - xx = XLOG2DEV_2 (x); - yy = YLOG2DEV_2 (y); - XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, - 0, yy, - ww, yy); - XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, - xx, 0, - xx, hh); - } + Destroy(); } -void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc ) +void wxWindowDCImpl::Init() { - wxCHECK_RET( Ok(), "invalid dc" ); - - // FreeGetPixelCache(); + m_display = NULL; + m_penGC = NULL; + m_brushGC = NULL; + m_textGC = NULL; + m_bgGC = NULL; + m_cmap = NULL; + m_isMemDC = false; + m_isScreenDC = false; + m_x11window = NULL; + +#if wxUSE_UNICODE + m_context = wxTheApp->GetPangoContext(); + m_fontdesc = NULL; +#endif +} - int xx1 = XLOG2DEV (x1); - int yy1 = YLOG2DEV (y1); - int xx2 = XLOG2DEV (x2); - int yy2 = YLOG2DEV (y2); - int xxc = XLOG2DEV (xc); - int yyc = YLOG2DEV (yc); - int xxc_2 = XLOG2DEV_2 (xc); - int yyc_2 = YLOG2DEV_2 (yc); +void wxWindowDCImpl::SetUpDC() +{ + m_ok = true; - wxCoord dx = xx1 - xxc; - wxCoord dy = yy1 - yyc; - double radius = sqrt ((double)(dx * dx + dy * dy)); - wxCoord r = (wxCoord) radius; + wxASSERT_MSG( !m_penGC, wxT("GCs already created") ); - double radius1, radius2; + bool ismono = false; + if (m_isMemDC) + { + wxMemoryDCImpl *mem_impl = (wxMemoryDCImpl *) this; + if (mem_impl->GetSelectedBitmap().IsOk()) + ismono = mem_impl->GetSelectedBitmap().GetDepth() == 1; + } - if (xx1 == xx2 && yy1 == yy2) + if (m_isScreenDC) { - radius1 = 0.0; - radius2 = 360.0; + m_penGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxPEN_SCREEN ); + m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBRUSH_SCREEN ); + m_textGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxTEXT_SCREEN ); + m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBG_SCREEN ); } - else if (radius == 0.0) - radius1 = radius2 = 0.0; else + if (m_isMemDC && ismono) { - if (xx1 - xxc == 0) - if (yy1 - yyc < 0) - radius1 = 90.0; - else - radius1 = -90.0; - else - radius1 = -atan2 ((double) (yy1 - yyc), (double) (xx1 - xxc)) * 360.0 / (2 * M_PI); - - if (xx2 - xxc == 0) - if (yy2 - yyc < 0) - radius2 = 90.0; - else - radius2 = -90.0; - else - radius2 = -atan2 ((double) (yy2 - yyc), (double) (xx2 - xxc)) * 360.0 / (2 * M_PI); + m_penGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxPEN_MONO ); + m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBRUSH_MONO ); + m_textGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxTEXT_MONO ); + m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBG_MONO ); } - radius1 *= 64.0; - radius2 *= 64.0; - int alpha1 = (int) radius1; - int alpha2 = (int) (radius2 - radius1); - while (alpha2 <= 0) - alpha2 += 360 * 64; - while (alpha2 > 360 * 64) - alpha2 -= 360 * 64; - - if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) + else { - SetBrush (m_brush); - XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) (GC) m_gc, - xxc - r, yyc - r, 2 * r, 2 * r, alpha1, alpha2); + m_penGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxPEN_COLOUR ); + m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBRUSH_COLOUR ); + m_textGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxTEXT_COLOUR ); + m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBG_COLOUR ); + } - if (m_window && m_window->GetBackingPixmap()) - XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, - xxc_2 - r, yyc_2 - r, 2 * r, 2 * r, alpha1, alpha2); + /* background colour */ + m_backgroundBrush = *wxWHITE_BRUSH; + m_backgroundBrush.GetColour().CalcPixel( m_cmap ); + unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel(); - } + m_textForegroundColour = *wxBLACK; + m_textBackgroundColour = *wxWHITE; - if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) - { - if (m_autoSetting) - SetPen (m_pen); - XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, - xxc - r, yyc - r, 2 * r, 2 * r, alpha1, alpha2); + /* m_textGC */ + m_textForegroundColour.CalcPixel( m_cmap ); + XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() ); - if (m_window && m_window->GetBackingPixmap()) - XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, - xxc_2 - r, yyc_2 - r, 2 * r, 2 * r, alpha1, alpha2); - } - CalcBoundingBox (x1, y1); - CalcBoundingBox (x2, y2); -} + m_textBackgroundColour.CalcPixel( m_cmap ); + XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() ); -void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea ) -{ - wxCHECK_RET( Ok(), "invalid dc" ); + XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillSolid ); - int xd, yd, wd, hd; +#if wxUSE_NANOX + // By default, draw transparently + GrSetGCUseBackground((GC) m_textGC, FALSE); +#endif - xd = XLOG2DEV(x); - yd = YLOG2DEV(y); - wd = XLOG2DEVREL(width); - hd = YLOG2DEVREL(height); + /* m_penGC */ + m_pen.GetColour().CalcPixel( m_cmap ); + XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() ); + XSetBackground( (Display*) m_display, (GC) m_penGC, bg_col ); - if (sa>=360 || sa<=-360) sa=sa-int(sa/360)*360; - if (ea>=360 || ea<=-360) ea=ea-int(ea/360)*360; - int start = int(sa*64); - int end = int(ea*64); - if (start<0) start+=360*64; - if (end <0) end +=360*64; - if (end>start) end-=start; - else end+=360*64-start; + XSetLineAttributes( (Display*) m_display, (GC) m_penGC, 0, LineSolid, CapNotLast, JoinRound ); - if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) - { - m_autoSetting = TRUE; // must be reset + /* m_brushGC */ + m_brush.GetColour().CalcPixel( m_cmap ); + XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() ); + XSetBackground( (Display*) m_display, (GC) m_brushGC, bg_col ); - SetBrush (m_brush); - XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, start, end); + XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid ); - if (m_window && m_window->GetBackingPixmap()) - XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y),wd,hd,start,end); - } + /* m_bgGC */ + XSetForeground( (Display*) m_display, (GC) m_bgGC, bg_col ); + XSetBackground( (Display*) m_display, (GC) m_bgGC, bg_col ); + + XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid ); + + /* ROPs */ + XSetFunction( (Display*) m_display, (GC) m_textGC, GXcopy ); + XSetFunction( (Display*) m_display, (GC) m_brushGC, GXcopy ); + XSetFunction( (Display*) m_display, (GC)m_penGC, GXcopy ); + + /* clipping */ + XSetClipMask( (Display*) m_display, (GC) m_penGC, None ); + XSetClipMask( (Display*) m_display, (GC) m_brushGC, None ); + XSetClipMask( (Display*) m_display, (GC) m_textGC, None ); + XSetClipMask( (Display*) m_display, (GC) m_bgGC, None ); - if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) + if (!hatch_bitmap) { - if (m_autoSetting) - SetPen (m_pen); - XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, start,end); - if (m_window && m_window->GetBackingPixmap()) - XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y),wd,hd,start,end); + int xscreen = DefaultScreen( (Display*) m_display ); + Window xroot = RootWindow( (Display*) m_display, xscreen ); + + hatch_bitmap = hatches; + hatch_bitmap[0] = XCreateBitmapFromData( (Display*) m_display, xroot, bdiag_bits, bdiag_width, bdiag_height ); + hatch_bitmap[1] = XCreateBitmapFromData( (Display*) m_display, xroot, cdiag_bits, cdiag_width, cdiag_height ); + hatch_bitmap[2] = XCreateBitmapFromData( (Display*) m_display, xroot, fdiag_bits, fdiag_width, fdiag_height ); + hatch_bitmap[3] = XCreateBitmapFromData( (Display*) m_display, xroot, cross_bits, cross_width, cross_height ); + hatch_bitmap[4] = XCreateBitmapFromData( (Display*) m_display, xroot, horiz_bits, horiz_width, horiz_height ); + hatch_bitmap[5] = XCreateBitmapFromData( (Display*) m_display, xroot, verti_bits, verti_width, verti_height ); } - CalcBoundingBox (x, y); - CalcBoundingBox (x + width, y + height); } -void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y ) +void wxWindowDCImpl::DoGetSize( int* width, int* height ) const { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( m_window, wxT("GetSize() doesn't work without window") ); - // FreeGetPixelCache(); - - if (m_pen.Ok() && m_autoSetting) - SetPen (m_pen); + m_window->GetSize(width, height); +} - XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y)); - if (m_window && m_window->GetBackingPixmap()) - XDrawPoint ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, XLOG2DEV_2 (x), YLOG2DEV_2 (y)); +extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, + const wxColour & col, wxFloodFillStyle style); - CalcBoundingBox (x, y); +bool wxWindowDCImpl::DoFloodFill(wxCoord x, wxCoord y, + const wxColour& col, wxFloodFillStyle style) +{ + return wxDoFloodFill(GetOwner(), x, y, col, style); } -void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset ) +bool wxWindowDCImpl::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const { - wxCHECK_RET( Ok(), "invalid dc" ); + // Generic (and therefore rather inefficient) method. + // Could be improved. + wxMemoryDC memdc; + wxBitmap bitmap(1, 1); + memdc.SelectObject(bitmap); + memdc.Blit(0, 0, 1, 1, GetOwner(), x1, y1); + memdc.SelectObject(wxNullBitmap); + wxImage image(bitmap.ConvertToImage()); + col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0)); + return true; +} - // FreeGetPixelCache(); +void wxWindowDCImpl::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) + if (m_pen.GetStyle() != wxTRANSPARENT) { - if (m_autoSetting) - SetPen (m_pen); - - XPoint *xpoints = new XPoint[n]; - int i; - - for (i = 0; i < n; i++) + if (m_x11window) { - xpoints[i].x = XLOG2DEV (points[i].x + xoffset); - xpoints[i].y = YLOG2DEV (points[i].y + yoffset); + // This hack is for the iPaq: XDrawLine draws + // nothing, whereas XDrawLines works... + wxPoint points[2]; + points[0].x = x1; + points[0].y = y1; + points[1].x = x2; + points[1].y = y2; + DoDrawLines( 2, points, 0, 0 ); + + // XDrawLine( (Display*) m_display, (Window) m_x11window, + // (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) ); } - XDrawLines ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints, n, 0); - if (m_window && m_window->GetBackingPixmap()) - { - for (i = 0; i < n; i++) - { - xpoints[i].x = XLOG2DEV_2 (points[i].x + xoffset); - xpoints[i].y = YLOG2DEV_2 (points[i].y + yoffset); - } - XDrawLines ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints, n, 0); - } - delete[]xpoints; + CalcBoundingBox(x1, y1); + CalcBoundingBox(x2, y2); } } -void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], - wxCoord xoffset, wxCoord yoffset, int fillStyle ) +void wxWindowDCImpl::DoCrossHair( wxCoord x, wxCoord y ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - // FreeGetPixelCache(); - - XPoint *xpoints1 = new XPoint[n + 1]; - XPoint *xpoints2 = new XPoint[n + 1]; - int i; - for (i = 0; i < n; i++) + if (m_pen.GetStyle() != wxTRANSPARENT) { - xpoints1[i].x = XLOG2DEV (points[i].x + xoffset); - xpoints1[i].y = YLOG2DEV (points[i].y + yoffset); - xpoints2[i].x = XLOG2DEV_2 (points[i].x + xoffset); - xpoints2[i].y = YLOG2DEV_2 (points[i].y + yoffset); - CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset); + int w = 0; + int h = 0; + DoGetSize( &w, &h ); + wxCoord xx = XLOG2DEV(x); + wxCoord yy = YLOG2DEV(y); + if (m_x11window) + { + XDrawLine( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, 0, yy, XLOG2DEVREL(w), yy ); + XDrawLine( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, xx, 0, xx, YLOG2DEVREL(h) ); + } } +} - // Close figure for XDrawLines (not needed for XFillPolygon) - xpoints1[i].x = xpoints1[0].x; - xpoints1[i].y = xpoints1[0].y; - xpoints2[i].x = xpoints2[0].x; - xpoints2[i].y = xpoints2[0].y; +void wxWindowDCImpl::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); + + wxCoord xx1 = XLOG2DEV(x1); + wxCoord yy1 = YLOG2DEV(y1); + wxCoord xx2 = XLOG2DEV(x2); + wxCoord yy2 = YLOG2DEV(y2); + wxCoord xxc = XLOG2DEV(xc); + wxCoord yyc = YLOG2DEV(yc); + double dx = xx1 - xxc; + double dy = yy1 - yyc; + double radius = sqrt((double)(dx*dx+dy*dy)); + wxCoord r = (wxCoord)radius; + double radius1, radius2; - if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) + if (xx1 == xx2 && yy1 == yy2) { - SetBrush (m_brush); - XSetFillRule ((Display*) m_display, (GC) m_gc, fillStyle == wxODDEVEN_RULE ? EvenOddRule : WindingRule); - XFillPolygon ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints1, n, Complex, 0); - XSetFillRule ((Display*) m_display, (GC) m_gc, EvenOddRule); // default mode - if (m_window && m_window->GetBackingPixmap()) - { - XSetFillRule ((Display*) m_display,(GC) m_gcBacking, - fillStyle == wxODDEVEN_RULE ? EvenOddRule : WindingRule); - XFillPolygon ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints2, n, Complex, 0); - XSetFillRule ((Display*) m_display,(GC) m_gcBacking, EvenOddRule); // default mode - } + radius1 = 0.0; + radius2 = 360.0; + } + else + if (radius == 0.0) + { + radius1 = radius2 = 0.0; + } + else + { + radius1 = (xx1 - xxc == 0) ? + (yy1 - yyc < 0) ? 90.0 : -90.0 : + -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG; + radius2 = (xx2 - xxc == 0) ? + (yy2 - yyc < 0) ? 90.0 : -90.0 : + -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG; } + wxCoord alpha1 = wxCoord(radius1 * 64.0); + wxCoord alpha2 = wxCoord((radius2 - radius1) * 64.0); + while (alpha2 <= 0) alpha2 += 360*64; + while (alpha1 > 360*64) alpha1 -= 360*64; - if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) + if (m_x11window) { - if (m_autoSetting) - SetPen (m_pen); - XDrawLines ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints1, n + 1, 0); + if (m_brush.GetStyle() != wxTRANSPARENT) + { + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); - if (m_window && m_window->GetBackingPixmap()) - XDrawLines ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints2, n + 1, 0); - } + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); - delete[]xpoints1; - delete[]xpoints2; -} + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); + } else + if (IS_15_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 15, m_deviceOriginY % 15 ); -void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) -{ - wxCHECK_RET( Ok(), "invalid dc" ); + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); - // FreeGetPixelCache(); + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (IS_16_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 16, m_deviceOriginY % 16 ); - int xd, yd, wfd, hfd, wd, hd; + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); - xd = XLOG2DEV(x); - yd = YLOG2DEV(y); - wfd = XLOG2DEVREL(width); - wd = wfd - WX_GC_CF; - hfd = YLOG2DEVREL(height); - hd = hfd - WX_GC_CF; + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (m_brush.GetStyle() == wxSTIPPLE) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); - if (wfd == 0 || hfd == 0) return; - if (wd < 0) { wd = - wd; xd = xd - wd; } - if (hd < 0) { hd = - hd; yd = yd - hd; } + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); - if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) - { - SetBrush (m_brush); - XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wfd, hfd); + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } + else + { + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); + } + } - if (m_window && m_window->GetBackingPixmap()) - XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y), - wfd, hfd); - } + if (m_pen.GetStyle() != wxTRANSPARENT) + { + XDrawArc( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); - if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) - { - if (m_autoSetting) - SetPen (m_pen); - XDrawRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd); + XDrawLine( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, xx1, yy1, xxc, yyc ); - if (m_window && m_window->GetBackingPixmap()) - XDrawRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y), - wd, hd); + XDrawLine( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, xxc, yyc, xx2, yy2 ); + } } - CalcBoundingBox (x, y); - CalcBoundingBox (x + width, y + height); + + CalcBoundingBox (x1, y1); + CalcBoundingBox (x2, y2); } -void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) +void wxWindowDCImpl::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - // FreeGetPixelCache(); + wxCoord xx = XLOG2DEV(x); + wxCoord yy = YLOG2DEV(y); + wxCoord ww = m_signX * XLOG2DEVREL(width); + wxCoord hh = m_signY * YLOG2DEVREL(height); - // If radius is negative, it's a proportion of the smaller dimension. + // CMB: handle -ve width and/or height + if (ww < 0) { ww = -ww; xx = xx - ww; } + if (hh < 0) { hh = -hh; yy = yy - hh; } - if (radius < 0.0) radius = - radius * ((width < height) ? width : height); + if (m_x11window) + { + wxCoord start = wxCoord(sa * 64.0); + wxCoord end = wxCoord((ea-sa) * 64.0); - int xd = XLOG2DEV (x); - int yd = YLOG2DEV (y); - int rd = XLOG2DEVREL ((long) radius); - int wd = XLOG2DEVREL (width) - WX_GC_CF; - int hd = YLOG2DEVREL (height) - WX_GC_CF; + if (m_brush.GetStyle() != wxTRANSPARENT) + { + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); - int rw_d = rd * 2; - int rh_d = rw_d; + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_textGC, xx, yy, ww, hh, start, end ); - // If radius is zero use DrawRectangle() instead to avoid - // X drawing errors with small radii - if (rd == 0) - { - DrawRectangle( x, y, width, height ); - return; - } + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); + } else + if (IS_15_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 15, m_deviceOriginY % 15 ); - // Draw nothing if transformed w or h is 0 - if (wd == 0 || hd == 0) return; + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh, start, end ); - // CMB: adjust size if outline is drawn otherwise the result is - // 1 pixel too wide and high - if (m_pen.GetStyle() != wxTRANSPARENT) - { - wd--; - hd--; - } - - // CMB: ensure dd is not larger than rectangle otherwise we - // get an hour glass shape - if (rw_d > wd) rw_d = wd; - if (rw_d > hd) rw_d = hd; - rd = rw_d / 2; - - // For backing pixmap - int xd2 = XLOG2DEV_2 (x); - int yd2 = YLOG2DEV_2 (y); - int rd2 = XLOG2DEVREL ((long) radius); - int wd2 = XLOG2DEVREL (width) ; - int hd2 = YLOG2DEVREL (height) ; - - int rw_d2 = rd2 * 2; - int rh_d2 = rw_d2; - - if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) - { - SetBrush (m_brush); - - XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd, - wd - rw_d, hd); - XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + rd, - wd, hd - rh_d); - - // Arcs start from 3 o'clock, positive angles anticlockwise - // Top-left - XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, - rw_d, rh_d, 90 * 64, 90 * 64); - // Top-right - XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, yd, - // rw_d, rh_d, 0, 90 * 64); - rw_d, rh_d, 0, 91 * 64); - // Bottom-right - XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, - yd + hd - rh_d, - // rw_d, rh_d, 270 * 64, 90 * 64); - rw_d, rh_d, 269 * 64, 92 * 64); - // Bottom-left - XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + hd - rh_d, - rw_d, rh_d, 180 * 64, 90 * 64); - - if (m_window && m_window->GetBackingPixmap()) - { - XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2 + rd2, yd2, wd2 - rw_d2, hd2); - XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2, yd2 + rd2, wd2, hd2 - rh_d2); - - XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2, yd2, rw_d2, rh_d2, 90 * 64, 90 * 64); - XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2 + wd2 - rw_d2, yd2, - // rw_d2, rh_d2, 0, 90 * 64); - rw_d2, rh_d2, 0, 91 * 64); - XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2 + wd2 - rw_d2, - yd2 + hd2 - rh_d2, - // rw_d2, rh_d2, 270 * 64, 90 * 64); - rw_d2, rh_d2, 269 * 64, 92 * 64); - XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2, yd2 + hd2 - rh_d2, - rw_d2, rh_d2, 180 * 64, 90 * 64); + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (IS_16_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 16, m_deviceOriginY % 16 ); + + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh, start, end ); + + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (m_brush.GetStyle() == wxSTIPPLE) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); + + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh, start, end ); + + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } + else + { + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh, start, end ); + } } - } - if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) - { - SetPen (m_pen); - XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd, - xd + wd - rd + 1, yd); - XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd + hd, - xd + wd - rd, yd + hd); - - XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + rd, - xd, yd + hd - rd); - XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd, yd + rd, - xd + wd, yd + hd - rd + 1); - XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, - rw_d, rh_d, 90 * 64, 90 * 64); - XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, yd, - // rw_d, rh_d, 0, 90 * 64); - rw_d, rh_d, 0, 91 * 64); - XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, - yd + hd - rh_d, - rw_d, rh_d, 269 * 64, 92 * 64); - XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + hd - rh_d, - rw_d, rh_d, 180 * 64, 90 * 64); - - if (m_window && m_window->GetBackingPixmap()) + if (m_pen.GetStyle() != wxTRANSPARENT) { - XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2 + rd2, yd2, - xd2 + wd2 - rd2 + 1, yd2); - XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2 + rd2, yd2 + hd2, - xd2 + wd2 - rd2, yd2 + hd2); - - XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2, yd2 + rd2, - xd2, yd2 + hd2 - rd2); - XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2 + wd2, yd2 + rd2, - xd2 + wd2, yd2 + hd2 - rd2 + 1); - XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2, yd2, - rw_d2, rh_d2, 90 * 64, 90 * 64); - XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2 + wd2 - rw_d2, yd2, - // rw_d2, rh_d2, 0, 90 * 64); - rw_d2, rh_d2, 0, 91 * 64); - XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2 + wd2 - rw_d2, - yd2 + hd2 - rh_d2, - rw_d2, rh_d2, 269 * 64, 92 * 64); - XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - xd2, yd2 + hd2 - rh_d2, - rw_d2, rh_d2, 180 * 64, 90 * 64); + XDrawArc( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, xx, yy, ww, hh, start, end ); } } + CalcBoundingBox (x, y); CalcBoundingBox (x + width, y + height); +} + +void wxWindowDCImpl::DoDrawPoint( wxCoord x, wxCoord y ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); + if ((m_pen.GetStyle() != wxTRANSPARENT) && m_x11window) + XDrawPoint( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, XLOG2DEV(x), YLOG2DEV(y) ); + CalcBoundingBox (x, y); } -void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) +void wxWindowDCImpl::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - // Check for negative width and height - if (height < 0) - { - y = y + height; - height = - height ; - } + if (m_pen.GetStyle() == wxTRANSPARENT) return; + if (n <= 0) return; - if (width < 0) + XPoint *xpoints = new XPoint[n]; + for (int i = 0; i < n; i++) { - x = x + width; - width = - width ; - } + xpoints[i].x = XLOG2DEV (points[i].x + xoffset); + xpoints[i].y = YLOG2DEV (points[i].y + yoffset); - // FreeGetPixelCache(); + CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset ); + } + XDrawLines( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xpoints, n, 0 ); - static const int angle = 23040; + delete[] xpoints; +} - int xd, yd, wd, hd; +void wxWindowDCImpl::DoDrawPolygon( int n, wxPoint points[], + wxCoord xoffset, wxCoord yoffset, + wxPolygonFillMode WXUNUSED(fillStyle) ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - xd = XLOG2DEV(x); - yd = YLOG2DEV(y); - wd = XLOG2DEVREL(width) ; - hd = YLOG2DEVREL(height) ; + if (n <= 0) return; - if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) + XPoint *xpoints = new XPoint[n + 1]; + int i; + for (i = 0; i < n; i++) { - SetBrush (m_brush); - XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, 0, angle); - if (m_window && m_window->GetBackingPixmap()) - XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y), - XLOG2DEVREL (width) - WX_GC_CF, - YLOG2DEVREL (height) - WX_GC_CF, 0, angle); + xpoints[i].x = XLOG2DEV (points[i].x + xoffset); + xpoints[i].y = YLOG2DEV (points[i].y + yoffset); + + CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset); } - if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) + if (m_x11window) { - if (m_autoSetting) - SetPen (m_pen); - XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, 0, angle); - if (m_window && m_window->GetBackingPixmap()) - XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y), - XLOG2DEVREL (width) - WX_GC_CF, - YLOG2DEVREL (height) - WX_GC_CF, 0, angle); - } - CalcBoundingBox (x, y); - CalcBoundingBox (x + width, y + height); + if (m_brush.GetStyle() != wxTRANSPARENT) + { -} + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); -bool wxWindowDC::CanDrawBitmap() const -{ - wxCHECK_MSG( Ok(), FALSE, "invalid dc" ); + XFillPolygon( (Display*) m_display, (Window) m_x11window, + (GC) m_textGC, xpoints, n, Complex, 0); - return TRUE; -} + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); + } else + if (IS_15_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 15, m_deviceOriginY % 15 ); -#if 0 -void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y) -{ - // FreeGetPixelCache(); - - // Be sure that foreground pixels (1) of - // the Icon will be painted with pen colour. [m_pen.SetColour()] - // Background pixels (0) will be painted with - // last selected background color. [::SetBackground] - if (m_pen.Ok() && m_autoSetting) - SetPen (m_pen); - - int width, height; - Pixmap iconPixmap = (Pixmap) icon.GetPixmap(); - width = icon.GetWidth(); - height = icon.GetHeight(); - if (icon.GetDisplay() == m_display) - { - if (icon.GetDepth() <= 1) - { - XCopyPlane ((Display*) m_display, iconPixmap, (Pixmap) m_pixmap, (GC) m_gc, - 0, 0, width, height, - (int) XLOG2DEV (x), (int) YLOG2DEV (y), 1); - } - else - { - XCopyArea ((Display*) m_display, iconPixmap, (Pixmap) m_pixmap, (GC) m_gc, - 0, 0, width, height, - (int) XLOG2DEV (x), (int) YLOG2DEV (y)); - } + XFillPolygon( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xpoints, n, Complex, 0); + + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (IS_16_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 16, m_deviceOriginY % 16 ); + XFillPolygon( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xpoints, n, Complex, 0); - if (m_window && m_window->GetBackingPixmap()) - { - if (icon.GetDepth() <= 1) + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (m_brush.GetStyle() == wxSTIPPLE) { - XCopyPlane ((Display*) m_display, iconPixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - 0, 0, width, height, (int) XLOG2DEV_2 (x), (int) YLOG2DEV_2 (y), 1); + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); + + XFillPolygon( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xpoints, n, Complex, 0); + + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); } else { - XCopyArea ((Display*) m_display, iconPixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - 0, 0, width, height, - (int) XLOG2DEV_2 (x), (int) YLOG2DEV_2 (y)); + XFillPolygon( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xpoints, n, Complex, 0); } } - } else { /* Remote copy (different (Display*) m_displays) */ - XImage *cache = NULL; - if (m_window && m_window->GetBackingPixmap()) - XCopyRemote((Display*) icon.GetDisplay(), (Display*) m_display, iconPixmap, (Pixmap) m_window->GetBackingPixmap(), - (GC) m_gcBacking, 0, 0, width, height, - (int) XLOG2DEV_2 (x), (int) YLOG2DEV_2 (y), TRUE, &cache); - XCopyRemote((Display*) icon.GetDisplay(), (Display*) m_display, iconPixmap, (Pixmap) m_pixmap, (GC) m_gc, - 0, 0, width, height, - (int) XLOG2DEV (x), (int) YLOG2DEV (y), FALSE, &cache); - } - CalcBoundingBox (x, y); -} -#endif // 0 - -// TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities -bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, - wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask, - wxCoord xsrcMask, wxCoord ysrcMask ) -{ - wxCHECK_MSG( Ok(), FALSE, "invalid dc" ); - wxWindowDC* sourceDC = wxDynamicCast(source, wxWindowDC); + if (m_pen.GetStyle () != wxTRANSPARENT) + { + // Close figure for XDrawLines + xpoints[i].x = xpoints[0].x; + xpoints[i].y = xpoints[0].y; - wxASSERT_MSG( sourceDC, "Blit source DC must be wxWindowDC or derived class." ); + XDrawLines( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xpoints, n + 1, 0); + } + } - // FreeGetPixelCache(); + delete[] xpoints; +} - // Be sure that foreground pixels (1) of the Icon will be painted with pen - // colour. [m_pen.SetColour()] Background pixels (0) will be painted with - // last selected background color. [::SetBackground] - if (m_pen.Ok() && m_autoSetting) - SetPen (m_pen); +void wxWindowDCImpl::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - // Do bitmap scaling if necessary + wxCoord xx = XLOG2DEV(x); + wxCoord yy = YLOG2DEV(y); + wxCoord ww = m_signX * XLOG2DEVREL(width); + wxCoord hh = m_signY * YLOG2DEVREL(height); - wxBitmap *scaledBitmap = (wxBitmap*) NULL; - Pixmap sourcePixmap = (Pixmap) NULL; - double scaleX, scaleY; - GetUserScale(& scaleX, & scaleY); + // CMB: draw nothing if transformed w or h is 0 + if (ww == 0 || hh == 0) return; - /* TODO: use the mask origin when drawing transparently */ - if (xsrcMask == -1 && ysrcMask == -1) - { - xsrcMask = xsrc; ysrcMask = ysrc; - } + // CMB: handle -ve width and/or height + if (ww < 0) { ww = -ww; xx = xx - ww; } + if (hh < 0) { hh = -hh; yy = yy - hh; } - // Sorry, can't scale masks just yet - if (!useMask && (scaleX != 1.0 || scaleY != 1.0) && sourceDC->IsKindOf(CLASSINFO(wxMemoryDC))) + if (m_x11window) { - wxMemoryDC* memDC = (wxMemoryDC*) sourceDC; - wxBitmap& bitmap = memDC->GetBitmap(); - - wxASSERT_MSG( (bitmap.Ok()), "Bad source bitmap in wxWindowDC::Blit"); - - wxImage image(bitmap); - if (!image.Ok()) + if (m_brush.GetStyle() != wxTRANSPARENT) { - sourcePixmap = (Pixmap) bitmap.GetPixmap(); - } - else - { - int scaledW = (int) (bitmap.GetWidth() * scaleX); - int scaledH = (int) (bitmap.GetHeight() * scaleY); + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); - image = image.Scale(scaledW, scaledH); - scaledBitmap = new wxBitmap(image.ConvertToBitmap()); - sourcePixmap = (Pixmap) scaledBitmap->GetPixmap(); - } - } - else - sourcePixmap = (Pixmap) sourceDC->m_pixmap; + XFillRectangle( (Display*) m_display, (Window) m_x11window, + (GC) m_textGC, xx, yy, ww, hh ); - if (m_pixmap && sourcePixmap) - { - /* MATTHEW: [9] */ - int orig = m_logicalFunction; + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); + } else + if (IS_15_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 15, m_deviceOriginY % 15 ); - SetLogicalFunction (rop); + XFillRectangle( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh ); - if (m_display != sourceDC->m_display) - { - XImage *cache = NULL; - - if (m_window && m_window->GetBackingPixmap()) - XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display, - (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(), - (GC) m_gcBacking, - source->LogicalToDeviceX (xsrc), - source->LogicalToDeviceY (ysrc), - source->LogicalToDeviceXRel(width), - source->LogicalToDeviceYRel(height), - XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), - TRUE, &cache); - - if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) ) + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (IS_16_PIX_HATCH(m_brush.GetStyle())) { - wxMemoryDC *memDC = (wxMemoryDC *)source; - wxBitmap& sel = memDC->GetBitmap(); - if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetPixmap() ) - { - XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetPixmap()); - XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest)); - } - } + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 16, m_deviceOriginY % 16 ); - XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc, - source->LogicalToDeviceX (xsrc), - source->LogicalToDeviceY (ysrc), - source->LogicalToDeviceXRel(width), - source->LogicalToDeviceYRel(height), - XLOG2DEV (xdest), YLOG2DEV (ydest), - FALSE, &cache); + XFillRectangle( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh ); - if ( useMask ) + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (m_brush.GetStyle() == wxSTIPPLE) { - XSetClipMask ((Display*) m_display, (GC) m_gc, None); - XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0); - } + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); - } else - { - if (m_window && m_window->GetBackingPixmap()) - { - // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1 - if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && ((wxMemoryDC*) source)->GetBitmap().GetDepth() == 1) - { - XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - source->LogicalToDeviceX (xsrc), - source->LogicalToDeviceY (ysrc), - source->LogicalToDeviceXRel(width), - source->LogicalToDeviceYRel(height), - XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), 1); - } - else - { - XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - source->LogicalToDeviceX (xsrc), - source->LogicalToDeviceY (ysrc), - source->LogicalToDeviceXRel(width), - source->LogicalToDeviceYRel(height), - XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest)); - } + XFillRectangle( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh ); + + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); } - if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) ) + else { - wxMemoryDC *memDC = (wxMemoryDC *)source; - wxBitmap& sel = memDC->GetBitmap(); - if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetPixmap() ) - { - XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetPixmap()); - XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest)); - } + XFillRectangle( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh ); } + } + + if (m_pen.GetStyle () != wxTRANSPARENT) + { + XDrawRectangle( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, xx, yy, ww-1, hh-1 ); + } + } - // Check if we're copying from a mono bitmap - if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && - ((wxMemoryDC*)source)->GetBitmap().Ok() && (((wxMemoryDC*)source)->GetBitmap().GetDepth () == 1)) + CalcBoundingBox( x, y ); + CalcBoundingBox( x + width, y + height ); +} + +void wxWindowDCImpl::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); + + if (radius < 0.0) radius = - radius * ((width < height) ? width : height); + + wxCoord xx = XLOG2DEV(x); + wxCoord yy = YLOG2DEV(y); + wxCoord ww = m_signX * XLOG2DEVREL(width); + wxCoord hh = m_signY * YLOG2DEVREL(height); + wxCoord rr = XLOG2DEVREL((wxCoord)radius); + + // CMB: handle -ve width and/or height + if (ww < 0) { ww = -ww; xx = xx - ww; } + if (hh < 0) { hh = -hh; yy = yy - hh; } + + // CMB: if radius is zero use DrawRectangle() instead to avoid + // X drawing errors with small radii + if (rr == 0) + { + XDrawRectangle( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, x, y, width, height); + return; + } + + // CMB: draw nothing if transformed w or h is 0 + if (ww == 0 || hh == 0) return; + + // CMB: adjust size if outline is drawn otherwise the result is + // 1 pixel too wide and high + if (m_pen.GetStyle() != wxTRANSPARENT) + { + ww--; + hh--; + } + + if (m_x11window) + { + // CMB: ensure dd is not larger than rectangle otherwise we + // get an hour glass shape + wxCoord dd = 2 * rr; + if (dd > ww) dd = ww; + if (dd > hh) dd = hh; + rr = dd / 2; + + if (m_brush.GetStyle() != wxTRANSPARENT) + { + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0); + } else + if (IS_15_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, m_deviceOriginX % 15, m_deviceOriginY % 15 ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0); + } else + if (IS_16_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, m_deviceOriginX % 16, m_deviceOriginY % 16 ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0); + } else + if (m_brush.GetStyle() == wxSTIPPLE) { - XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc, - source->LogicalToDeviceX (xsrc), - source->LogicalToDeviceY (ysrc), - source->LogicalToDeviceXRel(width), - source->LogicalToDeviceYRel(height), - XLOG2DEV (xdest), YLOG2DEV (ydest), 1); + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0); } else { - XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc, - source->LogicalToDeviceX (xsrc), - source->LogicalToDeviceY (ysrc), - source->LogicalToDeviceXRel(width), - source->LogicalToDeviceYRel(height), - XLOG2DEV (xdest), YLOG2DEV (ydest)); - + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); } - if ( useMask ) + } + if (m_pen.GetStyle() != wxTRANSPARENT) + { + XDrawLine( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+rr+1, yy, xx+ww-rr, yy ); + XDrawLine( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+rr+1, yy+hh, xx+ww-rr, yy+hh ); + XDrawLine( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx, yy+rr+1, xx, yy+hh-rr ); + XDrawLine( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+ww, yy+rr+1, xx+ww, yy+hh-rr ); + XDrawArc( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx, yy, dd, dd, 90*64, 90*64 ); + XDrawArc( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XDrawArc( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XDrawArc( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); + } + } + + // this ignores the radius + CalcBoundingBox( x, y ); + CalcBoundingBox( x + width, y + height ); +} + +void wxWindowDCImpl::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); + + wxCoord xx = XLOG2DEV(x); + wxCoord yy = YLOG2DEV(y); + wxCoord ww = m_signX * XLOG2DEVREL(width); + wxCoord hh = m_signY * YLOG2DEVREL(height); + + // CMB: handle -ve width and/or height + if (ww < 0) { ww = -ww; xx = xx - ww; } + if (hh < 0) { hh = -hh; yy = yy - hh; } + + if (m_x11window) + { + if (m_brush.GetStyle() != wxTRANSPARENT) + { + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) { - XSetClipMask ((Display*) m_display, (GC) m_gc, None); - XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0); - } + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); - } /* Remote/local (Display*) m_display */ - CalcBoundingBox (xdest, ydest); - CalcBoundingBox (xdest + width, ydest + height); + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_textGC, xx, yy, ww, hh, 0, 360*64 ); - SetLogicalFunction(orig); + XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); + } else + if (IS_15_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 15, m_deviceOriginY % 15 ); - if (scaledBitmap) delete scaledBitmap; + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 ); - return TRUE; - } - if (scaledBitmap) delete scaledBitmap; + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (IS_16_PIX_HATCH(m_brush.GetStyle())) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % 16, m_deviceOriginY % 16 ); + + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 ); + + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } else + if (m_brush.GetStyle() == wxSTIPPLE) + { + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, + m_deviceOriginX % m_brush.GetStipple()->GetWidth(), + m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); + + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 ); + + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); + } + else + { + XFillArc( (Display*) m_display, (Window) m_x11window, + (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 ); + } + } - return FALSE; + if (m_pen.GetStyle () != wxTRANSPARENT) + { + XDrawArc( (Display*) m_display, (Window) m_x11window, + (GC) m_penGC, xx, yy, ww, hh, 0, 360*64 ); + } + } + + CalcBoundingBox( x, y ); + CalcBoundingBox( x + width, y + height ); } -void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) +void wxWindowDCImpl::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y) { - wxCHECK_RET( Ok(), "invalid dc" ); + DoDrawBitmap(icon, x, y, true); +} - // Since X draws from the baseline of the text, must add the text height - int cx = 0; - int cy = 0; - int ascent = 0; - int slen; +#if wxUSE_NANOX +void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap, + wxCoord x, wxCoord y, + bool useMask ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); + + wxCHECK_RET( bitmap.IsOk(), wxT("invalid bitmap") ); + + bool is_mono = (bitmap.GetBitmap() != NULL); + + /* scale/translate size and position */ + int xx = XLOG2DEV(x); + int yy = YLOG2DEV(y); + + int w = bitmap.GetWidth(); + int h = bitmap.GetHeight(); - slen = strlen(text); + CalcBoundingBox( x, y ); + CalcBoundingBox( x + w, y + h ); - if (m_font.Ok()) + if (!m_x11window) return; + + int ww = XLOG2DEVREL(w); + int hh = YLOG2DEVREL(h); + + /* compare to current clipping region */ + if (!m_currentClippingRegion.IsNull()) { - WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); - int direction, descent; - XCharStruct overall_return; + wxRegion tmp( xx,yy,ww,hh ); + tmp.Intersect( m_currentClippingRegion ); + if (tmp.IsEmpty()) + return; + } + + /* scale bitmap if required */ + wxBitmap use_bitmap; + if ((w != ww) || (h != hh)) + { + wxImage image( bitmap.ConvertToImage() ); + image.Rescale( ww, hh ); #if 0 - if (use16) - (void)XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *)(const char*) text, slen, &direction, - &ascent, &descent, &overall_return); + if (is_mono) + use_bitmap = image.ConvertToMonoBitmap(255,255,255); else -#endif // 0 - (void)XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) text, slen, &direction, - &ascent, &descent, &overall_return); +#endif + use_bitmap = image; + } + else + { + use_bitmap = bitmap; + } - cx = overall_return.width; - cy = ascent + descent; + /* apply mask if any */ + WXPixmap mask = NULL; + if (use_bitmap.GetMask()) + mask = use_bitmap.GetMask()->GetBitmap(); + + if (useMask && mask) + { + Pixmap pixmap = (Pixmap) use_bitmap.GetPixmap() ; + Pixmap maskPixmap = (Pixmap) use_bitmap.GetMask()->GetBitmap() ; + Pixmap bufPixmap = GrNewPixmap(w, h, 0); + GC gc = GrNewGC(); + GrSetGCUseBackground(gc, FALSE); + GrSetGCMode(gc, GR_MODE_COPY); + + // This code assumes that background and foreground + // colours are used in ROPs, like in MSW. + // Not sure if this is true. + + // Copy destination to buffer. + // In DoBlit, we need this step because Blit has + // a ROP argument. Here, we don't need it. + // In DoBlit, we may be able to eliminate this step + // if we check if the rop = copy +#if 0 + GrCopyArea(bufPixmap, gc, 0, 0, w, h, (Window) m_x11window, + 0, 0, GR_MODE_COPY); +#endif + + // Copy src to buffer using selected raster op (none selected + // in DrawBitmap, so just use Gxcopy) + GrCopyArea(bufPixmap, gc, 0, 0, w, h, pixmap, + 0, 0, GR_MODE_COPY); + + // Set masked area in buffer to BLACK (pixel value 0) + GrSetGCBackground(gc, WHITE); + GrSetGCForeground(gc, BLACK); + GrCopyArea(bufPixmap, gc, 0, 0, w, h, maskPixmap, + 0, 0, GR_MODE_AND); + + // set unmasked area in dest to BLACK + GrSetGCBackground(gc, BLACK); + GrSetGCForeground(gc, WHITE); + GrCopyArea((Window) m_x11window, gc, xx, yy, w, h, maskPixmap, + 0, 0, GR_MODE_AND); + + // OR buffer to dest + GrCopyArea((Window) m_x11window, gc, xx, yy, w, h, bufPixmap, + 0, 0, GR_MODE_OR); + + GrDestroyGC(gc); + GrDestroyWindow(bufPixmap); } + else + XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_x11window, + (GC) m_penGC, 0, 0, w, h, xx, yy ); - // First draw a rectangle representing the text background, if a text - // background is specified - if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT)) + /* remove mask again if any */ + if (useMask && mask) { - wxColour oldPenColour = m_currentColour; - m_currentColour = m_textBackgroundColour; - bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () && - (oldPenColour.Red () == m_textBackgroundColour.Red ()) && - (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) && - (oldPenColour.Green () == m_textBackgroundColour.Green ())); + if (!m_currentClippingRegion.IsNull()) + XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); + } +} - // This separation of the big && test required for gcc2.7/HP UX 9.02 - // or pixel value can be corrupted! - sameColour = (sameColour && - (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel())); +#else - if (!sameColour || !GetOptimization()) - { - int pixel = m_textBackgroundColour.AllocColour(m_display); - m_currentColour = m_textBackgroundColour; +// Normal X11 +void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap, + wxCoord x, wxCoord y, + bool useMask ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - // Set the GC to the required colour - if (pixel > -1) - { - XSetForeground ((Display*) m_display, (GC) m_gc, pixel); - if (m_window && m_window->GetBackingPixmap()) - XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel); - } - } - else - m_textBackgroundColour = oldPenColour ; + wxCHECK_RET( bitmap.IsOk(), wxT("invalid bitmap") ); + + bool is_mono = (bitmap.GetBitmap() != NULL); + + // scale/translate size and position + int xx = XLOG2DEV(x); + int yy = YLOG2DEV(y); - XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy); - if (m_window && m_window->GetBackingPixmap()) - XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy); + int w = bitmap.GetWidth(); + int h = bitmap.GetHeight(); + + CalcBoundingBox( x, y ); + CalcBoundingBox( x + w, y + h ); + + if (!m_x11window) return; + + int ww = XLOG2DEVREL(w); + int hh = YLOG2DEVREL(h); + + // compare to current clipping region + if (!m_currentClippingRegion.IsNull()) + { + wxRegion tmp( xx,yy,ww,hh ); + tmp.Intersect( m_currentClippingRegion ); + if (tmp.IsEmpty()) + return; + } + + // scale bitmap if required + wxBitmap use_bitmap; + if ((w != ww) || (h != hh)) + { + wxImage image( bitmap.ConvertToImage() ); + image.Rescale( ww, hh ); +#if 0 + if (is_mono) + use_bitmap = image.ConvertToMonoBitmap(255,255,255); + else +#endif + use_bitmap = image; + } + else + { + use_bitmap = bitmap; } - // Now set the text foreground and draw the text - if (m_textForegroundColour.Ok ()) + // apply mask if any + WXPixmap mask = NULL; + if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); + + bool setClipMask = false; + + if (!m_currentClippingRegion.IsNull() || (useMask && mask)) { - wxColour oldPenColour = m_currentColour; - m_currentColour = m_textForegroundColour; - bool sameColour = (oldPenColour.Ok () && m_currentColour.Ok () && - (oldPenColour.Red () == m_currentColour.Red ()) && - (oldPenColour.Blue () == m_currentColour.Blue ()) && - (oldPenColour.Green () == m_currentColour.Green ()) && - (oldPenColour.GetPixel() == m_currentColour.GetPixel())); + // XSetClipMask() call is necessary (because of clip region and/or transparent mask) + setClipMask = true; + Pixmap new_pixmap = 0; - if (!sameColour || !GetOptimization()) + if (!m_currentClippingRegion.IsNull()) { - int pixel = -1; - if (!m_colour) // Mono display - { - // Unless foreground is really white, draw it in black - unsigned char red = m_textForegroundColour.Red (); - unsigned char blue = m_textForegroundColour.Blue (); - unsigned char green = m_textForegroundColour.Green (); - if (red == (unsigned char) 255 && blue == (unsigned char) 255 - && green == (unsigned char) 255) - { - m_currentColour = *wxWHITE; - pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display)); - m_currentColour.SetPixel(pixel); - m_textForegroundColour.SetPixel(pixel); - } - else - { - m_currentColour = *wxBLACK; - pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display)); - m_currentColour.SetPixel(pixel); - m_textForegroundColour.SetPixel(pixel); - } - } - else + // clipping necessary => create new_pixmap + Display *xdisplay = (Display*) m_display; + int xscreen = DefaultScreen( xdisplay ); + Window xroot = RootWindow( xdisplay, xscreen ); + + new_pixmap = XCreatePixmap( xdisplay, xroot, ww, hh, 1 ); + GC gc = XCreateGC( xdisplay, new_pixmap, 0, NULL ); + + XSetForeground( xdisplay, gc, BlackPixel(xdisplay,xscreen) ); + + XSetFillStyle( xdisplay, gc, FillSolid ); + XFillRectangle( xdisplay, new_pixmap, gc, 0, 0, ww, hh ); + + XSetForeground( xdisplay, gc, WhitePixel(xdisplay,xscreen) ); + + if (useMask && mask) { - pixel = m_textForegroundColour.AllocColour((Display*) m_display); - m_currentColour.SetPixel(pixel); + // transparent mask => call XSetStipple + XSetFillStyle( xdisplay, gc, FillStippled ); + XSetTSOrigin( xdisplay, gc, 0, 0); + XSetStipple( xdisplay, gc, (Pixmap) mask); } - // Set the GC to the required colour - if (pixel > -1) + wxVector rects; + for ( wxRegionIterator iter(m_currentClippingRegion); + iter; + ++iter ) { - XSetForeground ((Display*) m_display, (GC) m_gc, pixel); - if (m_window && m_window->GetBackingPixmap()) - XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel); + XRectangle rect; + rect.x = iter.GetX() - xx; + rect.y = iter.GetY() - yy; + rect.width = iter.GetWidth(); + rect.height = iter.GetHeight(); + rects.push_back(rect); } + + XFillRectangles(xdisplay, new_pixmap, gc, &rects[0], rects.size()); + + XFreeGC( xdisplay, gc ); + } + + if (is_mono) + { + if (new_pixmap) + XSetClipMask( (Display*) m_display, (GC) m_textGC, new_pixmap ); + else + XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask ); + XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy ); } else - m_textForegroundColour = oldPenColour; + { + if (new_pixmap) + XSetClipMask( (Display*) m_display, (GC) m_penGC, new_pixmap ); + else + XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask ); + XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy ); + } + + if (new_pixmap) + XFreePixmap( (Display*) m_display, new_pixmap ); } - // We need to add the ascent, not the whole height, since X draws at the - // point above the descender. -#if 0 - if (use16) - XDrawString16((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, - (XChar2b *)(char*) (const char*) text, slen); + // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For + // drawing a mono-bitmap (XBitmap) we use the current text GC + if (is_mono) + XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_x11window, + (GC) m_textGC, 0, 0, ww, hh, xx, yy, 1 ); else -#endif // 0 - XDrawString((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen); + XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_x11window, + (GC) m_penGC, 0, 0, ww, hh, xx, yy ); - if (m_window && m_window->GetBackingPixmap()) { -#if 0 - if (use16) - XDrawString16((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent, - (XChar2b *)(char*) (const char*) text, slen); + // remove mask again if any + if (setClipMask) + { + if (is_mono) + { + XSetClipMask( (Display*) m_display, (GC) m_textGC, None ); + XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); + if (!m_currentClippingRegion.IsNull()) + XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); + } else -#endif // 0 - XDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent, (char*) (const char*) text, slen); + { + XSetClipMask( (Display*) m_display, (GC) m_penGC, None ); + XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 ); + if (!m_currentClippingRegion.IsNull()) + XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); + } } - - wxCoord w, h; - GetTextExtent (text, &w, &h); - CalcBoundingBox (x + w, y + h); - CalcBoundingBox (x, y); } +#endif + // wxUSE_NANOX/!wxUSE_NANOX -void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle ) +bool wxWindowDCImpl::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, + wxDC *source, wxCoord xsrc, wxCoord ysrc, + wxRasterOperationMode logical_func, bool useMask, + wxCoord xsrcMask, wxCoord ysrcMask ) { - if (angle == 0.0) + /* 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( IsOk(), false, wxT("invalid window dc") ); + + wxCHECK_MSG( source, false, wxT("invalid source dc") ); + + if (!m_x11window) return false; + + // transform the source DC coords to the device ones + xsrc = source->LogicalToDeviceX(xsrc); + ysrc = source->LogicalToDeviceY(ysrc); + + wxClientDC *srcDC = (wxClientDC*)source; + wxMemoryDC *memDC = (wxMemoryDC*)source; + wxWindowDCImpl *src_impl = (wxWindowDCImpl*) srcDC->GetImpl(); + + bool use_bitmap_method = false; + bool is_mono = false; + + // TODO: use the mask origin when drawing transparently + if (xsrcMask == -1 && ysrcMask == -1) { - DrawText(text, x, y); - return; + xsrcMask = xsrc; + ysrcMask = ysrc; } - wxCHECK_RET( Ok(), "invalid dc" ); + if (src_impl->m_isMemDC) + { + wxBitmap selected = memDC->GetSelectedBitmap(); - // Since X draws from the baseline of the text, must add the text height - int cx = 0; - int cy = 0; - int ascent = 0; - int slen; + if (!selected.IsOk()) return false; - slen = strlen(text); + /* 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 (m_font.Ok()) + if (useMask && (selected.GetMask())) + { + /* 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; + } + else if (selected.GetDepth() == 1) + { + /* we HAVE TO use the direct way for memory dcs + that are bitmaps because XCopyArea doesn't cope + with different bit depths */ + is_mono = true; + use_bitmap_method = true; + } + else if ((xsrc == 0) && (ysrc == 0) && + (width == selected.GetWidth()) && + (height == 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 ); + + // scale/translate size and position + wxCoord xx = XLOG2DEV(xdest); + wxCoord yy = YLOG2DEV(ydest); + + wxCoord ww = XLOG2DEVREL(width); + wxCoord hh = YLOG2DEVREL(height); + + // compare to current clipping region + if (!m_currentClippingRegion.IsNull()) { - // Calculate text extent. - WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); - int direction, descent; - XCharStruct overall_return; + wxRegion tmp( xx,yy,ww,hh ); + tmp.Intersect( m_currentClippingRegion ); + if (tmp.IsEmpty()) + return true; + } + + wxRasterOperationMode old_logical_func = m_logicalFunction; + SetLogicalFunction( logical_func ); + + if (use_bitmap_method) + { + wxBitmap selected = memDC->GetSelectedBitmap(); + + // scale/translate bitmap size + wxCoord bm_width = selected.GetWidth(); + wxCoord bm_height = selected.GetHeight(); + + wxCoord bm_ww = XLOG2DEVREL( bm_width ); + wxCoord bm_hh = YLOG2DEVREL( bm_height ); + + // scale bitmap if required + wxBitmap use_bitmap; + + if ((bm_width != bm_ww) || (bm_height != bm_hh)) + { + wxImage image( selected.ConvertToImage() ); + image = image.Scale( bm_ww, bm_hh ); + #if 0 - if (use16) - (void)XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *)(const char*) text, slen, &direction, - &ascent, &descent, &overall_return); + if (is_mono) + use_bitmap = image.ConvertToMonoBitmap(255,255,255); + else +#endif + use_bitmap = image; + } else -#endif // 0 - (void)XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) text, slen, &direction, - &ascent, &descent, &overall_return); + { + use_bitmap = selected; + } - cx = overall_return.width; - cy = ascent + descent; - } + // apply mask if any + WXPixmap mask = NULL; + if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); - wxBitmap src(cx, cy); - wxMemoryDC dc; - dc.SelectObject(src); - dc.SetFont(GetFont()); - dc.SetBackground(*wxWHITE_BRUSH); - dc.SetBrush(*wxBLACK_BRUSH); - dc.Clear(); - dc.DrawText(text, 0, 0); - dc.SetFont(wxNullFont); - - // Calculate the size of the rotated bounding box. - double dx = cos(angle / 180.0 * M_PI); - double dy = sin(angle / 180.0 * M_PI); - double x4 = -cy * dy; - double y4 = cy * dx; - double x3 = cx * dx; - double y3 = cx * dy; - double x2 = x3 + x4; - double y2 = y3 + y4; - double x1 = x; - double y1 = y; - - // Create image from the source bitmap after writing the text into it. - wxImage image(src); - - int minx = roundmin(0, roundmin(x4, roundmin(x2, x3))); - int miny = roundmin(0, roundmin(y4, roundmin(y2, y3))); - int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3))); - int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3))); - - // This rotates counterclockwise around the top left corner. - for (int rx = minx; rx < maxx; rx++) - { - for (int ry = miny; ry < maxy; ry++) + if (useMask && mask) { - // transform dest coords to source coords - int sx = (int) (rx * dx + ry * dy + 0.5); - int sy = (int) (ry * dx - rx * dy + 0.5); - if (sx >= 0 && sx < cx && sy >= 0 && sy < cy) + WXPixmap new_mask = NULL; +#if 0 + if (!m_currentClippingRegion.IsNull()) { - // draw black pixels, ignore white ones (i.e. transparent b/g) - if (image.GetRed(sx, sy) == 0) - { - DrawPoint((wxCoord) (x1 + maxx - rx), (wxCoord) (cy + y1 - ry)); - } + GdkColor col; + 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 ); + gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); + col.pixel = 0; + gdk_gc_set_background( gc, &col ); + col.pixel = 1; + gdk_gc_set_foreground( gc, &col ); + gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() ); + gdk_gc_set_clip_origin( gc, -xx, -yy ); + gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED ); + gdk_gc_set_stipple( gc, mask ); + gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); + gdk_gc_unref( gc ); + } +#endif + if (is_mono) + { + if (new_mask) + XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask ); else - { - // Background - //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry); - } + XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask ); + XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy ); + } + else + { + if (new_mask) + XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask ); + else + XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask ); + XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy ); + } + + if (new_mask) + XFreePixmap( (Display*) m_display, (Pixmap) new_mask ); + } + + // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For + // drawing a mono-bitmap (XBitmap) we use the current text GC + if (is_mono) + XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_x11window, + (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 ); + else + XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_x11window, + (GC) m_penGC, xsrc, ysrc, width, height, xx, yy ); + + // remove mask again if any + if (useMask && mask) + { + if (is_mono) + { + XSetClipMask( (Display*) m_display, (GC) m_textGC, None ); + XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); + if (!m_currentClippingRegion.IsNull()) + XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); + } + else + { + XSetClipMask( (Display*) m_display, (GC) m_penGC, None ); + XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 ); + if (!m_currentClippingRegion.IsNull()) + XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); } } } + else // use_bitmap_method + { + wxDCImpl *impl = srcDC->GetImpl(); + wxWindowDCImpl *x11_impl = wxDynamicCast(impl, wxWindowDCImpl); + if (!x11_impl) + { + SetLogicalFunction( old_logical_func ); + return false; + } + + 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 ); + + // copy including child window contents + XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors ); + XCopyArea( (Display*) m_display, (Window) x11_impl->GetX11Window(), (Window) bitmap.GetPixmap(), + (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 ); + XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren ); + + // scale image + wxImage image( bitmap.ConvertToImage() ); + image = image.Scale( ww, hh ); + + // convert to bitmap + bitmap = image; + + // draw scaled bitmap + XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_x11window, + (GC) m_penGC, 0, 0, width, height, xx, yy ); + } + else + { + // No scaling and not a memory dc with a mask either + // copy including child window contents + XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors ); + XCopyArea( (Display*) m_display, (Window) x11_impl->GetX11Window(), (Window) m_x11window, + (GC) m_penGC, xsrc, ysrc, width, height, xx, yy ); + XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren ); + } + } + + SetLogicalFunction( old_logical_func ); + + return true; +} + +void wxWindowDCImpl::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); + + if (!m_x11window) return; + + x = XLOG2DEV(x); + y = YLOG2DEV(y); + +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new(m_context); + pango_layout_set_font_description(layout, m_fontdesc); + + const wxScopedCharBuffer data(text.utf8_str()); + pango_layout_set_text(layout, data, data.length()); + + // Measure layout. + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + wxCoord width = w; + wxCoord height = h; + + // Draw layout. + x11_draw_layout( (Drawable) m_x11window, (GC) m_textGC, x, y, layout, m_textForegroundColour ); + + g_object_unref( G_OBJECT( layout ) ); + + CalcBoundingBox (x + width, y + height); + CalcBoundingBox (x, y); +#else + XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); + + wxCHECK_RET( xfont, wxT("invalid font") ); -#if 0 // First draw a rectangle representing the text background, if a text // background is specified - if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT)) + if (m_textBackgroundColour.IsOk () && (m_backgroundMode != wxTRANSPARENT)) { - wxColour oldPenColour = m_currentColour; - m_currentColour = m_textBackgroundColour; - bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () && - (oldPenColour.Red () == m_textBackgroundColour.Red ()) && - (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) && - (oldPenColour.Green () == m_textBackgroundColour.Green ())); + // Since X draws from the baseline of the text, must add the text height + int cx = 0; + int cy = 0; + int ascent = 0; + int slen; + int direction, descent; - // This separation of the big && test required for gcc2.7/HP UX 9.02 - // or pixel value can be corrupted! - sameColour = (sameColour && - (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel())); + slen = strlen(text); + XCharStruct overall_return; - if (!sameColour || !GetOptimization()) - { - int pixel = m_textBackgroundColour.AllocColour(m_display); - m_currentColour = m_textBackgroundColour; + (void)XTextExtents(xfont, (const char*) text.c_str(), slen, &direction, + &ascent, &descent, &overall_return); - // Set the GC to the required colour - if (pixel > -1) - { - XSetForeground ((Display*) m_display, (GC) m_gc, pixel); - if (m_window && m_window->GetBackingPixmap()) - XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel); - } - } - else - m_textBackgroundColour = oldPenColour ; + cx = overall_return.width; + cy = ascent + descent; + m_textBackgroundColour.CalcPixel(m_cmap); + m_textForegroundColour.CalcPixel(m_cmap); + XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel()); + XFillRectangle( (Display*) m_display, (Window) m_x11window, + (GC) m_textGC, x, y, cx, cy ); + XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel()); - XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy); - if (m_window && m_window->GetBackingPixmap()) - XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, - XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy); } + + XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid ); +#if !wxUSE_NANOX + // This may be a test for whether the font is 16-bit, but it also + // seems to fail for valid 8-bit fonts too. + if (1) // (xfont->min_byte1 == 0) && (xfont->max_byte1 == 0)) #endif + { + XDrawString( (Display*) m_display, (Window) m_x11window, + (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.length() ); + } + +#if 0 + if (m_font.GetUnderlined()) + { + wxCoord ul_y = y + XFontStructGetAscent(font); + if (font->descent > 0) ul_y++; + gdk_draw_line( m_x11window, m_textGC, x, ul_y, x + width, ul_y); + } - long w, h; - // XXX use pixmap size - GetTextExtent (text, &w, &h); - CalcBoundingBox (x + w, y + h); + width = wxCoord(width / m_scaleX); + height = wxCoord(height / m_scaleY); + + CalcBoundingBox (x + width, y + height); CalcBoundingBox (x, y); +#endif +#endif } -bool wxWindowDC::CanGetTextExtent() const +void wxWindowDCImpl::DoDrawRotatedText(const wxString& WXUNUSED(text), + wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), + double WXUNUSED(angle)) { - return TRUE; + wxFAIL_MSG( "not implemented" ); } -void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height, +void wxWindowDCImpl::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading, - wxFont *font ) const + const wxFont *font ) const { - wxCHECK_RET( Ok(), "invalid dc" ); - - wxFont* theFont = font; - if (!theFont) - theFont = (wxFont *)&m_font; // const_cast + // Do not test for DC validity here, querying text extents is supposed to + // work even with a non-initialized wxMemoryDC. And the code below does + // actually work in this case. - if (!theFont->Ok()) + if (string.empty()) { - // TODO: this should be an error log function - wxFAIL_MSG("set a valid font before calling GetTextExtent!"); - - if (width) *width = -1; - if (height) *height = -1; + if (width) (*width) = 0; + if (height) (*height) = 0; return; } - WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); - - int direction, ascent, descent2; - XCharStruct overall; - int slen; +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( m_context ); -#if 0 - if (use16) - slen = str16len(string); + if (font) + pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description ); else -#endif // 0 - slen = strlen(string); + pango_layout_set_font_description(layout, m_fontdesc); -#if 0 - if (use16) - XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction, - &ascent, &descent2, &overall); - else -#endif // 0 - XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction, - &ascent, &descent2, &overall); + const wxScopedCharBuffer data(string.utf8_str()); + pango_layout_set_text(layout, data, data.length()); - if (width) *width = XDEV2LOGREL (overall.width); - if (height) *height = YDEV2LOGREL (ascent + descent2); - if (descent) - *descent = descent2; - if (externalLeading) - *externalLeading = 0; -} + // Measure text. + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); -wxCoord wxWindowDC::GetCharWidth() const -{ - wxCHECK_MSG( Ok(), 0, "invalid dc" ); - wxCHECK_MSG( m_font.Ok(), 0, "invalid font" ); + if (width) (*width) = (wxCoord) w; + if (height) (*height) = (wxCoord) h; + if (descent) + { + // Do something about metrics here. TODO. + (*descent) = 0; + } + if (externalLeading) (*externalLeading) = 0; // ?? - WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display); + g_object_unref( G_OBJECT( layout ) ); +#else + wxFont fontToUse = m_font; + if (font) fontToUse = *font; - int direction, ascent, descent; - XCharStruct overall; - XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent, - &descent, &overall); - return XDEV2LOGREL(overall.width); -} + wxCHECK_RET( fontToUse.IsOk(), wxT("invalid font") ); -wxCoord wxWindowDC::GetCharHeight() const -{ - wxCHECK_MSG( Ok(), 0, "invalid dc" ); - wxCHECK_MSG( m_font.Ok(), 0, "invalid font" ); + XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display ); - WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); + wxCHECK_RET( xfont, wxT("invalid font") ); - int direction, ascent, descent; + int direction, ascent, descent2; XCharStruct overall; - XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent, - &descent, &overall); - // return XDEV2LOGREL(overall.ascent + overall.descent); - return XDEV2LOGREL(ascent + descent); + + XTextExtents( xfont, (const char*) string.c_str(), string.length(), &direction, + &ascent, &descent2, &overall); + + if (width) + *width = (wxCoord)( overall.width / m_scaleX ); + if (height) + *height = (wxCoord)((ascent + descent2) / m_scaleY ); + if (descent) + *descent = (wxCoord)(descent2 / m_scaleY ); + if (externalLeading) + *externalLeading = 0; // ?? +#endif } -void wxWindowDC::Clear() +wxCoord wxWindowDCImpl::GetCharWidth() const { - wxCHECK_RET( Ok(), "invalid dc" ); + // Do not test for DC validity here for the same reasons as in + // DoGetTextExtent() above. - int w, h; - if (m_window) - { - m_window->GetSize(&w, &h); +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( m_context ); - if (m_window && m_window->GetBackingPixmap()) - { - w = m_window->GetPixmapWidth(); - h = m_window->GetPixmapHeight(); - } - } + if (m_fontdesc) + pango_layout_set_font_description(layout, m_fontdesc); else - { - if (this->IsKindOf(CLASSINFO(wxMemoryDC))) - { - wxMemoryDC* memDC = (wxMemoryDC*) this; - w = memDC->GetBitmap().GetWidth(); - h = memDC->GetBitmap().GetHeight(); - } - else - return; - } + pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description); + + pango_layout_set_text(layout, "H", 1 ); + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + g_object_unref( G_OBJECT( layout ) ); + + return w; +#else + wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") ); + + XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); - wxBrush saveBrush = m_brush; - SetBrush (m_backgroundBrush); + wxCHECK_MSG( xfont, 0, wxT("invalid font") ); - XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, 0, w, h); + int direction, ascent, descent; + XCharStruct overall; - if (m_window && m_window->GetBackingPixmap()) - XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 0, 0, w, h); + XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall ); - m_brush = saveBrush; + return (wxCoord)(overall.width / m_scaleX); +#endif } -void wxWindowDC::Clear(const wxRect& rect) +wxCoord wxWindowDCImpl::GetCharHeight() const { - wxCHECK_RET( Ok(), "invalid dc" ); + // Do not test for DC validity here for the same reasons as in + // DoGetTextExtent() above. + +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( m_context ); + + if (m_fontdesc) + pango_layout_set_font_description(layout, m_fontdesc); + else + pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description); + + pango_layout_set_text(layout, "H", 1 ); + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + g_object_unref( G_OBJECT( layout ) ); + + return h; +#else + wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") ); - int x = rect.x; int y = rect.y; - int w = rect.width; int h = rect.height; + XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); - wxBrush saveBrush = m_brush; - SetBrush (m_backgroundBrush); + wxCHECK_MSG( xfont, 0, wxT("invalid font") ); - XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x, y, w, h); + int direction, ascent, descent; + XCharStruct overall; - if (m_window && m_window->GetBackingPixmap()) - XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, x, y, w, h); + XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall ); - m_brush = saveBrush; + return (wxCoord)((ascent+descent) / m_scaleY); +#endif } -void wxWindowDC::SetFont( const wxFont &font ) +void wxWindowDCImpl::Clear() { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - m_font = font; + if (!m_x11window) return; - if (!m_font.Ok()) + /* - 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_window) { - if ((m_oldFont != (WXFont) 0) && ((wxCoord) m_oldFont != -1)) - { - XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont); + int width,height; + m_window->GetSize( &width, &height ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height ); + return; + } - if (m_window && m_window->GetBackingPixmap()) - XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont); - } + if (m_isMemDC) + { + int width,height; + DoGetSize( &width, &height ); + XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height ); return; } +} - WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); +void wxWindowDCImpl::SetFont( const wxFont &font ) +{ + wxCHECK_RET( IsOk(), wxT("invalid dc") ); - Font fontId = ((XFontStruct*)pFontStruct)->fid; - XSetFont ((Display*) m_display, (GC) m_gc, fontId); + m_font = font; - if (m_window && m_window->GetBackingPixmap()) - XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId); +#if wxUSE_UNICODE + m_fontdesc = font.GetNativeFontInfo()->description; +#endif } -void wxWindowDC::SetPen( const wxPen &pen ) +void wxWindowDCImpl::SetPen( const wxPen &pen ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); + + if (m_pen == pen) return; m_pen = pen; - if (!m_pen.Ok()) - return; - wxBitmap oldStipple = m_currentStipple; - int oldStyle = m_currentStyle; - int oldFill = m_currentFill; - int old_pen_width = m_currentPenWidth; - int old_pen_join = m_currentPenJoin; - int old_pen_cap = m_currentPenCap; - int old_pen_nb_dash = m_currentPenDashCount; - wxMOTIFDash *old_pen_dash = m_currentPenDash; - - wxColour oldPenColour = m_currentColour; - m_currentColour = m_pen.GetColour (); - m_currentStyle = m_pen.GetStyle (); - m_currentFill = m_pen.GetStyle (); // TODO? - m_currentPenWidth = m_pen.GetWidth (); - m_currentPenJoin = m_pen.GetJoin (); - m_currentPenCap = m_pen.GetCap (); - m_currentPenDashCount = m_pen.GetDashCount(); - m_currentPenDash = (wxMOTIFDash*)m_pen.GetDash(); - - if (m_currentStyle == wxSTIPPLE) - m_currentStipple = * m_pen.GetStipple (); - - bool sameStyle = (oldStyle == m_currentStyle && - oldFill == m_currentFill && - old_pen_join == m_currentPenJoin && - old_pen_cap == m_currentPenCap && - old_pen_nb_dash == m_currentPenDashCount && - old_pen_dash == m_currentPenDash && - old_pen_width == m_currentPenWidth); - - bool sameColour = (oldPenColour.Ok () && - (oldPenColour.Red () == m_currentColour.Red ()) && - (oldPenColour.Blue () == m_currentColour.Blue ()) && - (oldPenColour.Green () == m_currentColour.Green ()) && - (oldPenColour.GetPixel() == m_currentColour.GetPixel())); - - if (!sameStyle || !GetOptimization()) - { - int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ()); - if (scaled_width < 0) - scaled_width = 0; - - int style; - int join; - int cap; - static const wxMOTIFDash dotted[] = {2, 5}; - static const wxMOTIFDash short_dashed[] = {4, 4}; - static const wxMOTIFDash long_dashed[] = {4, 8}; - static const wxMOTIFDash dotted_dashed[] = {6, 6, 2, 6}; - - // We express dash pattern in pen width unit, so we are - // independent of zoom factor and so on... - int req_nb_dash; - const wxMOTIFDash *req_dash; - - switch (m_pen.GetStyle ()) - { + if (!m_pen.IsOk()) return; + + if (!m_x11window) return; + + int width = m_pen.GetWidth(); + if (width <= 0) + { + // CMB: if width is non-zero scale it with the dc + width = 1; + } + else + { + // X doesn't allow different width in x and y and so we take + // the average + double w = 0.5 + + ( fabs((double) XLOG2DEVREL(width)) + + fabs((double) YLOG2DEVREL(width)) ) / 2.0; + width = (int)w; + } + + static const wxX11Dash dotted[] = {1, 1}; + static const wxX11Dash short_dashed[] = {2, 2}; + static const wxX11Dash long_dashed[] = {2, 4}; + static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3}; + + // We express dash pattern in pen width unit, so we are + // independent of zoom factor and so on... + int req_nb_dash; + const wxX11Dash *req_dash; + + int lineStyle = LineSolid; + switch (m_pen.GetStyle()) + { case wxUSER_DASH: - req_nb_dash = m_currentPenDashCount; - req_dash = m_currentPenDash; - style = LineOnOffDash; + { + lineStyle = LineOnOffDash; + req_nb_dash = m_pen.GetDashCount(); + req_dash = (wxX11Dash*)m_pen.GetDash(); break; + } case wxDOT: + { + lineStyle = LineOnOffDash; req_nb_dash = 2; req_dash = dotted; - style = LineOnOffDash; - break; - case wxSHORT_DASH: - req_nb_dash = 2; - req_dash = short_dashed; - style = LineOnOffDash; break; + } case wxLONG_DASH: + { + lineStyle = LineOnOffDash; req_nb_dash = 2; req_dash = long_dashed; - style = LineOnOffDash; break; + } + case wxSHORT_DASH: + { + lineStyle = LineOnOffDash; + req_nb_dash = 2; + req_dash = short_dashed; + break; + } case wxDOT_DASH: + { +// lineStyle = LineDoubleDash; + lineStyle = LineOnOffDash; req_nb_dash = 4; req_dash = dotted_dashed; - style = LineOnOffDash; break; + } + + case wxTRANSPARENT: + case wxSTIPPLE_MASK_OPAQUE: case wxSTIPPLE: case wxSOLID: - case wxTRANSPARENT: default: - style = LineSolid; - req_dash = (wxMOTIFDash*)NULL; + { + lineStyle = LineSolid; + req_dash = NULL; req_nb_dash = 0; + break; } + } - if (req_dash && req_nb_dash) + int capStyle = CapRound; + switch (m_pen.GetCap()) + { + case wxCAP_PROJECTING: { capStyle = CapProjecting; break; } + case wxCAP_BUTT: { capStyle = CapButt; break; } + case wxCAP_ROUND: + default: { - wxMOTIFDash *real_req_dash = new wxMOTIFDash[req_nb_dash]; - if (real_req_dash) + if (width <= 1) { - int factor = scaled_width == 0 ? 1 : scaled_width; - for (int i = 0; i < req_nb_dash; i++) - real_req_dash[i] = req_dash[i] * factor; - XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash); - - if (m_window && m_window->GetBackingPixmap()) - XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash); - delete[]real_req_dash; + width = 0; + capStyle = CapNotLast; } else { - // No Memory. We use non-scaled dash pattern... - XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash); - - if (m_window && m_window->GetBackingPixmap()) - XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash); + capStyle = CapRound; } - } - - switch (m_pen.GetCap ()) - { - case wxCAP_PROJECTING: - cap = CapProjecting; - break; - case wxCAP_BUTT: - cap = CapButt; - break; - case wxCAP_ROUND: - default: - cap = (scaled_width <= 1) ? CapNotLast : CapRound; break; } + } - switch (m_pen.GetJoin ()) - { - case wxJOIN_BEVEL: - join = JoinBevel; - break; - case wxJOIN_MITER: - join = JoinMiter; - break; + int joinStyle = JoinRound; + switch (m_pen.GetJoin()) + { + case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; } + case wxJOIN_MITER: { joinStyle = JoinMiter; break; } case wxJOIN_ROUND: - default: - join = JoinRound; - break; - } + default: { joinStyle = JoinRound; break; } + } - XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join); + XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle ); - if (m_window && m_window->GetBackingPixmap()) - XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join); - } + m_pen.GetColour().CalcPixel( m_cmap ); + XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() ); +} - if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization())) - { - Pixmap myStipple; +void wxWindowDCImpl::SetBrush( const wxBrush &brush ) +{ + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - oldStipple = wxNullBitmap; // For later reset!! + if (m_brush == brush) return; - switch (m_currentFill) - { - case wxBDIAGONAL_HATCH: - if (bdiag == (Pixmap) 0) - bdiag = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - bdiag_bits, bdiag_width, bdiag_height); - myStipple = bdiag; - break; - case wxFDIAGONAL_HATCH: - if (fdiag == (Pixmap) 0) - fdiag = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - fdiag_bits, fdiag_width, fdiag_height); - myStipple = fdiag; - break; - case wxCROSS_HATCH: - if (cross == (Pixmap) 0) - cross = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - cross_bits, cross_width, cross_height); - myStipple = cross; - break; - case wxHORIZONTAL_HATCH: - if (horiz == (Pixmap) 0) - horiz = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - horiz_bits, horiz_width, horiz_height); - myStipple = horiz; - break; - case wxVERTICAL_HATCH: - if (verti == (Pixmap) 0) - verti = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - verti_bits, verti_width, verti_height); - myStipple = verti; - break; - case wxCROSSDIAG_HATCH: - default: - if (cdiag == (Pixmap) 0) - cdiag = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - cdiag_bits, cdiag_width, cdiag_height); - myStipple = cdiag; - break; - } - XSetStipple ((Display*) m_display, (GC) m_gc, myStipple); + m_brush = brush; - if (m_window && m_window->GetBackingPixmap()) - XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple); - } - else if (m_currentStipple.Ok() - && ((m_currentStipple != oldStipple) || !GetOptimization())) - { - XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap()); + if (!m_brush.IsOk()) return; - if (m_window && m_window->GetBackingPixmap()) - XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap()); - } + if (!m_x11window) return; - if ((m_currentFill != oldFill) || !GetOptimization()) - { - int fill_style; + m_brush.GetColour().CalcPixel( m_cmap ); + XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() ); - if (m_currentFill == wxSTIPPLE) - fill_style = FillStippled; - else if (IS_HATCH (m_currentFill)) - fill_style = FillStippled; - else - fill_style = FillSolid; - XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style); - if (m_window && m_window->GetBackingPixmap()) - XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style); - } + XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid ); - // must test m_logicalFunction, because it involves background! - if (!sameColour || !GetOptimization() - || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2))) + if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->IsOk())) { - int pixel = -1; - if (m_pen.GetStyle () == wxTRANSPARENT) - pixel = m_backgroundPixel; - else if (!m_colour) + if (m_brush.GetStipple()->GetPixmap()) { - unsigned char red = m_pen.GetColour ().Red (); - unsigned char blue = m_pen.GetColour ().Blue (); - unsigned char green = m_pen.GetColour ().Green (); - if (red == (unsigned char) 255 && blue == (unsigned char) 255 - && green == (unsigned char) 255) - { - pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display)); - m_currentColour = *wxWHITE; - m_pen.GetColour().SetPixel(pixel); - m_currentColour.SetPixel(pixel); - } - else - { - pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display)); - m_currentColour = *wxBLACK; - m_pen.GetColour().SetPixel(pixel); - } + XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled ); + XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() ); } else { - pixel = m_pen.GetColour ().AllocColour(m_display); - m_currentColour.SetPixel(pixel); + XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled ); + XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() ); } + } - // Finally, set the GC to the required colour - if (pixel > -1) - { - if (m_logicalFunction == wxXOR) - { - XGCValues values; - XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values); - XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background); - if (m_window && m_window->GetBackingPixmap()) - XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background); - } - else - { - XSetForeground ((Display*) m_display, (GC) m_gc, pixel); - if (m_window && m_window->GetBackingPixmap()) - XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel); - } - } + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + { + XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled ); + XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() ); } - else - m_pen.GetColour().SetPixel(oldPenColour.GetPixel()); - m_autoSetting = 0; + if (m_brush.IsHatch()) + { + XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled ); + int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH; + XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] ); + } } -void wxWindowDC::SetBrush( const wxBrush &brush ) +void wxWindowDCImpl::SetBackground( const wxBrush &brush ) { - wxCHECK_RET( Ok(), "invalid dc" ); + /* CMB 21/7/98: Added SetBackground. Sets background brush + * for Clear() and bg colour for shapes filled with cross-hatch brush */ - m_brush = brush; + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT) - return; + if (m_backgroundBrush == brush) return; - int oldFill = m_currentFill; - wxBitmap oldStipple = m_currentStipple; + m_backgroundBrush = brush; - m_autoSetting |= 0x1; + if (!m_backgroundBrush.IsOk()) return; - m_currentFill = m_brush.GetStyle (); - if (m_currentFill == wxSTIPPLE) - m_currentStipple = * m_brush.GetStipple (); + if (!m_x11window) return; - wxColour oldBrushColour(m_currentColour); - m_currentColour = m_brush.GetColour (); + m_backgroundBrush.GetColour().CalcPixel( m_cmap ); + XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() ); + XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() ); + XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() ); + XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() ); - bool sameColour = (oldBrushColour.Ok () && - (oldBrushColour.Red () == m_currentColour.Red ()) && - (oldBrushColour.Blue () == m_currentColour.Blue ()) && - (oldBrushColour.Green () == m_currentColour.Green ()) && - (oldBrushColour.GetPixel() == m_currentColour.GetPixel())); + XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid ); - if ((oldFill != m_brush.GetStyle ()) || !GetOptimization()) + if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->IsOk())) { - switch (brush.GetStyle ()) + if (m_backgroundBrush.GetStipple()->GetPixmap()) { - case wxTRANSPARENT: - break; - case wxBDIAGONAL_HATCH: - case wxCROSSDIAG_HATCH: - case wxFDIAGONAL_HATCH: - case wxCROSS_HATCH: - case wxHORIZONTAL_HATCH: - case wxVERTICAL_HATCH: - case wxSTIPPLE: - { - // Chris Breeze 23/07/97: use background mode to determine whether - // fill style should be solid or transparent - int style = (m_backgroundMode == wxSOLID ? FillOpaqueStippled : FillStippled); - XSetFillStyle ((Display*) m_display, (GC) m_gc, style); - if (m_window && m_window->GetBackingPixmap()) - XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style); - } - break; - case wxSOLID: - default: - XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid); - if (m_window && m_window->GetBackingPixmap()) - XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, FillSolid); + XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled ); + XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() ); } - } - - if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization())) - { - Pixmap myStipple; - - switch (m_currentFill) + else { - case wxBDIAGONAL_HATCH: - if (bdiag == (Pixmap) 0) - bdiag = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - bdiag_bits, bdiag_width, bdiag_height); - myStipple = bdiag; - break; - case wxFDIAGONAL_HATCH: - if (fdiag == (Pixmap) 0) - fdiag = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - fdiag_bits, fdiag_width, fdiag_height); - myStipple = fdiag; - break; - case wxCROSS_HATCH: - if (cross == (Pixmap) 0) - cross = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - cross_bits, cross_width, cross_height); - myStipple = cross; - break; - case wxHORIZONTAL_HATCH: - if (horiz == (Pixmap) 0) - horiz = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - horiz_bits, horiz_width, horiz_height); - myStipple = horiz; - break; - case wxVERTICAL_HATCH: - if (verti == (Pixmap) 0) - verti = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - verti_bits, verti_width, verti_height); - myStipple = verti; - break; - case wxCROSSDIAG_HATCH: - default: - if (cdiag == (Pixmap) 0) - cdiag = XCreateBitmapFromData ((Display*) m_display, - RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), - cdiag_bits, cdiag_width, cdiag_height); - myStipple = cdiag; - break; + XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled ); + XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() ); } - XSetStipple ((Display*) m_display, (GC) m_gc, myStipple); - - if (m_window && m_window->GetBackingPixmap()) - XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple); - } - // X can forget the stipple value when resizing a window (apparently) - // so always set the stipple. - else if (m_currentStipple.Ok()) // && m_currentStipple != oldStipple) - { - XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap()); - if (m_window && m_window->GetBackingPixmap()) - XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap()); } - // must test m_logicalFunction, because it involves background! - if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR) + if (m_backgroundBrush.IsHatch()) { - int pixel = -1; - if (!m_colour) - { - // Policy - on a monochrome screen, all brushes are white, - // except when they're REALLY black!!! - unsigned char red = m_brush.GetColour ().Red (); - unsigned char blue = m_brush.GetColour ().Blue (); - unsigned char green = m_brush.GetColour ().Green (); - - if (red == (unsigned char) 0 && blue == (unsigned char) 0 - && green == (unsigned char) 0) - { - pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display)); - m_currentColour = *wxBLACK; - m_brush.GetColour().SetPixel(pixel); - m_currentColour.SetPixel(pixel); - } - else - { - pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display)); - m_currentColour = *wxWHITE; - m_brush.GetColour().SetPixel(pixel); - m_currentColour.SetPixel(pixel); - } - - // N.B. comment out the above line and uncomment the following lines - // if you want non-white colours to be black on a monochrome display. - /* - if (red == (unsigned char )255 && blue == (unsigned char)255 - && green == (unsigned char)255) - pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display)); - else - pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display)); - */ - } - else if (m_brush.GetStyle () != wxTRANSPARENT) - { - pixel = m_brush.GetColour().AllocColour(m_display); - m_currentColour.SetPixel(pixel); - } - if (pixel > -1) - { - // Finally, set the GC to the required colour - if (m_logicalFunction == wxXOR) - { - XGCValues values; - XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values); - XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background); - if (m_window && m_window->GetBackingPixmap()) - XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background); - } - else - { - XSetForeground ((Display*) m_display, (GC) m_gc, pixel); - if (m_window && m_window->GetBackingPixmap()) - XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel); - } - } + XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled ); + int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH; + XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] ); } - else - m_brush.GetColour().SetPixel(oldBrushColour.GetPixel()); -} - -void wxWindowDC::SetBackground( const wxBrush &brush ) -{ - wxCHECK_RET( Ok(), "invalid dc" ); - - m_backgroundBrush = brush; - - if (!m_backgroundBrush.Ok()) - return; - - int pixel = m_backgroundBrush.GetColour().AllocColour(m_display); - - // New behaviour, 10/2/99: setting the background brush of a DC - // doesn't affect the window background colour. -/* - // XSetWindowBackground doesn't work for non-Window pixmaps - if (!this->IsKindOf(CLASSINFO(wxMemoryDC))) - XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel); -*/ - - // Necessary for ::DrawIcon, which use fg/bg pixel or the GC. - // And Blit,... (Any fct that use XCopyPlane, in fact.) - XSetBackground ((Display*) m_display, (GC) m_gc, pixel); - if (m_window && m_window->GetBackingPixmap()) - XSetBackground ((Display*) m_display,(GC) m_gcBacking, pixel); } -void wxWindowDC::SetLogicalFunction( int function ) +void wxWindowDCImpl::SetLogicalFunction( wxRasterOperationMode function ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( IsOk(), wxT("invalid dc") ); int x_function; - /* MATTHEW: [9] */ if (m_logicalFunction == function) return; + // VZ: shouldn't this be a CHECK? + if (!m_x11window) + return; + switch (function) { case wxCLEAR: @@ -2077,331 +2115,314 @@ void wxWindowDC::SetLogicalFunction( int function ) break; } - XSetFunction((Display*) m_display, (GC) m_gc, x_function); - if (m_window && m_window->GetBackingPixmap()) - XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function); + XSetFunction( (Display*) m_display, (GC) m_penGC, x_function ); + XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function ); - if ((m_logicalFunction == wxXOR) != (function == wxXOR)) - /* MATTHEW: [9] Need to redo pen simply */ - m_autoSetting |= 0x2; + // to stay compatible with wxMSW, we don't apply ROPs to the text + // operations (i.e. DrawText/DrawRotatedText). + // True, but mono-bitmaps use the m_textGC and they use ROPs as well. + XSetFunction( (Display*) m_display, (GC) m_textGC, x_function ); m_logicalFunction = function; - } -void wxWindowDC::SetTextForeground( const wxColour &col ) +void wxWindowDCImpl::SetTextForeground( const wxColour &col ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - if (m_textForegroundColour == col) + // 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.IsOk() || (m_textForegroundColour == col) ) return; m_textForegroundColour = col; + if (m_x11window) + { + m_textForegroundColour.CalcPixel( m_cmap ); + XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() ); + } } -void wxWindowDC::SetTextBackground( const wxColour &col ) +void wxWindowDCImpl::SetTextBackground( const wxColour &col ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - if (m_textBackgroundColour == col) + // same as above + if ( !col.IsOk() || (m_textBackgroundColour == col) ) return; m_textBackgroundColour = col; - if (!m_textBackgroundColour.Ok()) - return; + + if (m_x11window) + { + m_textBackgroundColour.CalcPixel( m_cmap ); + XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() ); + } } -void wxWindowDC::SetBackgroundMode( int mode ) +void wxWindowDCImpl::SetBackgroundMode( int mode ) { + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); + m_backgroundMode = mode; + +#if wxUSE_NANOX + GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE); +#endif + + if (!m_x11window) return; + + // 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) + { + XSetFillStyle( (Display*) m_display, (GC) m_brushGC, + (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled ); + } } -void wxWindowDC::SetPalette( const wxPalette& palette ) +void wxWindowDCImpl::SetPalette( const wxPalette& WXUNUSED(palette) ) { - if (m_window) +#if 0 + if (m_x11window) { - if (palette.Ok()) + if (palette.IsOk()) /* Use GetXColormap */ - XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(), + XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(), (Colormap) palette.GetXColormap()); else /* Use wxGetMainColormap */ - XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(), + XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(), (Colormap) wxTheApp->GetMainColormap(m_display)); } +#endif } -// Helper function -void wxWindowDC::SetDCClipping() +void wxWindowDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) { - // m_userRegion is the region set by calling SetClippingRegion + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - if (m_currentRegion) - XDestroyRegion ((Region) m_currentRegion); + if (!m_x11window) return; - // We need to take into account - // clipping imposed on a window by a repaint. - // We'll combine it with the user region. But for now, - // just use the currently-defined user clipping region. - if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) ) - m_currentRegion = (WXRegion) XCreateRegion (); - else - m_currentRegion = (WXRegion) NULL; + if (width <= 0) + width = 1; - if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion) - XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_userRegion, (Region) m_currentRegion); - else if (m_userRegion) - XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion); - else if (m_window && m_window->GetUpdateRegion().Ok()) - XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_window->GetUpdateRegion().GetXRegion(), - (Region) m_currentRegion); + if (height <= 0) + height = 1; - if (m_currentRegion) - { - XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion); - } + wxRect rect; + rect.x = XLOG2DEV(x); + rect.y = YLOG2DEV(y); + rect.width = XLOG2DEVREL(width); + rect.height = YLOG2DEVREL(height); + + if (!m_currentClippingRegion.IsEmpty()) + m_currentClippingRegion.Intersect( rect ); else - { - XSetClipMask ((Display*) m_display, (GC) m_gc, None); - } + m_currentClippingRegion = rect; + +#if USE_PAINT_REGION + if (!m_paintClippingRegion.IsEmpty()) + m_currentClippingRegion.Intersect( m_paintClippingRegion ); +#endif + + wxCoord xx, yy, ww, hh; + m_currentClippingRegion.GetBox( xx, yy, ww, hh ); + wxX11DCImpl::DoSetClippingRegion( xx, yy, ww, hh ); + XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); + XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() ); + XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); + XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() ); } -void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) +void wxWindowDCImpl::DoSetDeviceClippingRegion( const wxRegion& region ) { - wxDC::DoSetClippingRegion( x, y, width, height ); - - if (m_userRegion) - XDestroyRegion ((Region) m_userRegion); - m_userRegion = (WXRegion) XCreateRegion (); - XRectangle r; - r.x = XLOG2DEV (x); - r.y = YLOG2DEV (y); - r.width = XLOG2DEVREL(width); - r.height = YLOG2DEVREL(height); - XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion); - - SetDCClipping (); - - // Needs to work differently for Pixmap: without this, - // there's a nasty (Display*) m_display bug. 8/12/94 - if (m_window && m_window->GetBackingPixmap()) - { - XRectangle rects[1]; - rects[0].x = XLOG2DEV_2(x); - rects[0].y = YLOG2DEV_2(y); - rects[0].width = XLOG2DEVREL(width); - rects[0].height = YLOG2DEVREL(height); - XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); + + if (region.Empty()) + { + DestroyClippingRegion(); + return; } + + if (!m_x11window) return; + + if (!m_currentClippingRegion.IsEmpty()) + m_currentClippingRegion.Intersect( region ); + else + m_currentClippingRegion = region; + +#if USE_PAINT_REGION + if (!m_paintClippingRegion.IsEmpty()) + m_currentClippingRegion.Intersect( m_paintClippingRegion ); +#endif + + wxCoord xx, yy, ww, hh; + m_currentClippingRegion.GetBox( xx, yy, ww, hh ); + wxX11DCImpl::DoSetClippingRegion( xx, yy, ww, hh ); + + XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); + XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() ); + XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); + XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() ); } -void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region ) +void wxWindowDCImpl::DestroyClippingRegion() { - wxRect box = region.GetBox(); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); - wxDC::DoSetClippingRegion( box.x, box.y, box.width, box.height ); + wxDCImpl::DestroyClippingRegion(); - if (m_userRegion) - XDestroyRegion ((Region) m_userRegion); - m_userRegion = (WXRegion) XCreateRegion (); + m_currentClippingRegion.Clear(); - XUnionRegion((Region) m_userRegion, (Region) region.GetXRegion(), (Region) m_userRegion); +#if USE_PAINT_REGION + if (!m_paintClippingRegion.IsEmpty()) + m_currentClippingRegion.Union( m_paintClippingRegion ); +#endif - SetDCClipping (); + if (!m_x11window) return; - // Needs to work differently for Pixmap: without this, - // there's a nasty (Display*) m_display bug. 8/12/94 - if (m_window && m_window->GetBackingPixmap()) + if (m_currentClippingRegion.IsEmpty()) + { + XSetClipMask( (Display*) m_display, (GC) m_penGC, None ); + XSetClipMask( (Display*) m_display, (GC) m_brushGC, None ); + XSetClipMask( (Display*) m_display, (GC) m_textGC, None ); + XSetClipMask( (Display*) m_display, (GC) m_bgGC, None ); + } + else { - XRectangle rects[1]; - rects[0].x = XLOG2DEV_2(box.x); - rects[0].y = YLOG2DEV_2(box.y); - rects[0].width = XLOG2DEVREL(box.width); - rects[0].height = YLOG2DEVREL(box.height); - XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted); + XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); + XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() ); + XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); + XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() ); } } - -void wxWindowDC::DestroyClippingRegion() +void wxWindowDCImpl::Destroy() { - wxDC::DestroyClippingRegion(); + if (m_penGC) wxFreePoolGC( (GC) m_penGC ); + m_penGC = NULL; + if (m_brushGC) wxFreePoolGC( (GC) m_brushGC ); + m_brushGC = NULL; + if (m_textGC) wxFreePoolGC( (GC) m_textGC ); + m_textGC = NULL; + if (m_bgGC) wxFreePoolGC( (GC) m_bgGC ); + m_bgGC = NULL; +} - if (m_userRegion) - XDestroyRegion ((Region) m_userRegion); - m_userRegion = NULL; +void wxWindowDCImpl::ComputeScaleAndOrigin() +{ + /* CMB: copy scale to see if it changes */ + double origScaleX = m_scaleX; + double origScaleY = m_scaleY; - SetDCClipping (); + wxDCImpl::ComputeScaleAndOrigin(); - XGCValues gc_val; - gc_val.clip_mask = None; - if (m_window && m_window->GetBackingPixmap()) - XChangeGC((Display*) m_display, (GC) m_gcBacking, GCClipMask, &gc_val); + /* CMB: if scale has changed call SetPen to recalulate the line width */ + if ((m_scaleX != origScaleX || m_scaleY != origScaleY) && + (m_pen.IsOk())) + { + /* 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 -wxSize wxWindowDC::GetPPI() const +wxSize wxWindowDCImpl::GetPPI() const { return wxSize(100, 100); } -int wxWindowDC::GetDepth() const +int wxWindowDCImpl::GetDepth() const { - // TODO - return 24; -} - + wxFAIL_MSG(wxT("not implemented")); + return -1; +} +//----------------------------------------------------------------------------- +// wxClientDC +//----------------------------------------------------------------------------- -// ---------------------------------------------------------------------------- -// wxPaintDC -// ---------------------------------------------------------------------------- +IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl) -wxPaintDC::wxPaintDC(wxWindow* win) : wxWindowDC(win) +wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *window ) + : wxWindowDCImpl( owner, window ) { - wxRegion* region = NULL; + wxCHECK_RET( window, wxT("NULL window in wxClientDC::wxClientDC") ); - // Combine all the update rects into a region - const wxRectList& updateRects(win->GetUpdateRects()); - if ( updateRects.GetCount() != 0 ) - { - for ( wxRectList::Node *node = updateRects.GetFirst(); - node; - node = node->GetNext() ) - { - wxRect* rect = node->GetData(); + m_x11window = (WXWindow*) window->GetClientAreaWindow(); - if (!region) - region = new wxRegion(*rect); - else - // TODO: is this correct? In SetDCClipping above, - // XIntersectRegion is used to combine paint and user - // regions. XIntersectRegion appears to work in that case... - region->Union(*rect); - } - } - else + // Adjust the client area when the wxWindow is not using 2 X11 windows. + if (m_x11window == (WXWindow*) window->X11GetMainWindow()) { - int cw, ch; - win->GetClientSize(&cw, &ch); - region = new wxRegion(wxRect(0, 0, cw, ch)); + wxPoint ptOrigin = window->GetClientAreaOrigin(); + SetDeviceOrigin(ptOrigin.x, ptOrigin.y); + wxSize size = window->GetClientSize(); + DoSetClippingRegion( 0, 0, size.x, size.y ); } - - win->SetUpdateRegion(*region); - - wxRegion& theRegion(win->GetUpdateRegion()); - theRegion.SetRects(updateRects); // We also store in terms of rects, for iteration to work. - - // Set the clipping region. Any user-defined region will be combined with this - // one in SetDCClipping. - XSetRegion ((Display*) m_display, (GC) m_gc, (Region) region->GetXRegion()); - - delete region; } -wxPaintDC::~wxPaintDC() +void wxClientDCImpl::DoGetSize(int *width, int *height) const { - XSetClipMask ((Display*) m_display, (GC) m_gc, None); - if (m_window) - m_window->ClearUpdateRegion(); + wxCHECK_RET( m_window, wxT("GetSize() doesn't work without window") ); + + m_window->GetClientSize( width, height ); } // ---------------------------------------------------------------------------- -// private functions +// wxPaintDC // ---------------------------------------------------------------------------- -/* - Used when copying between drawables on different (Display*) m_displays. Not - very fast, but better than giving up. -*/ - -static void XCopyRemote(Display *src_display, Display *dest_display, - Drawable src, Drawable dest, - GC destgc, - int srcx, int srcy, - unsigned int w, unsigned int h, - int destx, int desty, - bool more, XImage **cache) -{ - XImage *image, *destimage; - Colormap destcm, srccm; - static const int CACHE_SIZE = 256; - - unsigned int i, j; - unsigned long cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE]; - int k, cache_pos, all_cache; +IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxClientDCImpl) - if (!cache || !*cache) - image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap); - else - image = *cache; - - destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap); - - srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display); - destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display); - - cache_pos = 0; - all_cache = FALSE; - - for (i = 0; i < w; i++) - for (j = 0; j < h; j++) { - unsigned long pixel; - XColor xcol; - - pixel = XGetPixel(image, i, j); - for (k = cache_pos; k--; ) - if (cachesrc[k] == pixel) { - pixel = cachedest[k]; - goto install; - } - if (all_cache) - for (k = CACHE_SIZE; k-- > cache_pos; ) - if (cachesrc[k] == pixel) { - pixel = cachedest[k]; - goto install; - } - - cachesrc[cache_pos] = xcol.pixel = pixel; - XQueryColor(src_display, srccm, &xcol); - if (!XAllocColor(dest_display, destcm, &xcol)) - xcol.pixel = 0; - cachedest[cache_pos] = pixel = xcol.pixel; - - if (++cache_pos >= CACHE_SIZE) { - cache_pos = 0; - all_cache = TRUE; - } - -install: - XPutPixel(destimage, i, j, pixel); - } +wxPaintDCImpl::wxPaintDCImpl(wxDC *owner, wxWindow* window) + : wxClientDCImpl(owner, window) +{ +#if USE_PAINT_REGION + if (!window->GetClipPaintRegion()) + return; - XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h); - XDestroyImage(destimage); + m_paintClippingRegion = window->GetUpdateRegion(); + Region region = (Region) m_paintClippingRegion.GetX11Region(); + if (region) + { + m_currentClippingRegion.Union( m_paintClippingRegion ); - if (more) - *cache = image; - else - XDestroyImage(image); + XSetRegion( (Display*) m_display, (GC) m_penGC, region ); + XSetRegion( (Display*) m_display, (GC) m_brushGC, region ); + XSetRegion( (Display*) m_display, (GC) m_textGC, region ); + XSetRegion( (Display*) m_display, (GC) m_bgGC, region ); + } +#endif // USE_PAINT_REGION } -#if 0 +// ---------------------------------------------------------------------------- +// wxDCModule +// ---------------------------------------------------------------------------- -/* Helper function for 16-bit fonts */ -static int str16len(const char *s) +class wxDCModule : public wxModule { - int count = 0; - - while (s[0] && s[1]) { - count++; - s += 2; +public: + // we must be cleaned up before wxDisplayModule which closes the global + // display + wxDCModule() + { + AddDependency(wxClassInfo::FindClass(wxT("wxX11DisplayModule"))); } - return count; -} + bool OnInit() { wxInitGCPool(); return true; } + void OnExit() { wxCleanUpGCPool(); } + +private: + DECLARE_DYNAMIC_CLASS(wxDCModule) +}; + +IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) -#endif // 0