X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a11672a469f036436838911c268cb2f8d5da5bf8..3338a5bde55eabf53f0aea4eb9f01a8b45b4039d:/src/x11/dcclient.cpp diff --git a/src/x11/dcclient.cpp b/src/x11/dcclient.cpp index c00bb29e35..2b8e355341 100644 --- a/src/x11/dcclient.cpp +++ b/src/x11/dcclient.cpp @@ -9,7 +9,7 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "dcclient.h" #endif @@ -18,11 +18,21 @@ #include "wx/window.h" #include "wx/app.h" #include "wx/image.h" +#include "wx/module.h" +#include "wx/fontutil.h" #include "wx/x11/private.h" #include +#if wxUSE_UNICODE +#include "glib.h" +#include "pango/pangox.h" +#include "pango/pangoxft.h" + +#include "pango_x.cpp" +#endif + //----------------------------------------------------------------------------- // local defines //----------------------------------------------------------------------------- @@ -162,6 +172,11 @@ wxWindowDC::wxWindowDC() m_isMemDC = FALSE; m_isScreenDC = FALSE; m_owner = (wxWindow *)NULL; + +#if wxUSE_UNICODE + m_context = (PangoContext *)NULL; + m_fontdesc = (PangoFontDescription *)NULL; +#endif } wxWindowDC::wxWindowDC( wxWindow *window ) @@ -192,6 +207,11 @@ wxWindowDC::wxWindowDC( wxWindow *window ) m_display = (WXDisplay *) wxGlobalDisplay(); +#if wxUSE_UNICODE + m_context = wxTheApp->GetPangoContext(); + m_fontdesc = window->GetFont().GetNativeFontInfo()->description; +#endif + int screen = DefaultScreen( (Display*) m_display ); m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen ); @@ -225,7 +245,6 @@ void wxWindowDC::SetUpDC() m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_SCREEN ); m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_SCREEN ); } -#if 0 else if (m_isMemDC && (((wxMemoryDC*)this)->m_selected.GetDepth() == 1)) { @@ -234,7 +253,6 @@ void wxWindowDC::SetUpDC() m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_MONO ); m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_MONO ); } -#endif else { m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_COLOUR ); @@ -248,6 +266,9 @@ void wxWindowDC::SetUpDC() m_backgroundBrush.GetColour().CalcPixel( m_cmap ); unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel(); + m_textForegroundColour = *wxBLACK; + m_textBackgroundColour = *wxWHITE; + /* m_textGC */ m_textForegroundColour.CalcPixel( m_cmap ); XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() ); @@ -257,6 +278,11 @@ void wxWindowDC::SetUpDC() XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillSolid ); +#if wxUSE_NANOX + // By default, draw transparently + GrSetGCUseBackground((GC) m_textGC, FALSE); +#endif + /* m_penGC */ m_pen.GetColour().CalcPixel( m_cmap ); XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() ); @@ -310,10 +336,13 @@ void wxWindowDC::DoGetSize( int* width, int* height ) const m_owner->GetSize(width, height); } -void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1), - const wxColour& WXUNUSED(col), int WXUNUSED(style) ) +extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, + const wxColour & col, int style); + +bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y, + const wxColour& col, int style) { - wxFAIL_MSG("not implemented"); + return wxDoFloodFill(this, x, y, col, style); } bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const @@ -325,7 +354,7 @@ bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const memdc.SelectObject(bitmap); memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1); memdc.SelectObject(wxNullBitmap); - wxImage image(bitmap); + wxImage image(bitmap.ConvertToImage()); col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0)); return TRUE; } @@ -337,13 +366,22 @@ void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) if (m_pen.GetStyle() != wxTRANSPARENT) { if (m_window) - XDrawLine( (Display*) m_display, (Window) m_window, - (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) ); + { + // 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; + DrawLines( 2, points, 0, 0 ); + + // XDrawLine( (Display*) m_display, (Window) m_window, + // (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) ); + } CalcBoundingBox(x1, y1); CalcBoundingBox(x2, y2); - - wxLogDebug("Drawing line at %d, %d -> %d, %d", XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) ); } } @@ -745,18 +783,135 @@ void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord h if (m_pen.GetStyle () != wxTRANSPARENT) { XDrawRectangle( (Display*) m_display, (Window) m_window, - (GC) m_penGC, xx, yy, ww, hh ); + (GC) m_penGC, xx, yy, ww-1, hh-1 ); } } CalcBoundingBox( x, y ); CalcBoundingBox( x + width, y + height ); - wxLogDebug("Drawing rectangle at %d, %d (%dx%d)", x, y, width, height); } void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) { - // later + wxCHECK_RET( Ok(), 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_window, + (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_window) + { + // 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_window, (GC) m_textGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (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_window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (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_window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (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) + { + 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_window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); + XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0); + } + else + { + XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); + XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); + } + } + if (m_pen.GetStyle() != wxTRANSPARENT) + { + XDrawLine( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+rr+1, yy, xx+ww-rr, yy ); + XDrawLine( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+rr+1, yy+hh, xx+ww-rr, yy+hh ); + XDrawLine( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx, yy+rr+1, xx, yy+hh-rr ); + XDrawLine( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+ww, yy+rr+1, xx+ww, yy+hh-rr ); + XDrawArc( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx, yy, dd, dd, 90*64, 90*64 ); + XDrawArc( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); + XDrawArc( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); + XDrawArc( (Display*) m_display, (Window) m_window, (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 wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) @@ -838,8 +993,10 @@ void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord hei void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y) { + DoDrawBitmap(icon, x, y, TRUE); } +#if wxUSE_NANOX void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, wxCoord x, wxCoord y, bool useMask ) @@ -878,14 +1035,14 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, wxBitmap use_bitmap; if ((w != ww) || (h != hh)) { - wxImage image( bitmap ); + wxImage image( bitmap.ConvertToImage() ); image.Rescale( ww, hh ); #if 0 if (is_mono) use_bitmap = image.ConvertToMonoBitmap(255,255,255); else #endif - use_bitmap = image.ConvertToBitmap(); + use_bitmap = image; } else { @@ -894,8 +1051,127 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, /* apply mask if any */ WXPixmap mask = NULL; - if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); + 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_window, + 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_window, gc, xx, yy, w, h, maskPixmap, + 0, 0, GR_MODE_AND); + + // OR buffer to dest + GrCopyArea((Window) m_window, 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_window, + (GC) m_penGC, 0, 0, w, h, xx, yy ); + + /* remove mask again if any */ + if (useMask && mask) + { + if (!m_currentClippingRegion.IsNull()) + XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); + } +} + +#else + +// Normal X11 +void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, + wxCoord x, wxCoord y, + bool useMask ) +{ + wxCHECK_RET( Ok(), wxT("invalid window dc") ); + + wxCHECK_RET( bitmap.Ok(), 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(); + + CalcBoundingBox( x, y ); + CalcBoundingBox( x + w, y + h ); + + if (!m_window) 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; + } + + // apply mask if any + WXPixmap mask = NULL; + if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); + if (useMask && mask) { WXPixmap new_mask = NULL; @@ -940,10 +1216,9 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, 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 */ + // 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_window, (GC) m_textGC, 0, 0, w, h, xx, yy, 1 ); @@ -951,7 +1226,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window, (GC) m_penGC, 0, 0, w, h, xx, yy ); - /* remove mask again if any */ + // remove mask again if any if (useMask && mask) { if (is_mono) @@ -970,9 +1245,11 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, } } } +#endif + // wxUSE_NANOX/!wxUSE_NANOX bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, - wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask, + wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask, wxCoord xsrcMask, wxCoord ysrcMask ) { /* this is the nth try to get this utterly useless function to @@ -996,13 +1273,13 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he bool use_bitmap_method = FALSE; bool is_mono = FALSE; - /* TODO: use the mask origin when drawing transparently */ + // TODO: use the mask origin when drawing transparently if (xsrcMask == -1 && ysrcMask == -1) { - xsrcMask = xsrc; ysrcMask = ysrc; + xsrcMask = xsrc; + ysrcMask = ysrc; } -#if 0 if (srcDC->m_isMemDC) { if (!memDC->m_selected.Ok()) return FALSE; @@ -1047,14 +1324,14 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he CalcBoundingBox( xdest, ydest ); CalcBoundingBox( xdest + width, ydest + height ); - /* scale/translate size and position */ + // 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 */ + // compare to current clipping region if (!m_currentClippingRegion.IsNull()) { wxRegion tmp( xx,yy,ww,hh ); @@ -1068,38 +1345,41 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he if (use_bitmap_method) { - /* scale/translate bitmap size */ + // scale/translate bitmap size wxCoord bm_width = memDC->m_selected.GetWidth(); wxCoord bm_height = memDC->m_selected.GetHeight(); wxCoord bm_ww = XLOG2DEVREL( bm_width ); wxCoord bm_hh = YLOG2DEVREL( bm_height ); - /* scale bitmap if required */ + // scale bitmap if required wxBitmap use_bitmap; if ((bm_width != bm_ww) || (bm_height != bm_hh)) { - wxImage image( memDC->m_selected ); + wxImage image( memDC->m_selected.ConvertToImage() ); image = image.Scale( bm_ww, bm_hh ); +#if 0 if (is_mono) use_bitmap = image.ConvertToMonoBitmap(255,255,255); else - use_bitmap = image.ConvertToBitmap(); +#endif + use_bitmap = image; } else { use_bitmap = memDC->m_selected; } - /* apply mask if any */ - GdkBitmap *mask = (GdkBitmap *) NULL; + // apply mask if any + WXPixmap mask = NULL; if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); if (useMask && mask) { - GdkBitmap *new_mask = (GdkBitmap*) NULL; + WXPixmap new_mask = NULL; +#if 0 if (!m_currentClippingRegion.IsNull()) { GdkColor col; @@ -1119,59 +1399,62 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); gdk_gc_unref( gc ); } - +#endif if (is_mono) { if (new_mask) - gdk_gc_set_clip_mask( m_textGC, new_mask ); + XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask ); else - gdk_gc_set_clip_mask( m_textGC, mask ); - gdk_gc_set_clip_origin( m_textGC, xx, yy ); + XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask ); + XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy ); } else { if (new_mask) - gdk_gc_set_clip_mask( m_penGC, new_mask ); + XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask ); else - gdk_gc_set_clip_mask( m_penGC, mask ); - gdk_gc_set_clip_origin( m_penGC, xx, yy ); + XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask ); + XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy ); } + if (new_mask) - gdk_bitmap_unref( 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 */ + // 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) - gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh ); + XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window, + (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 ); else - gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh ); + XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window, + (GC) m_penGC, xsrc, ysrc, width, height, xx, yy ); - /* remove mask again if any */ + // remove mask again if any if (useMask && mask) { if (is_mono) { - gdk_gc_set_clip_mask( m_textGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_textGC, 0, 0 ); + XSetClipMask( (Display*) m_display, (GC) m_textGC, None ); + XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); if (!m_currentClippingRegion.IsNull()) - gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() ); + XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); } else { - gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_penGC, 0, 0 ); + XSetClipMask( (Display*) m_display, (GC) m_penGC, None ); + XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 ); if (!m_currentClippingRegion.IsNull()) - gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); + XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); } } } - else /* use_bitmap_method */ + else // use_bitmap_method { if ((width != ww) || (height != hh)) { - /* draw source window into a bitmap as we cannot scale + /* 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 @@ -1186,42 +1469,38 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he wxBitmap bitmap( width, height ); - /* copy including child window contents */ - gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS ); - gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0, - srcDC->GetWindow(), - xsrc, ysrc, width, height ); - gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN ); + // copy including child window contents + XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors ); + XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (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 ); + // scale image + wxImage image( bitmap.ConvertToImage() ); image = image.Scale( ww, hh ); - /* convert to bitmap */ - bitmap = image.ConvertToBitmap(); - - /* draw scaled bitmap */ - gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); + // convert to bitmap + bitmap = image; + // draw scaled bitmap + XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window, + (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 */ - gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS ); - gdk_window_copy_area( m_window, m_penGC, xx, yy, - srcDC->GetWindow(), - xsrc, ysrc, width, height ); - gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN ); + // 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) srcDC->GetWindow(), (Window) m_window, + (GC) m_penGC, xsrc, ysrc, width, height, xx, yy ); + XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren ); } } SetLogicalFunction( old_logical_func ); + return TRUE; -#endif - - return FALSE; } void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) @@ -1230,36 +1509,75 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) if (!m_window) return; - XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); - - wxCHECK_RET( xfont, wxT("invalid font") ); - x = XLOG2DEV(x); y = YLOG2DEV(y); -#if 0 - wxCoord width = gdk_string_width( font, text.mbc_str() ); - wxCoord height = font->ascent + font->descent; +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new(m_context); + pango_layout_set_font_description(layout, m_fontdesc); + + const wxCharBuffer data = wxConvUTF8.cWC2MB( text ); + pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); + + // 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_window, (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 ); - if ( m_backgroundMode == wxSOLID ) + wxCHECK_RET( xfont, wxT("invalid font") ); + + // First draw a rectangle representing the text background, if a text + // background is specified + if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT)) { - gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() ); - gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height ); - gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() ); + // 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; + + slen = strlen(text); + XCharStruct overall_return; + + (void)XTextExtents(xfont, (char*) text.c_str(), slen, &direction, + &ascent, &descent, &overall_return); + + 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_window, + (GC) m_textGC, x, y, cx, cy ); + XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel()); + } -#endif XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid ); +#if !wxUSE_NANOX if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0)) - { +#endif + { XDrawString( (Display*) m_display, (Window) m_window, - (GC) m_textGC, x, y + xfont->ascent, text.c_str(), text.Len() ); - } + (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() ); + } #if 0 if (m_font.GetUnderlined()) { - wxCoord ul_y = y + font->ascent; + wxCoord ul_y = y + XFontStructGetAscent(font); if (font->descent > 0) ul_y++; gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y); } @@ -1270,6 +1588,7 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) CalcBoundingBox (x + width, y + height); CalcBoundingBox (x, y); #endif +#endif } void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle ) @@ -1281,12 +1600,45 @@ void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoor wxCoord *descent, wxCoord *externalLeading, wxFont *font ) const { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( Ok(), wxT("invalid dc") ); + if (string.IsEmpty()) + { + if (width) (*width) = 0; + if (height) (*height) = 0; + return; + } + +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( m_context ); + + if (font) + pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description ); + else + pango_layout_set_font_description(layout, m_fontdesc); + + const wxCharBuffer data = wxConvUTF8.cWC2MB( string ); + pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); + + // Measure text. + int w,h; + pango_layout_get_pixel_size(layout, &w, &h); + + if (width) (*width) = (wxCoord) w; + if (height) (*height) = (wxCoord) h; + if (descent) + { + // Do something about metrics here. TODO. + (*descent) = 0; + } + if (externalLeading) (*externalLeading) = 0; // ?? + + g_object_unref( G_OBJECT( layout ) ); +#else wxFont fontToUse = m_font; if (font) fontToUse = *font; - wxCHECK_RET( fontToUse.Ok(), "invalid font" ); + wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") ); XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display ); @@ -1295,7 +1647,7 @@ void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoor int direction, ascent, descent2; XCharStruct overall; - XTextExtents( xfont, string.c_str(), string.Len(), &direction, + XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction, &ascent, &descent2, &overall); if (width) @@ -1306,13 +1658,31 @@ void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoor *descent = (wxCoord)(descent2 / m_scaleY ); if (externalLeading) *externalLeading = 0; // ?? +#endif } wxCoord wxWindowDC::GetCharWidth() const { - wxCHECK_MSG( Ok(), 0, "invalid dc" ); + wxCHECK_MSG( Ok(), 0, wxT("invalid dc") ); - wxCHECK_MSG( m_font.Ok(), 0, "invalid font" ); +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( m_context ); + + if (!m_fontdesc) + { + char *crash = NULL; + *crash = 0; + } + + pango_layout_set_font_description(layout, m_fontdesc); + 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.Ok(), 0, wxT("invalid font") ); XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); @@ -1324,13 +1694,32 @@ wxCoord wxWindowDC::GetCharWidth() const XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall ); return (wxCoord)(overall.width / m_scaleX); +#endif } wxCoord wxWindowDC::GetCharHeight() const { - wxCHECK_MSG( Ok(), 0, "invalid dc" ); + wxCHECK_MSG( Ok(), 0, wxT("invalid dc") ); + +#if wxUSE_UNICODE + PangoLayout *layout = pango_layout_new( m_context ); + + if (!m_fontdesc) + { + char *crash = NULL; + *crash = 0; + } + + pango_layout_set_font_description(layout, m_fontdesc); - wxCHECK_MSG( m_font.Ok(), 0, "invalid font" ); + 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.Ok(), 0, wxT("invalid font") ); XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); @@ -1342,6 +1731,7 @@ wxCoord wxWindowDC::GetCharHeight() const XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall ); return (wxCoord)((ascent+descent) / m_scaleY); +#endif } void wxWindowDC::Clear() @@ -1376,7 +1766,7 @@ void wxWindowDC::Clear() void wxWindowDC::SetFont( const wxFont &font ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( Ok(), wxT("invalid dc") ); m_font = font; } @@ -1535,14 +1925,14 @@ void wxWindowDC::SetBrush( const wxBrush &brush ) else { XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled ); -// XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() ); + XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() ); } } 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() ); + XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() ); } if (IS_HATCH(m_brush.GetStyle())) @@ -1586,7 +1976,7 @@ void wxWindowDC::SetBackground( const wxBrush &brush ) else { 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_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() ); } } @@ -1600,7 +1990,7 @@ void wxWindowDC::SetBackground( const wxBrush &brush ) void wxWindowDC::SetLogicalFunction( int function ) { - wxCHECK_RET( Ok(), "invalid dc" ); + wxCHECK_RET( Ok(), wxT("invalid dc") ); int x_function; @@ -1717,6 +2107,10 @@ void wxWindowDC::SetBackgroundMode( int mode ) m_backgroundMode = mode; +#if wxUSE_NANOX + GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE); +#endif + if (!m_window) return; // CMB 21/7/98: fill style of cross-hatch brushes is affected by @@ -1885,64 +2279,63 @@ int wxWindowDC::GetDepth() const return -1; } +//----------------------------------------------------------------------------- +// wxClientDC +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC) + +wxClientDC::wxClientDC( wxWindow *window ) + : wxWindowDC( window ) +{ + wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") ); + + m_window = (WXWindow*) window->GetClientAreaWindow(); + + // Adjust the client area when the wxWindow is not using 2 X11 windows. + if (m_window == (WXWindow*) window->GetMainWindow()) + { + wxPoint ptOrigin = window->GetClientAreaOrigin(); + SetDeviceOrigin(ptOrigin.x, ptOrigin.y); + wxSize size = window->GetClientSize(); + SetClippingRegion(wxPoint(0, 0), size); + } +} + +void wxClientDC::DoGetSize(int *width, int *height) const +{ + wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") ); + + m_owner->GetClientSize( width, height ); +} + // ---------------------------------------------------------------------------- // wxPaintDC // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC) -wxPaintDC::wxPaintDC(wxWindow* win) - : wxClientDC(win) +wxPaintDC::wxPaintDC(wxWindow* window) + : wxClientDC(window) { #if USE_PAINT_REGION - if (!win->GetClipPaintRegion()) + if (!window->GetClipPaintRegion()) return; - m_paintClippingRegion = win->GetUpdateRegion(); + m_paintClippingRegion = window->GetUpdateRegion(); Region region = (Region) m_paintClippingRegion.GetX11Region(); if (region) { - m_paintClippingRegion = win->GetUpdateRegion(); - Region region2 = (Region) m_paintClippingRegion.GetX11Region(); - if (region2) - { m_currentClippingRegion.Union( m_paintClippingRegion ); - XSetRegion( (Display*) m_display, (GC) m_penGC, region2 ); - XSetRegion( (Display*) m_display, (GC) m_brushGC, region2 ); - XSetRegion( (Display*) m_display, (GC) m_textGC, region2 ); - XSetRegion( (Display*) m_display, (GC) m_bgGC, region2 ); - } + 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 } -//----------------------------------------------------------------------------- -// wxClientDC -//----------------------------------------------------------------------------- - -IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC) - -wxClientDC::wxClientDC( wxWindow *win ) - : wxWindowDC( win ) -{ - wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") ); - -#ifdef __WXUNIVERSAL__ - wxPoint ptOrigin = win->GetClientAreaOrigin(); - SetDeviceOrigin(ptOrigin.x, ptOrigin.y); - wxSize size = win->GetClientSize(); - SetClippingRegion(wxPoint(0, 0), size); -#endif // __WXUNIVERSAL__ -} - -void wxClientDC::DoGetSize(int *width, int *height) const -{ - wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") ); - - m_owner->GetClientSize( width, height ); -} - // ---------------------------------------------------------------------------- // wxDCModule // ----------------------------------------------------------------------------