// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "dcclient.h"
#endif
#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 <math.h>
+#if wxUSE_UNICODE
+#include "glib.h"
+#include "pango/pangox.h"
+#include "pango/pangoxft.h"
+
+#include "pango_x.cpp"
+#endif
+
//-----------------------------------------------------------------------------
// local defines
//-----------------------------------------------------------------------------
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 )
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 );
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() );
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;
}
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);
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 )
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
{
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
{
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
use_bitmap = image.ConvertToMonoBitmap(255,255,255);
else
#endif
- use_bitmap = image.ConvertToBitmap();
+ use_bitmap = image;
}
else
{
XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
// scale image
- wxImage image( bitmap );
+ wxImage image( bitmap.ConvertToImage() );
image = image.Scale( ww, hh );
// convert to bitmap
- bitmap = image.ConvertToBitmap();
+ bitmap = image;
// draw scaled bitmap
XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window,
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 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 );
+
+ 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))
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 );
CalcBoundingBox (x + width, y + height);
CalcBoundingBox (x, y);
#endif
+#endif
}
void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
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 );
*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 );
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 );
XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
return (wxCoord)((ascent+descent) / m_scaleY);
+#endif
}
void wxWindowDC::Clear()
void wxWindowDC::SetFont( const wxFont &font )
{
- wxCHECK_RET( Ok(), "invalid dc" );
+ wxCHECK_RET( Ok(), wxT("invalid dc") );
m_font = font;
}
void wxWindowDC::SetLogicalFunction( int function )
{
- wxCHECK_RET( Ok(), "invalid dc" );
+ wxCHECK_RET( Ok(), wxT("invalid dc") );
int x_function;
m_window = (WXWindow*) window->GetClientAreaWindow();
- // Adjust the client area when the wxWindow is not using 2 X windows.
+ // Adjust the client area when the wxWindow is not using 2 X11 windows.
if (m_window == (WXWindow*) window->GetMainWindow())
{
wxPoint ptOrigin = window->GetClientAreaOrigin();