X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a1fffa9fd5792a2d45b03330909f3698b28ca51f..66b6b04535cf261b7bae7da77332835b242abd04:/src/gtk1/dcclient.cpp diff --git a/src/gtk1/dcclient.cpp b/src/gtk1/dcclient.cpp index cdd1f13950..383dc186bd 100644 --- a/src/gtk1/dcclient.cpp +++ b/src/gtk1/dcclient.cpp @@ -15,10 +15,10 @@ #include "wx/dcmemory.h" #include "wx/image.h" #include "wx/gtk/win_gtk.h" -#include // for floating-point functions -#include "gdk/gdk.h" -#include "gtk/gtk.h" +#include // for floating-point functions +#include +#include //----------------------------------------------------------------------------- // local data @@ -39,7 +39,16 @@ static GdkPixmap **hatch_bitmap = (GdkPixmap **) NULL; // constants //----------------------------------------------------------------------------- -#define RAD2DEG 57.2957795131 +const double RAD2DEG = 180.0 / M_PI; + +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +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; } + +static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } //----------------------------------------------------------------------------- // temporary implementation of the missing GDK function @@ -119,8 +128,8 @@ wxWindowDC::wxWindowDC( wxWindow *window ) wxASSERT_MSG( widget, wxT("DC needs a widget") ); - GtkMyFixed *myfixed = GTK_MYFIXED( widget ); - m_window = myfixed->bin_window; + GtkPizza *pizza = GTK_PIZZA( widget ); + m_window = pizza->bin_window; /* not realized ? */ if (!m_window) @@ -153,19 +162,19 @@ wxWindowDC::~wxWindowDC() Destroy(); } -void wxWindowDC::DoFloodFill( long WXUNUSED(x), long WXUNUSED(y), +void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxColour &WXUNUSED(col), int WXUNUSED(style) ) { wxFAIL_MSG( wxT("wxWindowDC::DoFloodFill not implemented") ); } -bool wxWindowDC::DoGetPixel( long WXUNUSED(x1), long WXUNUSED(y1), wxColour *WXUNUSED(col) ) const +bool wxWindowDC::DoGetPixel( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1), wxColour *WXUNUSED(col) ) const { wxFAIL_MSG( wxT("wxWindowDC::DoGetPixel not implemented") ); return FALSE; } -void wxWindowDC::DoDrawLine( long x1, long y1, long x2, long y2 ) +void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); @@ -179,7 +188,7 @@ void wxWindowDC::DoDrawLine( long x1, long y1, long x2, long y2 ) } } -void wxWindowDC::DoCrossHair( long x, long y ) +void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); @@ -188,8 +197,8 @@ void wxWindowDC::DoCrossHair( long x, long y ) int w = 0; int h = 0; GetSize( &w, &h ); - long xx = XLOG2DEV(x); - long yy = YLOG2DEV(y); + wxCoord xx = XLOG2DEV(x); + wxCoord yy = YLOG2DEV(y); if (m_window) { gdk_draw_line( m_window, m_penGC, 0, yy, XLOG2DEVREL(w), yy ); @@ -198,21 +207,21 @@ void wxWindowDC::DoCrossHair( long x, long y ) } } -void wxWindowDC::DoDrawArc( long x1, long y1, long x2, long y2, - long xc, long yc ) +void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, + wxCoord xc, wxCoord yc ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); - long xx1 = XLOG2DEV(x1); - long yy1 = YLOG2DEV(y1); - long xx2 = XLOG2DEV(x2); - long yy2 = YLOG2DEV(y2); - long xxc = XLOG2DEV(xc); - long yyc = YLOG2DEV(yc); + 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)); - long r = (long)radius; + wxCoord r = (wxCoord)radius; double radius1, radius2; if (xx1 == xx2 && yy1 == yy2) @@ -234,8 +243,8 @@ void wxWindowDC::DoDrawArc( long x1, long y1, long x2, long y2, (yy2 - yyc < 0) ? 90.0 : -90.0 : -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG; } - long alpha1 = long(radius1 * 64.0); - long alpha2 = long((radius2 - radius1) * 64.0); + 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; @@ -252,14 +261,14 @@ void wxWindowDC::DoDrawArc( long x1, long y1, long x2, long y2, CalcBoundingBox (x2, y2); } -void wxWindowDC::DoDrawEllipticArc( long x, long y, long width, long height, double sa, double ea ) +void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); - long xx = XLOG2DEV(x); - long yy = YLOG2DEV(y); - long ww = m_signX * XLOG2DEVREL(width); - long hh = m_signY * YLOG2DEVREL(height); + 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; } @@ -267,8 +276,8 @@ void wxWindowDC::DoDrawEllipticArc( long x, long y, long width, long height, dou if (m_window) { - long start = long(sa * 64.0); - long end = long(ea * 64.0); + wxCoord start = wxCoord(sa * 64.0); + wxCoord end = wxCoord(ea * 64.0); if (m_brush.GetStyle() != wxTRANSPARENT) gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, start, end ); @@ -281,7 +290,7 @@ void wxWindowDC::DoDrawEllipticArc( long x, long y, long width, long height, dou CalcBoundingBox (x + width, y + height); } -void wxWindowDC::DoDrawPoint( long x, long y ) +void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); @@ -291,7 +300,7 @@ void wxWindowDC::DoDrawPoint( long x, long y ) CalcBoundingBox (x, y); } -void wxWindowDC::DoDrawLines( int n, wxPoint points[], long xoffset, long yoffset ) +void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); @@ -302,10 +311,10 @@ void wxWindowDC::DoDrawLines( int n, wxPoint points[], long xoffset, long yoffse for (int i = 0; i < n-1; i++) { - long x1 = XLOG2DEV(points[i].x + xoffset); - long x2 = XLOG2DEV(points[i+1].x + xoffset); - long y1 = YLOG2DEV(points[i].y + yoffset); // oh, what a waste - long y2 = YLOG2DEV(points[i+1].y + yoffset); + wxCoord x1 = XLOG2DEV(points[i].x + xoffset); + wxCoord x2 = XLOG2DEV(points[i+1].x + xoffset); + wxCoord y1 = YLOG2DEV(points[i].y + yoffset); // oh, what a waste + wxCoord y2 = YLOG2DEV(points[i+1].y + yoffset); if (m_window) gdk_draw_line( m_window, m_penGC, x1, y1, x2, y2 ); @@ -314,7 +323,7 @@ void wxWindowDC::DoDrawLines( int n, wxPoint points[], long xoffset, long yoffse } } -void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], long xoffset, long yoffset, int WXUNUSED(fillStyle) ) +void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int WXUNUSED(fillStyle) ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); @@ -330,8 +339,16 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], long xoffset, long yoff CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset ); } - if ((m_brush.GetStyle() != wxTRANSPARENT) && m_window) - gdk_draw_polygon (m_window, m_brushGC, TRUE, gdkpoints, n); + if (m_window) + { + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + gdk_draw_polygon (m_window, m_textGC, TRUE, gdkpoints, n); + else + { + if ((m_brush.GetStyle() != wxTRANSPARENT)) + gdk_draw_polygon (m_window, m_brushGC, TRUE, gdkpoints, n); + } + } // To do: Fillstyle @@ -350,14 +367,14 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], long xoffset, long yoff delete[] gdkpoints; } -void wxWindowDC::DoDrawRectangle( long x, long y, long width, long height ) +void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); - long xx = XLOG2DEV(x); - long yy = YLOG2DEV(y); - long ww = m_signX * XLOG2DEVREL(width); - long hh = m_signY * YLOG2DEVREL(height); + wxCoord xx = XLOG2DEV(x); + wxCoord yy = YLOG2DEV(y); + wxCoord ww = m_signX * XLOG2DEVREL(width); + wxCoord hh = m_signY * YLOG2DEVREL(height); // CMB: draw nothing if transformed w or h is 0 if (ww == 0 || hh == 0) return; @@ -368,28 +385,36 @@ void wxWindowDC::DoDrawRectangle( long x, long y, long width, long height ) if (m_window) { - if (m_brush.GetStyle() != wxTRANSPARENT) - gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy, ww, hh ); - - if (m_pen.GetStyle() != wxTRANSPARENT) - gdk_draw_rectangle( m_window, m_penGC, FALSE, xx, yy, ww-1, hh-1 ); + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + { + gdk_draw_rectangle( m_window, m_textGC, TRUE, xx, yy, ww, hh ); + gdk_draw_rectangle( m_window, m_penGC, FALSE, xx, yy, ww-1, hh-1 ); + } + else + { + if (m_brush.GetStyle() != wxTRANSPARENT) + gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy, ww, hh ); + + if (m_pen.GetStyle() != wxTRANSPARENT) + gdk_draw_rectangle( m_window, m_penGC, FALSE, xx, yy, ww-1, hh-1 ); + } } CalcBoundingBox( x, y ); CalcBoundingBox( x + width, y + height ); } -void wxWindowDC::DoDrawRoundedRectangle( long x, long y, long width, long height, double radius ) +void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); if (radius < 0.0) radius = - radius * ((width < height) ? width : height); - long xx = XLOG2DEV(x); - long yy = YLOG2DEV(y); - long ww = m_signX * XLOG2DEVREL(width); - long hh = m_signY * YLOG2DEVREL(height); - long rr = XLOG2DEVREL((long)radius); + 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; } @@ -418,7 +443,7 @@ void wxWindowDC::DoDrawRoundedRectangle( long x, long y, long width, long height { // CMB: ensure dd is not larger than rectangle otherwise we // get an hour glass shape - long dd = 2 * rr; + wxCoord dd = 2 * rr; if (dd > ww) dd = ww; if (dd > hh) dd = hh; rr = dd / 2; @@ -451,14 +476,14 @@ void wxWindowDC::DoDrawRoundedRectangle( long x, long y, long width, long height CalcBoundingBox( x + width, y + height ); } -void wxWindowDC::DoDrawEllipse( long x, long y, long width, long height ) +void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); - long xx = XLOG2DEV(x); - long yy = YLOG2DEV(y); - long ww = m_signX * XLOG2DEVREL(width); - long hh = m_signY * YLOG2DEVREL(height); + 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; } @@ -477,20 +502,22 @@ void wxWindowDC::DoDrawEllipse( long x, long y, long width, long height ) CalcBoundingBox( x + width, y + height ); } -void wxWindowDC::DoDrawIcon( const wxIcon &icon, long x, long y ) +void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y ) { // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why DoDrawBitmap( (const wxBitmap&)icon, x, y, (bool)TRUE ); } void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, - long x, long y, + 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); @@ -514,9 +541,11 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, if ((w != ww) || (h != hh)) { wxImage image( bitmap ); - image = image.Scale( ww, hh ); - - use_bitmap = image.ConvertToBitmap(); + image.Rescale( ww, hh ); + if (is_mono) + use_bitmap = image.ConvertToMonoBitmap(255,255,255); + else + use_bitmap = image.ConvertToBitmap(); } else { @@ -530,37 +559,44 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, if (useMask && mask) { - gdk_gc_set_clip_mask( m_penGC, mask ); - gdk_gc_set_clip_origin( m_penGC, xx, yy ); - } - - /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */ - - GdkPixmap *pm = use_bitmap.GetPixmap(); - if (pm) - { - gdk_draw_pixmap( m_window, m_penGC, pm, 0, 0, xx, yy, -1, -1 ); - } - else - { - GdkBitmap *bm = use_bitmap.GetBitmap(); - if (bm) + if (is_mono) + { + gdk_gc_set_clip_mask( m_textGC, mask ); + gdk_gc_set_clip_origin( m_textGC, xx, yy ); + } + else { - gdk_draw_bitmap( m_window, m_penGC, bm, 0, 0, xx, yy, -1, -1 ); + gdk_gc_set_clip_mask( m_penGC, mask ); + gdk_gc_set_clip_origin( m_penGC, xx, yy ); } } + /* 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_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), 0, 0, xx, yy, -1, -1 ); + else + gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); + /* remove mask again if any */ if (useMask && mask) { - gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_penGC, 0, 0 ); + if (is_mono) + { + gdk_gc_set_clip_mask( m_textGC, (GdkBitmap *) NULL ); + gdk_gc_set_clip_origin( m_textGC, 0, 0 ); + } + else + { + gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); + gdk_gc_set_clip_origin( m_penGC, 0, 0 ); + } } } -bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height, - wxDC *source, long xsrc, long ysrc, +bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, + wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask ) { /* this is the nth try to get this utterly useless function to @@ -578,6 +614,7 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height, wxMemoryDC *memDC = (wxMemoryDC*)source; bool use_bitmap_method = FALSE; + bool is_mono = FALSE; if (srcDC->m_isMemDC) { @@ -601,6 +638,7 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height, /* 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) && @@ -629,11 +667,11 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height, { /* scale/translate bitmap size */ - long bm_width = memDC->m_selected.GetWidth(); - long bm_height = memDC->m_selected.GetHeight(); + wxCoord bm_width = memDC->m_selected.GetWidth(); + wxCoord bm_height = memDC->m_selected.GetHeight(); - long bm_ww = XLOG2DEVREL( bm_width ); - long bm_hh = YLOG2DEVREL( bm_height ); + wxCoord bm_ww = XLOG2DEVREL( bm_width ); + wxCoord bm_hh = YLOG2DEVREL( bm_height ); /* scale bitmap if required */ @@ -644,7 +682,10 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height, wxImage image( memDC->m_selected ); image = image.Scale( bm_ww, bm_hh ); - use_bitmap = image.ConvertToBitmap(); + if (is_mono) + use_bitmap = image.ConvertToMonoBitmap(255,255,255); + else + use_bitmap = image.ConvertToBitmap(); } else { @@ -653,11 +694,11 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height, /* scale/translate size and position */ - long xx = XLOG2DEV(xdest); - long yy = YLOG2DEV(ydest); + wxCoord xx = XLOG2DEV(xdest); + wxCoord yy = YLOG2DEV(ydest); - long ww = XLOG2DEVREL(width); - long hh = YLOG2DEVREL(height); + wxCoord ww = XLOG2DEVREL(width); + wxCoord hh = YLOG2DEVREL(height); /* apply mask if any */ @@ -666,45 +707,50 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height, if (useMask && mask) { - gdk_gc_set_clip_mask( m_penGC, mask ); - gdk_gc_set_clip_origin( m_penGC, xx, yy ); - } - - /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */ - - GdkPixmap *pm = use_bitmap.GetPixmap(); - if (pm) - { - gdk_draw_pixmap( m_window, m_penGC, pm, xsrc, ysrc, xx, yy, ww, hh ); - } - else - { - GdkBitmap *bm = use_bitmap.GetBitmap(); - if (bm) + if (is_mono) + { + gdk_gc_set_clip_mask( m_textGC, mask ); + gdk_gc_set_clip_origin( m_textGC, xx, yy ); + } + else { - /* we use the textGC here because blitting a bitmap is done - using the current text colour */ - gdk_draw_bitmap( m_window, m_textGC, bm, xsrc, ysrc, xx, yy, ww, hh ); + gdk_gc_set_clip_mask( m_penGC, mask ); + gdk_gc_set_clip_origin( m_penGC, xx, yy ); } } + /* 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_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh ); + else + gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh ); + /* remove mask again if any */ if (useMask && mask) { - gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_penGC, 0, 0 ); + if (is_mono) + { + gdk_gc_set_clip_mask( m_textGC, (GdkBitmap *) NULL ); + gdk_gc_set_clip_origin( m_textGC, 0, 0 ); + } + else + { + gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); + gdk_gc_set_clip_origin( m_penGC, 0, 0 ); + } } } else /* use_bitmap_method */ { /* scale/translate size and position */ - long xx = XLOG2DEV(xdest); - long yy = YLOG2DEV(ydest); + wxCoord xx = XLOG2DEV(xdest); + wxCoord yy = YLOG2DEV(ydest); - long ww = XLOG2DEVREL(width); - long hh = YLOG2DEVREL(height); + wxCoord ww = XLOG2DEVREL(width); + wxCoord hh = YLOG2DEVREL(height); if ((width != ww) || (height != hh)) { @@ -754,7 +800,7 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height, return TRUE; } -void wxWindowDC::DoDrawText( const wxString &text, long x, long y ) +void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) { wxCHECK_RET( Ok(), wxT("invalid window dc") ); @@ -770,8 +816,8 @@ void wxWindowDC::DoDrawText( const wxString &text, long x, long y ) /* CMB 21/5/98: draw text background if mode is wxSOLID */ if (m_backgroundMode == wxSOLID) { - long width = gdk_string_width( font, text.mbc_str() ); - long height = font->ascent + font->descent; + wxCoord width = gdk_string_width( font, text.mbc_str() ); + wxCoord height = font->ascent + font->descent; gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() ); gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height ); gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() ); @@ -783,42 +829,160 @@ void wxWindowDC::DoDrawText( const wxString &text, long x, long y ) properties (see wxXt implementation) */ if (m_font.GetUnderlined()) { - long width = gdk_string_width( font, text.mbc_str() ); - long ul_y = y + font->ascent; + wxCoord width = gdk_string_width( font, text.mbc_str() ); + wxCoord ul_y = y + font->ascent; if (font->descent > 0) ul_y++; gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y); } - long w, h; + wxCoord w, h; GetTextExtent (text, &w, &h); CalcBoundingBox (x + w, y + h); CalcBoundingBox (x, y); } -void wxWindowDC::GetTextExtent( const wxString &string, long *width, long *height, - long *descent, long *externalLeading, - wxFont *theFont ) const +void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle ) +{ + if (angle == 0.0) + { + DrawText(text, x, y); + return; + } + + wxCHECK_RET( Ok(), wxT("invalid window dc") ); + + if (!m_window) return; + + GdkFont *font = m_font.GetInternalFont( m_scaleY ); + + wxCHECK_RET( font, wxT("invalid font") ); + + // the size of the text + wxCoord w = gdk_string_width( font, text.mbc_str() ); + wxCoord h = font->ascent + font->descent; + + // draw the string normally + wxBitmap src(w, h); + 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); + dc.SelectObject(wxNullBitmap); + + // Calculate the size of the rotated bounding box. + double rad = DegToRad(angle); + double dx = cos(rad), + dy = sin(rad); + + // the rectngle vertices are counted clockwise with the first one being at + // (0, 0) (or, rather, at (x, y)) + double x2 = w*dx, + y2 = -w*dy; // y axis points to the bottom, hence minus + double x4 = h*dy, + y4 = h*dx; + double x3 = x4 + x2, + y3 = y4 + y2; + + // calc max and min + wxCoord maxX = (wxCoord)(dmax(x2, dmax(x3, x4)) + 0.5), + maxY = (wxCoord)(dmax(y2, dmax(y3, y4)) + 0.5), + minX = (wxCoord)(dmin(x2, dmin(x3, x4)) - 0.5), + minY = (wxCoord)(dmin(y2, dmin(y3, y4)) - 0.5); + + // prepare to blit-with-rotate the bitmap to the DC + wxImage image(src); + + GdkColor *colText = m_textForegroundColour.GetColor(), + *colBack = m_textBackgroundColour.GetColor(); + + bool textColSet = TRUE; + + unsigned char *data = image.GetData(); + + // paint pixel by pixel + for ( wxCoord srcX = 0; srcX < w; srcX++ ) + { + for ( wxCoord srcY = 0; srcY < h; srcY++ ) + { + // transform source coords to dest coords + double r = sqrt(srcX*srcX + srcY*srcY); + double angleOrig = atan2(srcY, srcX) - rad; + wxCoord dstX = (wxCoord)(r*cos(angleOrig) + 0.5), + dstY = (wxCoord)(r*sin(angleOrig) + 0.5); + + // black pixel? + bool textPixel = data[(srcY*w + srcX)*3] == 0; + if ( textPixel || (m_backgroundMode == wxSOLID) ) + { + // change colour if needed + if ( textPixel != textColSet ) + { + gdk_gc_set_foreground( m_textGC, textPixel ? colText + : colBack ); + + textColSet = textPixel; + } + + // don't use DrawPoint() because it uses the current pen + // colour, and we don't need it here + gdk_draw_point( m_window, m_textGC, + XLOG2DEV(x + dstX), YLOG2DEV(y + dstY) ); + } + } + } + + // it would be better to draw with non underlined font and draw the line + // manually here (it would be more straight...) +#if 0 + if ( m_font.GetUnderlined() ) + { + gdk_draw_line( m_window, m_textGC, + XLOG2DEV(x + x4), YLOG2DEV(y + y4 + font->descent), + XLOG2DEV(x + x3), YLOG2DEV(y + y3 + font->descent)); + } +#endif // 0 + + // restore the font colour + gdk_gc_set_foreground( m_textGC, colText ); + + // update the bounding box + CalcBoundingBox(x + minX, y + minY); + CalcBoundingBox(x + maxX, y + maxY); +} + +void wxWindowDC::DoGetTextExtent(const wxString &string, + wxCoord *width, wxCoord *height, + wxCoord *descent, wxCoord *externalLeading, + wxFont *theFont) const { wxFont fontToUse = m_font; if (theFont) fontToUse = *theFont; GdkFont *font = fontToUse.GetInternalFont( m_scaleY ); - if (width) (*width) = long(gdk_string_width( font, string.mbc_str() ) / m_scaleX); - if (height) (*height) = long((font->ascent + font->descent) / m_scaleY); - if (descent) (*descent) = long(font->descent / m_scaleY); + if (width) (*width) = wxCoord(gdk_string_width( font, string.mbc_str() ) / m_scaleX); + if (height) (*height) = wxCoord((font->ascent + font->descent) / m_scaleY); + if (descent) (*descent) = wxCoord(font->descent / m_scaleY); if (externalLeading) (*externalLeading) = 0; // ?? } -long wxWindowDC::GetCharWidth() const +wxCoord wxWindowDC::GetCharWidth() const { GdkFont *font = m_font.GetInternalFont( m_scaleY ); - return long(gdk_string_width( font, "H" ) / m_scaleX); + wxCHECK_MSG( font, -1, wxT("invalid font") ); + + return wxCoord(gdk_string_width( font, "H" ) / m_scaleX); } -long wxWindowDC::GetCharHeight() const +wxCoord wxWindowDC::GetCharHeight() const { GdkFont *font = m_font.GetInternalFont( m_scaleY ); - return long((font->ascent + font->descent) / m_scaleY); + wxCHECK_MSG( font, -1, wxT("invalid font") ); + + return wxCoord((font->ascent + font->descent) / m_scaleY); } void wxWindowDC::Clear() @@ -886,7 +1050,7 @@ void wxWindowDC::SetPen( const wxPen &pen ) static const char dotted[] = {1, 1}; static const char short_dashed[] = {2, 2}; - static const char long_dashed[] = {2, 4}; + static const char wxCoord_dashed[] = {2, 4}; static const char dotted_dashed[] = {3, 3, 1, 3}; // We express dash pattern in pen width unit, so we are @@ -915,7 +1079,7 @@ void wxWindowDC::SetPen( const wxPen &pen ) { lineStyle = GDK_LINE_ON_OFF_DASH; req_nb_dash = 2; - req_dash = long_dashed; + req_dash = wxCoord_dashed; break; } case wxSHORT_DASH: @@ -935,6 +1099,7 @@ void wxWindowDC::SetPen( const wxPen &pen ) } case wxTRANSPARENT: + case wxSTIPPLE_MASK_OPAQUE: case wxSTIPPLE: case wxSOLID: default: @@ -1018,6 +1183,12 @@ void wxWindowDC::SetBrush( const wxBrush &brush ) } } + if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) + { + gdk_gc_set_fill( m_textGC, GDK_OPAQUE_STIPPLED); + gdk_gc_set_stipple( m_textGC, m_brush.GetStipple()->GetMask()->GetBitmap() ); + } + if (IS_HATCH(m_brush.GetStyle())) { gdk_gc_set_fill( m_brushGC, GDK_STIPPLED ); @@ -1168,7 +1339,7 @@ void wxWindowDC::SetPalette( const wxPalette& WXUNUSED(palette) ) wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") ); } -void wxWindowDC::DoSetClippingRegion( long x, long y, long width, long height ) +void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) { wxCHECK_RET( Ok(), wxT("invalid window dc") );