X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b610cc76ee60b50d89f21cacb1bbfe3e90b2c235..12b5f4b4d2d8a07962da7ba3b78c8c1ec2634a67:/src/common/dcbase.cpp?ds=sidebyside diff --git a/src/common/dcbase.cpp b/src/common/dcbase.cpp index 3156558ff1..224cf624a1 100644 --- a/src/common/dcbase.cpp +++ b/src/common/dcbase.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: common/dcbase.cpp +// Name: src/common/dcbase.cpp // Purpose: generic methods of the wxDC Class // Author: Vadim Zeitlin // Modified by: @@ -13,10 +13,6 @@ // declarations // ============================================================================ -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "dcbase.h" -#endif - // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- @@ -29,27 +25,614 @@ #endif #include "wx/dc.h" +#include "wx/dcclient.h" +#include "wx/dcmemory.h" +#include "wx/dcscreen.h" +#include "wx/dcprint.h" +#include "wx/prntbase.h" + +#ifndef WX_PRECOMP + #include "wx/math.h" + #include "wx/module.h" +#endif + +#ifdef __WXMSW__ + #include "wx/msw/dcclient.h" + #include "wx/msw/dcmemory.h" + #include "wx/msw/dcscreen.h" +#endif -// bool wxDCBase::sm_cacheing = false; +#ifdef __WXGTK20__ + #include "wx/gtk/dcclient.h" + #include "wx/gtk/dcmemory.h" + #include "wx/gtk/dcscreen.h" +#elif defined(__WXGTK__) + #include "wx/gtk1/dcclient.h" + #include "wx/gtk1/dcmemory.h" + #include "wx/gtk1/dcscreen.h" +#endif -// ============================================================================ -// implementation -// ============================================================================ +#ifdef __WXMAC__ + #include "wx/osx/dcclient.h" + #include "wx/osx/dcmemory.h" + #include "wx/osx/dcscreen.h" +#endif + +#ifdef __WXPM__ + #include "wx/os2/dcclient.h" + #include "wx/os2/dcmemory.h" + #include "wx/os2/dcscreen.h" +#endif + +#ifdef __WXCOCOA__ + #include "wx/cocoa/dcclient.h" + #include "wx/cocoa/dcmemory.h" + #include "wx/cocoa/dcscreen.h" +#endif + +#ifdef __WXMOTIF__ + #include "wx/motif/dcclient.h" + #include "wx/motif/dcmemory.h" + #include "wx/motif/dcscreen.h" +#endif + +#ifdef __WXX11__ + #include "wx/x11/dcclient.h" + #include "wx/x11/dcmemory.h" + #include "wx/x11/dcscreen.h" +#endif + +#ifdef __WXDFB__ + #include "wx/dfb/dcclient.h" + #include "wx/dfb/dcmemory.h" + #include "wx/dfb/dcscreen.h" +#endif + +#ifdef __WXPALMOS__ + #include "wx/palmos/dcclient.h" + #include "wx/palmos/dcmemory.h" + #include "wx/palmos/dcscreen.h" +#endif + +//---------------------------------------------------------------------------- +// wxDCFactory +//---------------------------------------------------------------------------- + +wxDCFactory *wxDCFactory::m_factory = NULL; + +void wxDCFactory::Set(wxDCFactory *factory) +{ + delete m_factory; + + m_factory = factory; +} + +wxDCFactory *wxDCFactory::Get() +{ + if ( !m_factory ) + m_factory = new wxNativeDCFactory; + + return m_factory; +} + +class wxDCFactoryCleanupModule : public wxModule +{ +public: + virtual bool OnInit() { return true; } + virtual void OnExit() { wxDCFactory::Set(NULL); } + +private: + DECLARE_DYNAMIC_CLASS(wxDCFactoryCleanupModule) +}; + +IMPLEMENT_DYNAMIC_CLASS(wxDCFactoryCleanupModule, wxModule) + +//----------------------------------------------------------------------------- +// wxNativeDCFactory +//----------------------------------------------------------------------------- + +wxDCImpl* wxNativeDCFactory::CreateWindowDC( wxWindowDC *owner, wxWindow *window ) +{ + wxDCImpl * const impl = new wxWindowDCImpl( owner, window ); + impl->InheritAttributes(window); + return impl; +} + +wxDCImpl* wxNativeDCFactory::CreateClientDC( wxClientDC *owner, wxWindow *window ) +{ + wxDCImpl * const impl = new wxClientDCImpl( owner, window ); + impl->InheritAttributes(window); + return impl; +} + +wxDCImpl* wxNativeDCFactory::CreatePaintDC( wxPaintDC *owner, wxWindow *window ) +{ + wxDCImpl * const impl = new wxPaintDCImpl( owner, window ); + impl->InheritAttributes(window); + return impl; +} + +wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner ) +{ + return new wxMemoryDCImpl( owner ); +} + +wxDCImpl* wxNativeDCFactory::CreateMemoryDC(wxMemoryDC *owner, wxBitmap& bitmap) +{ + // the bitmap may be modified when it's selected into a memory DC so make + // sure changing this bitmap doesn't affect any other shallow copies of it + // (see wxMemoryDC::SelectObject()) + // + // notice that we don't provide any ctor equivalent to SelectObjectAsSource + // method because this should be rarely needed and easy to work around by + // using the default ctor and calling SelectObjectAsSource itself + if ( bitmap.IsOk() ) + bitmap.UnShare(); + + return new wxMemoryDCImpl(owner, bitmap); +} + +wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner, wxDC *dc ) +{ + return new wxMemoryDCImpl( owner, dc ); +} + +wxDCImpl* wxNativeDCFactory::CreateScreenDC( wxScreenDC *owner ) +{ + return new wxScreenDCImpl( owner ); +} + +#if wxUSE_PRINTING_ARCHITECTURE +wxDCImpl *wxNativeDCFactory::CreatePrinterDC( wxPrinterDC *owner, const wxPrintData &data ) +{ + wxPrintFactory *factory = wxPrintFactory::GetFactory(); + return factory->CreatePrinterDCImpl( owner, data ); +} +#endif + +//----------------------------------------------------------------------------- +// wxWindowDC +//----------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxWindowDC, wxDC) + +wxWindowDC::wxWindowDC(wxWindow *win) + : wxDC(wxDCFactory::Get()->CreateWindowDC(this, win)) +{ +} + +//----------------------------------------------------------------------------- +// wxClientDC +//----------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxClientDC, wxWindowDC) + +wxClientDC::wxClientDC(wxWindow *win) + : wxWindowDC(wxDCFactory::Get()->CreateClientDC(this, win)) +{ +} + +//----------------------------------------------------------------------------- +// wxMemoryDC +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC, wxDC) + +wxMemoryDC::wxMemoryDC() + : wxDC(wxDCFactory::Get()->CreateMemoryDC(this)) +{ +} + +wxMemoryDC::wxMemoryDC(wxBitmap& bitmap) + : wxDC(wxDCFactory::Get()->CreateMemoryDC(this, bitmap)) +{ +} + +wxMemoryDC::wxMemoryDC(wxDC *dc) + : wxDC(wxDCFactory::Get()->CreateMemoryDC(this, dc)) +{ +} + +void wxMemoryDC::SelectObject(wxBitmap& bmp) +{ + // make sure that the given wxBitmap is not sharing its data with other + // wxBitmap instances as its contents will be modified by any drawing + // operation done on this DC + if (bmp.IsOk()) + bmp.UnShare(); + + GetImpl()->DoSelect(bmp); +} + +void wxMemoryDC::SelectObjectAsSource(const wxBitmap& bmp) +{ + GetImpl()->DoSelect(bmp); +} + +const wxBitmap& wxMemoryDC::GetSelectedBitmap() const +{ + return GetImpl()->GetSelectedBitmap(); +} + +wxBitmap& wxMemoryDC::GetSelectedBitmap() +{ + return GetImpl()->GetSelectedBitmap(); +} + + +//----------------------------------------------------------------------------- +// wxPaintDC +//----------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxPaintDC, wxClientDC) + +wxPaintDC::wxPaintDC(wxWindow *win) + : wxClientDC(wxDCFactory::Get()->CreatePaintDC(this, win)) +{ +} + +//----------------------------------------------------------------------------- +// wxScreenDC +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxScreenDC, wxWindowDC) + +wxScreenDC::wxScreenDC() + : wxDC(wxDCFactory::Get()->CreateScreenDC(this)) +{ +} + +//----------------------------------------------------------------------------- +// wxPrinterDC +//----------------------------------------------------------------------------- + +#if wxUSE_PRINTING_ARCHITECTURE + +IMPLEMENT_DYNAMIC_CLASS(wxPrinterDC, wxDC) + +wxPrinterDC::wxPrinterDC() + : wxDC(wxDCFactory::Get()->CreatePrinterDC(this, wxPrintData())) +{ +} + +wxPrinterDC::wxPrinterDC(const wxPrintData& data) + : wxDC(wxDCFactory::Get()->CreatePrinterDC(this, data)) +{ +} + +wxRect wxPrinterDC::GetPaperRect() const +{ + return GetImpl()->GetPaperRect(); +} + +int wxPrinterDC::GetResolution() const +{ + return GetImpl()->GetResolution(); +} + +#endif // wxUSE_PRINTING_ARCHITECTURE + +//----------------------------------------------------------------------------- +// wxDCImpl +//----------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxDCImpl, wxObject) + +wxDCImpl::wxDCImpl( wxDC *owner ) + : m_window(NULL) + , m_colour(wxColourDisplay()) + , m_ok(true) + , m_clipping(false) + , m_isInteractive(0) + , m_isBBoxValid(false) + , m_logicalOriginX(0), m_logicalOriginY(0) + , m_deviceOriginX(0), m_deviceOriginY(0) + , m_deviceLocalOriginX(0), m_deviceLocalOriginY(0) + , m_logicalScaleX(1.0), m_logicalScaleY(1.0) + , m_userScaleX(1.0), m_userScaleY(1.0) + , m_scaleX(1.0), m_scaleY(1.0) + , m_signX(1), m_signY(1) + , m_minX(0), m_minY(0), m_maxX(0), m_maxY(0) + , m_clipX1(0), m_clipY1(0), m_clipX2(0), m_clipY2(0) + , m_logicalFunction(wxCOPY) + , m_backgroundMode(wxBRUSHSTYLE_TRANSPARENT) + , m_mappingMode(wxMM_TEXT) + , m_pen() + , m_brush() + , m_backgroundBrush() + , m_textForegroundColour(*wxBLACK) + , m_textBackgroundColour(*wxWHITE) + , m_font() +#if wxUSE_PALETTE + , m_palette() + , m_hasCustomPalette(false) +#endif // wxUSE_PALETTE +{ + m_owner = owner; + + m_mm_to_pix_x = (double)wxGetDisplaySize().GetWidth() / + (double)wxGetDisplaySizeMM().GetWidth(); + m_mm_to_pix_y = (double)wxGetDisplaySize().GetHeight() / + (double)wxGetDisplaySizeMM().GetHeight(); + + ResetBoundingBox(); + ResetClipping(); +} + +wxDCImpl::~wxDCImpl() +{ +} // ---------------------------------------------------------------------------- -// special symbols +// coordinate conversions and transforms // ---------------------------------------------------------------------------- -void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1, +wxCoord wxDCImpl::DeviceToLogicalX(wxCoord x) const +{ + return wxRound( (double)((x - m_deviceOriginX - m_deviceLocalOriginX) * m_signX) / m_scaleX ) + m_logicalOriginX ; +} + +wxCoord wxDCImpl::DeviceToLogicalY(wxCoord y) const +{ + return wxRound( (double)((y - m_deviceOriginY - m_deviceLocalOriginY) * m_signY) / m_scaleY ) + m_logicalOriginY ; +} + +wxCoord wxDCImpl::DeviceToLogicalXRel(wxCoord x) const +{ + return wxRound((double)(x) / m_scaleX); +} + +wxCoord wxDCImpl::DeviceToLogicalYRel(wxCoord y) const +{ + return wxRound((double)(y) / m_scaleY); +} + +wxCoord wxDCImpl::LogicalToDeviceX(wxCoord x) const +{ + return wxRound( (double)((x - m_logicalOriginX) * m_signX) * m_scaleX) + m_deviceOriginX + m_deviceLocalOriginX; +} + +wxCoord wxDCImpl::LogicalToDeviceY(wxCoord y) const +{ + return wxRound( (double)((y - m_logicalOriginY) * m_signY) * m_scaleY) + m_deviceOriginY + m_deviceLocalOriginY; +} + +wxCoord wxDCImpl::LogicalToDeviceXRel(wxCoord x) const +{ + return wxRound((double)(x) * m_scaleX); +} + +wxCoord wxDCImpl::LogicalToDeviceYRel(wxCoord y) const +{ + return wxRound((double)(y) * m_scaleY); +} + +void wxDCImpl::ComputeScaleAndOrigin() +{ + m_scaleX = m_logicalScaleX * m_userScaleX; + m_scaleY = m_logicalScaleY * m_userScaleY; +} + +void wxDCImpl::SetMapMode( wxMappingMode mode ) +{ + switch (mode) + { + case wxMM_TWIPS: + SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y ); + break; + case wxMM_POINTS: + SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y ); + break; + case wxMM_METRIC: + SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y ); + break; + case wxMM_LOMETRIC: + SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 ); + break; + default: + case wxMM_TEXT: + SetLogicalScale( 1.0, 1.0 ); + break; + } + m_mappingMode = mode; +} + +void wxDCImpl::SetUserScale( double x, double y ) +{ + // allow negative ? -> no + m_userScaleX = x; + m_userScaleY = y; + ComputeScaleAndOrigin(); +} + +void wxDCImpl::SetLogicalScale( double x, double y ) +{ + // allow negative ? + m_logicalScaleX = x; + m_logicalScaleY = y; + ComputeScaleAndOrigin(); +} + +void wxDCImpl::SetLogicalOrigin( wxCoord x, wxCoord y ) +{ + m_logicalOriginX = x * m_signX; + m_logicalOriginY = y * m_signY; + ComputeScaleAndOrigin(); +} + +void wxDCImpl::SetDeviceOrigin( wxCoord x, wxCoord y ) +{ + m_deviceOriginX = x; + m_deviceOriginY = y; + ComputeScaleAndOrigin(); +} + +void wxDCImpl::SetDeviceLocalOrigin( wxCoord x, wxCoord y ) +{ + m_deviceLocalOriginX = x; + m_deviceLocalOriginY = y; + ComputeScaleAndOrigin(); +} + +void wxDCImpl::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) +{ + // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there + // wxWidgets 2.9: no longer override it + m_signX = (xLeftRight ? 1 : -1); + m_signY = (yBottomUp ? -1 : 1); + ComputeScaleAndOrigin(); +} + + +// Each element of the widths array will be the width of the string up to and +// including the corresponding character in text. This is the generic +// implementation, the port-specific classes should do this with native APIs +// if available and if faster. Note: pango_layout_index_to_pos is much slower +// than calling GetTextExtent!! + +#define FWC_SIZE 256 + +class FontWidthCache +{ +public: + FontWidthCache() : m_scaleX(1), m_widths(NULL) { } + ~FontWidthCache() { delete []m_widths; } + + void Reset() + { + if (!m_widths) + m_widths = new int[FWC_SIZE]; + + memset(m_widths, 0, sizeof(int)*FWC_SIZE); + } + + wxFont m_font; + double m_scaleX; + int *m_widths; +}; + +static FontWidthCache s_fontWidthCache; + +bool wxDCImpl::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const +{ + int totalWidth = 0; + + const size_t len = text.length(); + widths.Empty(); + widths.Add(0, len); + + // reset the cache if font or horizontal scale have changed + if ( !s_fontWidthCache.m_widths || + !wxIsSameDouble(s_fontWidthCache.m_scaleX, m_scaleX) || + (s_fontWidthCache.m_font != GetFont()) ) + { + s_fontWidthCache.Reset(); + s_fontWidthCache.m_font = GetFont(); + s_fontWidthCache.m_scaleX = m_scaleX; + } + + // Calculate the position of each character based on the widths of + // the previous characters + int w, h; + for ( size_t i = 0; i < len; i++ ) + { + const wxChar c = text[i]; + unsigned int c_int = (unsigned int)c; + + if ((c_int < FWC_SIZE) && (s_fontWidthCache.m_widths[c_int] != 0)) + { + w = s_fontWidthCache.m_widths[c_int]; + } + else + { + DoGetTextExtent(c, &w, &h); + if (c_int < FWC_SIZE) + s_fontWidthCache.m_widths[c_int] = w; + } + + totalWidth += w; + widths[i] = totalWidth; + } + + return true; +} + +void wxDCImpl::GetMultiLineTextExtent(const wxString& text, + wxCoord *x, + wxCoord *y, + wxCoord *h, + const wxFont *font) const +{ + wxCoord widthTextMax = 0, widthLine, + heightTextTotal = 0, heightLineDefault = 0, heightLine = 0; + + wxString curLine; + for ( wxString::const_iterator pc = text.begin(); ; ++pc ) + { + if ( pc == text.end() || *pc == _T('\n') ) + { + if ( curLine.empty() ) + { + // we can't use GetTextExtent - it will return 0 for both width + // and height and an empty line should count in height + // calculation + + // assume that this line has the same height as the previous + // one + if ( !heightLineDefault ) + heightLineDefault = heightLine; + + if ( !heightLineDefault ) + { + // but we don't know it yet - choose something reasonable + DoGetTextExtent(_T("W"), NULL, &heightLineDefault, + NULL, NULL, font); + } + + heightTextTotal += heightLineDefault; + } + else + { + DoGetTextExtent(curLine, &widthLine, &heightLine, + NULL, NULL, font); + if ( widthLine > widthTextMax ) + widthTextMax = widthLine; + heightTextTotal += heightLine; + } + + if ( pc == text.end() ) + { + break; + } + else // '\n' + { + curLine.clear(); + } + } + else + { + curLine += *pc; + } + } + + if ( x ) + *x = widthTextMax; + if ( y ) + *y = heightTextTotal; + if ( h ) + *h = heightLine; +} + +void wxDCImpl::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height) { - wxCHECK_RET( Ok(), wxT("invalid window dc") ); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); wxCoord x2 = x1 + width, y2 = y1 + height; - // this is to yield width of 3 for width == height == 10 - SetPen(wxPen(GetTextForeground(), (width + height + 1) / 7, wxSOLID)); + // the pen width is calibrated to give 3 for width == height == 10 + wxDCPenChanger pen( *m_owner, wxPen(GetTextForeground(), (width + height + 1)/7)); // we're drawing a scaled version of wx/generic/tick.xpm here wxCoord x3 = x1 + (4*width) / 10, // x of the tick bottom @@ -61,19 +644,47 @@ void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1, CalcBoundingBox(x2, y2); } -// ---------------------------------------------------------------------------- -// line/polygons -// ---------------------------------------------------------------------------- +bool +wxDCImpl::DoStretchBlit(wxCoord xdest, wxCoord ydest, + wxCoord dstWidth, wxCoord dstHeight, + wxDC *source, + wxCoord xsrc, wxCoord ysrc, + wxCoord srcWidth, wxCoord srcHeight, + wxRasterOperationMode rop, + bool useMask, + wxCoord xsrcMask, + wxCoord ysrcMask) +{ + wxCHECK_MSG( srcWidth && srcHeight && dstWidth && dstHeight, false, + _T("invalid blit size") ); + + // emulate the stretching by modifying the DC scale + double xscale = (double)srcWidth/dstWidth, + yscale = (double)srcHeight/dstHeight; + + double xscaleOld, yscaleOld; + GetUserScale(&xscaleOld, &yscaleOld); + SetUserScale(xscaleOld/xscale, yscaleOld/yscale); + + bool rc = DoBlit(wxCoord(xdest*xscale), wxCoord(ydest*yscale), + wxCoord(dstWidth*xscale), wxCoord(dstHeight*yscale), + source, + xsrc, ysrc, rop, useMask, xsrcMask, ysrcMask); + + SetUserScale(xscaleOld, yscaleOld); + + return rc; +} -void wxDCBase::DrawLines(const wxList *list, wxCoord xoffset, wxCoord yoffset) +void wxDCImpl::DrawLines(const wxPointList *list, wxCoord xoffset, wxCoord yoffset) { int n = list->GetCount(); wxPoint *points = new wxPoint[n]; int i = 0; - for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ ) + for ( wxPointList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ ) { - wxPoint *point = (wxPoint *)node->GetData(); + wxPoint *point = node->GetData(); points[i].x = point->x; points[i].y = point->y; } @@ -83,18 +694,17 @@ void wxDCBase::DrawLines(const wxList *list, wxCoord xoffset, wxCoord yoffset) delete [] points; } - -void wxDCBase::DrawPolygon(const wxList *list, +void wxDCImpl::DrawPolygon(const wxPointList *list, wxCoord xoffset, wxCoord yoffset, - int fillStyle) + wxPolygonFillMode fillStyle) { int n = list->GetCount(); wxPoint *points = new wxPoint[n]; int i = 0; - for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ ) + for ( wxPointList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ ) { - wxPoint *point = (wxPoint *)node->GetData(); + wxPoint *point = node->GetData(); points[i].x = point->x; points[i].y = point->y; } @@ -105,11 +715,11 @@ void wxDCBase::DrawPolygon(const wxList *list, } void -wxDCBase::DoDrawPolyPolygon(int n, +wxDCImpl::DoDrawPolyPolygon(int n, int count[], wxPoint points[], wxCoord xoffset, wxCoord yoffset, - int fillStyle) + wxPolygonFillMode fillStyle) { if ( n == 1 ) { @@ -136,7 +746,7 @@ wxDCBase::DoDrawPolyPolygon(int n, } pen = GetPen(); - SetPen(wxPen(*wxBLACK, 0, wxTRANSPARENT)); + SetPen(wxPen(*wxBLACK, 0, wxPENSTYLE_TRANSPARENT)); DoDrawPolygon(j, pts, xoffset, yoffset, fillStyle); SetPen(pen); for (i = j = 0; i < n; i++) @@ -147,45 +757,21 @@ wxDCBase::DoDrawPolyPolygon(int n, delete[] pts; } -// ---------------------------------------------------------------------------- -// splines -// ---------------------------------------------------------------------------- - #if wxUSE_SPLINES -// TODO: this API needs fixing (wxPointList, why (!const) "wxList *"?) -void wxDCBase::DrawSpline(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord x3, wxCoord y3) +void wxDCImpl::DrawSpline(wxCoord x1, wxCoord y1, + wxCoord x2, wxCoord y2, + wxCoord x3, wxCoord y3) { - wxList point_list; - - wxPoint *point1 = new wxPoint; - point1->x = x1; point1->y = y1; - point_list.Append((wxObject*)point1); - - wxPoint *point2 = new wxPoint; - point2->x = x2; point2->y = y2; - point_list.Append((wxObject*)point2); - - wxPoint *point3 = new wxPoint; - point3->x = x3; point3->y = y3; - point_list.Append((wxObject*)point3); - - DrawSpline(&point_list); - - for( wxList::compatibility_iterator node = point_list.GetFirst(); node; node = node->GetNext() ) - { - wxPoint *p = (wxPoint *)node->GetData(); - delete p; - } + wxPoint points[] = { wxPoint(x1, y1), wxPoint(x2, y2), wxPoint(x3, y3) }; + DrawSpline(WXSIZEOF(points), points); } -void wxDCBase::DrawSpline(int n, wxPoint points[]) +void wxDCImpl::DrawSpline(int n, wxPoint points[]) { - wxList list; - for (int i =0; i < n; i++) - { - list.Append((wxObject*)&points[i]); - } + wxPointList list; + for ( int i = 0; i < n; i++ ) + list.Append(&points[i]); DrawSpline(&list); } @@ -200,9 +786,9 @@ int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3, void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4); static bool wx_spline_add_point(double x, double y); -static void wx_spline_draw_point_array(wxDCBase *dc); +static void wx_spline_draw_point_array(wxDC *dc); -wxList wx_spline_point_list; +wxPointList wx_spline_point_list; #define half(z1, z2) ((z1+z2)/2.0) #define THRESHOLD 5 @@ -285,36 +871,34 @@ int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, static bool wx_spline_add_point(double x, double y) { - wxPoint *point = new wxPoint ; - point->x = (int) x; - point->y = (int) y; - wx_spline_point_list.Append((wxObject*)point); - return true; + wxPoint *point = new wxPoint( wxRound(x), wxRound(y) ); + wx_spline_point_list.Append(point ); + return true; } -static void wx_spline_draw_point_array(wxDCBase *dc) +static void wx_spline_draw_point_array(wxDC *dc) { - dc->DrawLines(&wx_spline_point_list, 0, 0 ); - wxList::compatibility_iterator node = wx_spline_point_list.GetFirst(); - while (node) - { - wxPoint *point = (wxPoint *)node->GetData(); - delete point; - wx_spline_point_list.Erase(node); - node = wx_spline_point_list.GetFirst(); - } + dc->DrawLines(&wx_spline_point_list, 0, 0 ); + wxPointList::compatibility_iterator node = wx_spline_point_list.GetFirst(); + while (node) + { + wxPoint *point = node->GetData(); + delete point; + wx_spline_point_list.Erase(node); + node = wx_spline_point_list.GetFirst(); + } } -void wxDCBase::DoDrawSpline( wxList *points ) +void wxDCImpl::DoDrawSpline( const wxPointList *points ) { - wxCHECK_RET( Ok(), wxT("invalid window dc") ); + wxCHECK_RET( IsOk(), wxT("invalid window dc") ); wxPoint *p; double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4; double x1, y1, x2, y2; - wxList::compatibility_iterator node = points->GetFirst(); - if (node == wxList::compatibility_iterator()) + wxPointList::compatibility_iterator node = points->GetFirst(); + if (!node) // empty list return; @@ -324,7 +908,7 @@ void wxDCBase::DoDrawSpline( wxList *points ) y1 = p->y; node = node->GetNext(); - p = (wxPoint *)node->GetData(); + p = node->GetData(); x2 = p->x; y2 = p->y; @@ -341,7 +925,7 @@ void wxDCBase::DoDrawSpline( wxList *points ) #endif // !wxUSE_STL ) { - p = (wxPoint *)node->GetData(); + p = node->GetData(); x1 = x2; y1 = y2; x2 = p->x; @@ -362,162 +946,185 @@ void wxDCBase::DoDrawSpline( wxList *points ) wx_spline_add_point( cx1, cy1 ); wx_spline_add_point( x2, y2 ); - wx_spline_draw_point_array( this ); + wx_spline_draw_point_array( m_owner ); } #endif // wxUSE_SPLINES -// ---------------------------------------------------------------------------- -// Partial Text Extents -// ---------------------------------------------------------------------------- -// Each element of the widths array will be the width of the string up to and -// including the coresponding character in text. This is the generic -// implementation, the port-specific classes should do this with native APIs -// if available and if faster. Note: pango_layout_index_to_pos is much slower -// than calling GetTextExtent!! - -#define FWC_SIZE 256 - -class FontWidthCache +void wxDCImpl::DoGradientFillLinear(const wxRect& rect, + const wxColour& initialColour, + const wxColour& destColour, + wxDirection nDirection) { -public: - FontWidthCache() : m_scaleX(1), m_widths(NULL) { } - ~FontWidthCache() { delete []m_widths; } - - void Reset() + // save old pen + wxPen oldPen = m_pen; + wxBrush oldBrush = m_brush; + + wxUint8 nR1 = initialColour.Red(); + wxUint8 nG1 = initialColour.Green(); + wxUint8 nB1 = initialColour.Blue(); + wxUint8 nR2 = destColour.Red(); + wxUint8 nG2 = destColour.Green(); + wxUint8 nB2 = destColour.Blue(); + wxUint8 nR, nG, nB; + + if ( nDirection == wxEAST || nDirection == wxWEST ) { - if (!m_widths) - m_widths = new int[FWC_SIZE]; - - memset(m_widths, 0, sizeof(int)*FWC_SIZE); - } - - wxFont m_font; - double m_scaleX; - int *m_widths; -}; - -static FontWidthCache s_fontWidthCache; + wxInt32 x = rect.GetWidth(); + wxInt32 w = x; // width of area to shade + wxInt32 xDelta = w/256; // height of one shade bend + if (xDelta < 1) + xDelta = 1; -bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const -{ - int totalWidth = 0; + while (x >= xDelta) + { + x -= xDelta; + if (nR1 > nR2) + nR = nR1 - (nR1-nR2)*(w-x)/w; + else + nR = nR1 + (nR2-nR1)*(w-x)/w; - size_t i, len = text.Length(); - widths.Empty(); - widths.Add(0, len); - int w, h; + if (nG1 > nG2) + nG = nG1 - (nG1-nG2)*(w-x)/w; + else + nG = nG1 + (nG2-nG1)*(w-x)/w; - // reset the cache if font or horizontal scale have changed - if (!s_fontWidthCache.m_widths || - (s_fontWidthCache.m_scaleX != m_scaleX) || - (s_fontWidthCache.m_font != GetFont())) - { - s_fontWidthCache.Reset(); - s_fontWidthCache.m_font = GetFont(); - s_fontWidthCache.m_scaleX = m_scaleX; + if (nB1 > nB2) + nB = nB1 - (nB1-nB2)*(w-x)/w; + else + nB = nB1 + (nB2-nB1)*(w-x)/w; + + wxColour colour(nR,nG,nB); + SetPen(wxPen(colour, 1, wxPENSTYLE_SOLID)); + SetBrush(wxBrush(colour)); + if(nDirection == wxEAST) + DoDrawRectangle(rect.GetRight()-x-xDelta+1, rect.GetTop(), + xDelta, rect.GetHeight()); + else //nDirection == wxWEST + DoDrawRectangle(rect.GetLeft()+x, rect.GetTop(), + xDelta, rect.GetHeight()); + } } - - // Calculate the position of each character based on the widths of - // the previous characters - for (i=0; i 0) { - w = s_fontWidthCache.m_widths[c_int]; - } - else - { - GetTextExtent(c, &w, &h); - if (c_int < FWC_SIZE) - s_fontWidthCache.m_widths[c_int] = w; - } + y -= yDelta; + if (nR1 > nR2) + nR = nR1 - (nR1-nR2)*(w-y)/w; + else + nR = nR1 + (nR2-nR1)*(w-y)/w; - totalWidth += w; - widths[i] = totalWidth; + if (nG1 > nG2) + nG = nG1 - (nG1-nG2)*(w-y)/w; + else + nG = nG1 + (nG2-nG1)*(w-y)/w; + + if (nB1 > nB2) + nB = nB1 - (nB1-nB2)*(w-y)/w; + else + nB = nB1 + (nB2-nB1)*(w-y)/w; + + wxColour colour(nR,nG,nB); + SetPen(wxPen(colour, 1, wxPENSTYLE_SOLID)); + SetBrush(wxBrush(colour)); + if(nDirection == wxNORTH) + DoDrawRectangle(rect.GetLeft(), rect.GetTop()+y, + rect.GetWidth(), yDelta); + else //nDirection == wxSOUTH + DoDrawRectangle(rect.GetLeft(), rect.GetBottom()-y-yDelta+1, + rect.GetWidth(), yDelta); + } } - return true; + SetPen(oldPen); + SetBrush(oldBrush); } - -// ---------------------------------------------------------------------------- -// enhanced text drawing -// ---------------------------------------------------------------------------- - -void wxDCBase::GetMultiLineTextExtent(const wxString& text, - wxCoord *x, - wxCoord *y, - wxCoord *h, - wxFont *font) +void wxDCImpl::DoGradientFillConcentric(const wxRect& rect, + const wxColour& initialColour, + const wxColour& destColour, + const wxPoint& circleCenter) { - wxCoord widthTextMax = 0, widthLine, - heightTextTotal = 0, heightLineDefault = 0, heightLine = 0; - - wxString curLine; - for ( const wxChar *pc = text; ; pc++ ) - { - if ( *pc == _T('\n') || *pc == _T('\0') ) - { - if ( curLine.empty() ) - { - // we can't use GetTextExtent - it will return 0 for both width - // and height and an empty line should count in height - // calculation - - // assume that this line has the same height as the previous - // one - if ( !heightLineDefault ) - heightLineDefault = heightLine; - - if ( !heightLineDefault ) - { - // but we don't know it yet - choose something reasonable - GetTextExtent(_T("W"), NULL, &heightLineDefault, - NULL, NULL, font); - } + //save the old pen color + wxColour oldPenColour = m_pen.GetColour(); + + wxUint8 nR1 = destColour.Red(); + wxUint8 nG1 = destColour.Green(); + wxUint8 nB1 = destColour.Blue(); + wxUint8 nR2 = initialColour.Red(); + wxUint8 nG2 = initialColour.Green(); + wxUint8 nB2 = initialColour.Blue(); + wxUint8 nR, nG, nB; + + + //Radius + wxInt32 cx = rect.GetWidth() / 2; + wxInt32 cy = rect.GetHeight() / 2; + wxInt32 nRadius; + if (cx < cy) + nRadius = cx; + else + nRadius = cy; - heightTextTotal += heightLineDefault; - } - else - { - GetTextExtent(curLine, &widthLine, &heightLine, - NULL, NULL, font); - if ( widthLine > widthTextMax ) - widthTextMax = widthLine; - heightTextTotal += heightLine; - } + //Offset of circle + wxInt32 nCircleOffX = circleCenter.x - (rect.GetWidth() / 2); + wxInt32 nCircleOffY = circleCenter.y - (rect.GetHeight() / 2); - if ( *pc == _T('\n') ) - { - curLine.clear(); - } - else - { - // the end of string - break; - } - } - else + for ( wxInt32 x = 0; x < rect.GetWidth(); x++ ) + { + for ( wxInt32 y = 0; y < rect.GetHeight(); y++ ) { - curLine += *pc; + //get color difference + wxInt32 nGradient = ((nRadius - + (wxInt32)sqrt( + pow((double)(x - cx - nCircleOffX), 2) + + pow((double)(y - cy - nCircleOffY), 2) + )) * 100) / nRadius; + + //normalize Gradient + if (nGradient < 0 ) + nGradient = 0; + + //get dest colors + nR = (wxUint8)(nR1 + ((nR2 - nR1) * nGradient / 100)); + nG = (wxUint8)(nG1 + ((nG2 - nG1) * nGradient / 100)); + nB = (wxUint8)(nB1 + ((nB2 - nB1) * nGradient / 100)); + + //set the pixel + m_pen.SetColour(wxColour(nR,nG,nB)); + DoDrawPoint(x + rect.GetLeft(), y + rect.GetTop()); } } + //return old pen color + m_pen.SetColour(oldPenColour); +} - if ( x ) - *x = widthTextMax; - if ( y ) - *y = heightTextTotal; - if ( h ) - *h = heightLine; +void wxDCImpl::InheritAttributes(wxWindow *win) +{ + wxCHECK_RET( win, "window can't be NULL" ); + + SetFont(win->GetFont()); + SetTextForeground(win->GetForegroundColour()); + SetTextBackground(win->GetBackgroundColour()); + SetBackground(wxBrush(win->GetBackgroundColour())); } -void wxDCBase::DrawLabel(const wxString& text, +//----------------------------------------------------------------------------- +// wxDC +//----------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) + +void wxDC::DrawLabel(const wxString& text, const wxBitmap& bitmap, const wxRect& rect, int alignment, @@ -589,9 +1196,9 @@ void wxDCBase::DrawLabel(const wxString& text, // split the string into lines and draw each of them separately wxString curLine; - for ( const wxChar *pc = text; ; pc++ ) + for ( wxString::const_iterator pc = text.begin(); ; ++pc ) { - if ( *pc == _T('\n') || *pc == _T('\0') ) + if ( pc == text.end() || *pc == '\n' ) { int xRealStart = x; // init it here to avoid compielr warnings @@ -629,14 +1236,14 @@ void wxDCBase::DrawLabel(const wxString& text, endUnderscore += xRealStart; } - if ( *pc == _T('\0') ) + if ( pc == text.end() ) break; curLine.clear(); } else // not end of line { - if ( pc - text.c_str() == indexAccel ) + if ( pc - text.begin() == indexAccel ) { // remeber to draw underscore here GetTextExtent(curLine, &startUnderscore, NULL); @@ -656,7 +1263,7 @@ void wxDCBase::DrawLabel(const wxString& text, if ( startUnderscore != endUnderscore ) { // it should be of the same colour as text - SetPen(wxPen(GetTextForeground(), 0, wxSOLID)); + SetPen(wxPen(GetTextForeground(), 0, wxPENSTYLE_SOLID)); yUnderscore--; @@ -673,6 +1280,60 @@ void wxDCBase::DrawLabel(const wxString& text, CalcBoundingBox(x0 + width0, y0 + height); } +#if WXWIN_COMPATIBILITY_2_8 + // for compatibility with the old code when wxCoord was long everywhere +void wxDC::GetTextExtent(const wxString& string, + long *x, long *y, + long *descent, + long *externalLeading, + const wxFont *theFont) const + { + wxCoord x2, y2, descent2, externalLeading2; + m_pimpl->DoGetTextExtent(string, &x2, &y2, + &descent2, &externalLeading2, + theFont); + if ( x ) + *x = x2; + if ( y ) + *y = y2; + if ( descent ) + *descent = descent2; + if ( externalLeading ) + *externalLeading = externalLeading2; + } + +void wxDC::GetLogicalOrigin(long *x, long *y) const + { + wxCoord x2, y2; + m_pimpl->DoGetLogicalOrigin(&x2, &y2); + if ( x ) + *x = x2; + if ( y ) + *y = y2; + } + +void wxDC::GetDeviceOrigin(long *x, long *y) const + { + wxCoord x2, y2; + m_pimpl->DoGetDeviceOrigin(&x2, &y2); + if ( x ) + *x = x2; + if ( y ) + *y = y2; + } + +void wxDC::GetClippingBox(long *x, long *y, long *w, long *h) const + { + wxCoord xx,yy,ww,hh; + m_pimpl->DoGetClippingBox(&xx, &yy, &ww, &hh); + if (x) *x = xx; + if (y) *y = yy; + if (w) *w = ww; + if (h) *h = hh; + } + +#endif // WXWIN_COMPATIBILITY_2_8 + /* Notes for wxWidgets DrawEllipticArcRot(...) @@ -715,26 +1376,26 @@ p.lenhard@t-online.de */ #ifdef __WXWINCE__ -void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y, +void wxDCImpl::DoDrawEllipticArcRot( wxCoord x, wxCoord y, wxCoord w, wxCoord h, double sa, double ea, double angle ) { - wxList list; + wxPointList list; CalculateEllipticPoints( &list, x, y, w, h, sa, ea ); Rotate( &list, angle, wxPoint( x+w/2, y+h/2 ) ); // Add center (for polygon/pie) - list.Append( (wxObject*) new wxPoint( x+w/2, y+h/2 ) ); + list.Append( new wxPoint( x+w/2, y+h/2 ) ); // copy list into array and delete list elements - int n = list.Number(); + int n = list.GetCount(); wxPoint *points = new wxPoint[n]; int i = 0; - wxNode* node = 0; - for ( node = list.First(); node; node = node->Next(), i++ ) + wxPointList::compatibility_iterator node; + for ( node = list.GetFirst(); node; node = node->GetNext(), i++ ) { - wxPoint *point = (wxPoint *)node->Data(); + wxPoint *point = node->GetData(); points[i].x = point->x; points[i].y = point->y; delete point; @@ -760,16 +1421,17 @@ void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y, } // DrawEllipticArcRot -void wxDCBase::Rotate( wxList* points, double angle, wxPoint center ) +void wxDCImpl::Rotate( wxPointList* points, double angle, wxPoint center ) { if( angle != 0.0 ) { double pi(M_PI); double dSinA = -sin(angle*2.0*pi/360.0); double dCosA = cos(angle*2.0*pi/360.0); - for ( wxNode* node = points->First(); node; node = node->Next() ) + wxPointList::compatibility_iterator node; + for ( node = points->GetFirst(); node; node = node->GetNext() ) { - wxPoint* point = (wxPoint*)node->Data(); + wxPoint* point = node->GetData(); // transform coordinates, if necessary if( center.x ) point->x -= center.x; @@ -787,7 +1449,7 @@ void wxDCBase::Rotate( wxList* points, double angle, wxPoint center ) } } -void wxDCBase::CalculateEllipticPoints( wxList* points, +void wxDCImpl::CalculateEllipticPoints( wxPointList* points, wxCoord xStart, wxCoord yStart, wxCoord w, wxCoord h, double sa, double ea ) @@ -860,7 +1522,7 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, long y2_old = 0; long y_old = 0; // Lists for quadrant 1 to 4 - wxList pointsarray[4]; + wxPointList pointsarray[4]; // Calculate points for first quadrant and set in all quadrants for( x = 0; x <= a; ++x ) { @@ -879,40 +1541,41 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, { int x1 = x - 1; // remove points on the same line - pointsarray[0].Insert( (wxObject*) new wxPoint( xCenter + x1 - decrX, yCenter - y_old ) ); - pointsarray[1].Append( (wxObject*) new wxPoint( xCenter - x1, yCenter - y_old ) ); - pointsarray[2].Insert( (wxObject*) new wxPoint( xCenter - x1, yCenter + y_old - decrY ) ); - pointsarray[3].Append( (wxObject*) new wxPoint( xCenter + x1 - decrX, yCenter + y_old - decrY ) ); + pointsarray[0].Insert( new wxPoint( xCenter + x1 - decrX, yCenter - y_old ) ); + pointsarray[1].Append( new wxPoint( xCenter - x1, yCenter - y_old ) ); + pointsarray[2].Insert( new wxPoint( xCenter - x1, yCenter + y_old - decrY ) ); + pointsarray[3].Append( new wxPoint( xCenter + x1 - decrX, yCenter + y_old - decrY ) ); } // set point } // calculate point // Starting and/or ending points for the quadrants, first quadrant gets both. - pointsarray[0].Insert( (wxObject*) new wxPoint( xCenter + a - decrX, yCenter ) ); - pointsarray[0].Append( (wxObject*) new wxPoint( xCenter, yCenter - b ) ); - pointsarray[1].Append( (wxObject*) new wxPoint( xCenter - a, yCenter ) ); - pointsarray[2].Append( (wxObject*) new wxPoint( xCenter, yCenter + b - decrY ) ); - pointsarray[3].Append( (wxObject*) new wxPoint( xCenter + a - decrX, yCenter ) ); + pointsarray[0].Insert( new wxPoint( xCenter + a - decrX, yCenter ) ); + pointsarray[0].Append( new wxPoint( xCenter, yCenter - b ) ); + pointsarray[1].Append( new wxPoint( xCenter - a, yCenter ) ); + pointsarray[2].Append( new wxPoint( xCenter, yCenter + b - decrY ) ); + pointsarray[3].Append( new wxPoint( xCenter + a - decrX, yCenter ) ); // copy quadrants in original list if( bUseAngles ) { // Copy the right part of the points in the lists // and delete the wxPoints, because they do not leave this method. - points->Append( (wxObject*) new wxPoint( xsa, ysa ) ); + points->Append( new wxPoint( xsa, ysa ) ); int q = sq; bool bStarted = false; bool bReady = false; bool bForceTurn = ( sq == eq && sa > ea ); while( !bReady ) { - for( wxNode *node = pointsarray[q].First(); node; node = node->Next() ) + wxPointList::compatibility_iterator node; + for( node = pointsarray[q].GetFirst(); node; node = node->GetNext() ) { // once: go to starting point in start quadrant if( !bStarted && ( - ( (wxPoint*) node->Data() )->x < xsa+1 && q <= 1 + node->GetData()->x < xsa+1 && q <= 1 || - ( (wxPoint*) node->Data() )->x > xsa-1 && q >= 2 + node->GetData()->x > xsa-1 && q >= 2 ) ) { @@ -924,16 +1587,16 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, { if( q != eq || bForceTurn || - ( (wxPoint*) node->Data() )->x > xea+1 && q <= 1 + ( (wxPoint*) node->GetData() )->x > xea+1 && q <= 1 || - ( (wxPoint*) node->Data() )->x < xea-1 && q >= 2 + ( (wxPoint*) node->GetData() )->x < xea-1 && q >= 2 ) { // copy point - wxPoint* pPoint = new wxPoint( *((wxPoint*) node->Data() ) ); - points->Append( (wxObject*) pPoint ); + wxPoint* pPoint = new wxPoint( *(node->GetData()) ); + points->Append( pPoint ); } - else if( q == eq && !bForceTurn || ( (wxPoint*) node->Data() )->x == xea) + else if( q == eq && !bForceTurn || node->GetData()->x == xea) { bReady = true; } @@ -944,78 +1607,56 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, bForceTurn = false; bStarted = true; } // while not bReady - points->Append( (wxObject*) new wxPoint( xea, yea ) ); + points->Append( new wxPoint( xea, yea ) ); // delete points for( q = 0; q < 4; ++q ) { - for( wxNode *node = pointsarray[q].First(); node; node = node->Next() ) + wxPointList::compatibility_iterator node; + for( node = pointsarray[q].GetFirst(); node; node = node->GetNext() ) { - wxPoint *p = (wxPoint *)node->Data(); + wxPoint *p = node->GetData(); delete p; } } } else { + wxPointList::compatibility_iterator node; // copy whole ellipse, wxPoints will be deleted outside - for( wxNode *node = pointsarray[0].First(); node; node = node->Next() ) + for( node = pointsarray[0].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxPoint *p = node->GetData(); points->Append( p ); } - for( node = pointsarray[1].First(); node; node = node->Next() ) + for( node = pointsarray[1].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxPoint *p = node->GetData(); points->Append( p ); } - for( node = pointsarray[2].First(); node; node = node->Next() ) + for( node = pointsarray[2].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxPoint *p = node->GetData(); points->Append( p ); } - for( node = pointsarray[3].First(); node; node = node->Next() ) + for( node = pointsarray[3].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxPoint *p = node->GetData(); points->Append( p ); } } // not iUseAngles } // CalculateEllipticPoints -#endif +#endif // __WXWINCE__ -bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, - const wxColour& col, int style) +float wxDCImpl::GetFontPointSizeAdjustment(float dpi) { -#if wxUSE_IMAGE - if (dc->GetBrush().GetStyle() == wxTRANSPARENT) - return true; - - int height = 0; - int width = 0; - dc->GetSize(&width, &height); - - //it would be nice to fail if we don't get a sensible size... - wxCHECK_MSG(width >= 1 && height >= 1, false, - wxT("In FloodFill, dc.GetSize routine failed, method not supported by this DC")); - - //this is much faster than doing the individual pixels - wxMemoryDC memdc; - wxBitmap bitmap(width, height); - memdc.SelectObject(bitmap); - memdc.Blit(0, 0, width, height, dc, 0, 0); - memdc.SelectObject(wxNullBitmap); - - wxImage image = bitmap.ConvertToImage(); - wxImageFloodFill(&image, x,y, dc->GetBrush(), col, style, - dc->GetLogicalFunction()); - bitmap = wxBitmap(image); - memdc.SelectObject(bitmap); - dc->Blit(0, 0, width, height, &memdc, 0, 0); - memdc.SelectObject(wxNullBitmap); - - return true; -#else - return false; -#endif + // wxMSW has long-standing bug where wxFont point size is interpreted as + // "pixel size corresponding to given point size *on screen*". In other + // words, on a typical 600dpi printer and a typical 96dpi screen, fonts + // are ~6 times smaller when printing. Unfortunately, this bug is so severe + // that *all* printing code has to account for it and consequently, other + // ports need to emulate this bug too: + const wxSize screenPPI = wxGetDisplayPPI(); + return float(screenPPI.y) / dpi; }