X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4f320d7c57daa1cd4bc86cbe1da1ef1619b22edc..0a470e5ea537237f0562c3b2182ee293dec36eb3:/src/msw/graphics.cpp diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index 7e42d37f03..77fa96e6b2 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -37,13 +37,15 @@ #include "wx/dcprint.h" #endif +#include "wx/stack.h" + #include "wx/private/graphics.h" #include "wx/msw/wrapgdip.h" #include "wx/msw/dc.h" -#include "wx/dcgraph.h" #if wxUSE_ENH_METAFILE #include "wx/msw/enhmeta.h" #endif +#include "wx/dcgraph.h" #include "wx/msw/private.h" // needs to be before #include @@ -51,10 +53,6 @@ #include #endif -#include "wx/stack.h" - -WX_DECLARE_STACK(GraphicsState, GraphicsStates); - namespace { @@ -283,6 +281,10 @@ public: virtual Bitmap* GetGDIPlusBitmap() { return m_bitmap; } +#if wxUSE_IMAGE + wxImage ConvertToImage() const; +#endif // wxUSE_IMAGE + private : Bitmap* m_bitmap; Bitmap* m_helper; @@ -299,7 +301,16 @@ public: virtual Brush* GetGDIPlusBrush() { return m_textBrush; } virtual Font* GetGDIPlusFont() { return m_font; } + private : + // Common part of all ctors, flags here is a combination of values of + // FontStyle GDI+ enum. + void Init(const wxString& name, + REAL size, + int style, + const wxColour& col, + Unit fontUnit = UnitPixel); + Brush* m_textBrush; Font* m_font; }; @@ -311,7 +322,7 @@ public: wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc, wxDouble width, wxDouble height ); wxGDIPlusContext( wxGraphicsRenderer* renderer, HWND hwnd ); wxGDIPlusContext( wxGraphicsRenderer* renderer, Graphics* gr); - wxGDIPlusContext(); + wxGDIPlusContext(wxGraphicsRenderer* renderer); virtual ~wxGDIPlusContext(); @@ -327,6 +338,8 @@ public: virtual void StrokePath( const wxGraphicsPath& p ); virtual void FillPath( const wxGraphicsPath& p , wxPolygonFillMode fillStyle = wxODDEVEN_RULE ); + virtual void DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ); + // stroke lines connecting each of the points virtual void StrokeLines( size_t n, const wxPoint2DDouble *points); @@ -335,6 +348,8 @@ public: virtual bool SetAntialiasMode(wxAntialiasMode antialias); + virtual bool SetInterpolationQuality(wxInterpolationQuality interpolation); + virtual bool SetCompositionMode(wxCompositionMode op); virtual void BeginLayer(wxDouble opacity); @@ -370,43 +385,67 @@ public: virtual void GetSize( wxDouble* width, wxDouble *height ); Graphics* GetGraphics() const { return m_context; } - bool IsPrinting() const { return m_isPrinting; } - // utility to setup page scale etc for printing - void SetupForPrinting(); +protected: -private: - void Init(); - void SetDefaults(); + wxDouble m_fontScaleRatio; + + // Used from ctors (including those in the derived classes) and takes + // ownership of the graphics pointer that must be non-NULL. + void Init(Graphics* graphics, int width, int height); +private: virtual void DoDrawText(const wxString& str, wxDouble x, wxDouble y) { DoDrawFilledText(str, x, y, wxNullGraphicsBrush); } virtual void DoDrawFilledText(const wxString& str, wxDouble x, wxDouble y, const wxGraphicsBrush& backgroundBrush); Graphics* m_context; - - GraphicsStates m_stateStack; + wxStack m_stateStack; GraphicsState m_state1; GraphicsState m_state2; - wxDouble m_width; - wxDouble m_height; + wxDECLARE_NO_COPY_CLASS(wxGDIPlusContext); +}; - bool m_isPrinting; +#if wxUSE_IMAGE - DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusContext) +class wxGDIPlusImageContext : public wxGDIPlusContext +{ +public: + wxGDIPlusImageContext(wxGraphicsRenderer* renderer, wxImage& image) : + wxGDIPlusContext(renderer), + m_image(image), + m_bitmap(renderer, image) + { + Init + ( + new Graphics(m_bitmap.GetGDIPlusBitmap()), + image.GetWidth(), + image.GetHeight() + ); + } + + virtual ~wxGDIPlusImageContext() + { + m_image = m_bitmap.ConvertToImage(); + } + +private: + wxImage& m_image; + wxGDIPlusBitmapData m_bitmap; + + wxDECLARE_NO_COPY_CLASS(wxGDIPlusImageContext); }; +#endif // wxUSE_IMAGE + class wxGDIPlusMeasuringContext : public wxGDIPlusContext { public: wxGDIPlusMeasuringContext( wxGraphicsRenderer* renderer ) : wxGDIPlusContext( renderer , m_hdc = GetDC(NULL), 1000, 1000 ) { } - wxGDIPlusMeasuringContext() - { - } virtual ~wxGDIPlusMeasuringContext() { @@ -414,10 +453,17 @@ public: } private: - HDC m_hdc; - DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusMeasuringContext) + HDC m_hdc ; } ; +class wxGDIPlusPrintingContext : public wxGDIPlusContext +{ +public: + wxGDIPlusPrintingContext( wxGraphicsRenderer* renderer, const wxDC& dc ); + virtual ~wxGDIPlusPrintingContext() { } +protected: +}; + //----------------------------------------------------------------------------- // wxGDIPlusRenderer declaration //----------------------------------------------------------------------------- @@ -459,6 +505,10 @@ public : virtual wxGraphicsContext * CreateContext( wxWindow* window ); +#if wxUSE_IMAGE + virtual wxGraphicsContext * CreateContextFromImage(wxImage& image); +#endif // wxUSE_IMAGE + virtual wxGraphicsContext * CreateMeasuringContext(); // Path @@ -488,6 +538,9 @@ public : // create a native bitmap representation virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ); +#if wxUSE_IMAGE + virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image); +#endif // wxUSE_IMAGE // stub: should not be called directly virtual wxGraphicsFont CreateFont( const wxFont& WXUNUSED(font), @@ -594,25 +647,25 @@ wxGDIPlusPenData::wxGDIPlusPenData( wxGraphicsRenderer* renderer, const wxPen &p DashStyle dashStyle = DashStyleSolid; switch ( pen.GetStyle() ) { - case wxSOLID : + case wxPENSTYLE_SOLID : break; - case wxDOT : + case wxPENSTYLE_DOT : dashStyle = DashStyleDot; break; - case wxLONG_DASH : + case wxPENSTYLE_LONG_DASH : dashStyle = DashStyleDash; // TODO verify break; - case wxSHORT_DASH : + case wxPENSTYLE_SHORT_DASH : dashStyle = DashStyleDash; break; - case wxDOT_DASH : + case wxPENSTYLE_DOT_DASH : dashStyle = DashStyleDashDot; break; - case wxUSER_DASH : + case wxPENSTYLE_USER_DASH : { dashStyle = DashStyleCustom; wxDash *dashes; @@ -629,12 +682,18 @@ wxGDIPlusPenData::wxGDIPlusPenData( wxGraphicsRenderer* renderer, const wxPen &p } } break; - case wxSTIPPLE : + case wxPENSTYLE_STIPPLE : { wxBitmap* bmp = pen.GetStipple(); - if ( bmp && bmp->Ok() ) + if ( bmp && bmp->IsOk() ) { - m_penImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE()); + m_penImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(), +#if wxUSE_PALETTE + (HPALETTE)bmp->GetPalette()->GetHPALETTE() +#else + NULL +#endif + ); m_penBrush = new TextureBrush(m_penImage); m_pen->SetBrush( m_penBrush ); } @@ -642,30 +701,32 @@ wxGDIPlusPenData::wxGDIPlusPenData( wxGraphicsRenderer* renderer, const wxPen &p } break; default : - if ( pen.GetStyle() >= wxFIRST_HATCH && pen.GetStyle() <= wxLAST_HATCH ) + if ( pen.GetStyle() >= wxPENSTYLE_FIRST_HATCH && + pen.GetStyle() <= wxPENSTYLE_LAST_HATCH ) { - HatchStyle style = HatchStyleHorizontal; + HatchStyle style; switch( pen.GetStyle() ) { - case wxBDIAGONAL_HATCH : + case wxPENSTYLE_BDIAGONAL_HATCH : style = HatchStyleBackwardDiagonal; break ; - case wxCROSSDIAG_HATCH : + case wxPENSTYLE_CROSSDIAG_HATCH : style = HatchStyleDiagonalCross; break ; - case wxFDIAGONAL_HATCH : + case wxPENSTYLE_FDIAGONAL_HATCH : style = HatchStyleForwardDiagonal; break ; - case wxCROSS_HATCH : + case wxPENSTYLE_CROSS_HATCH : style = HatchStyleCross; break ; - case wxHORIZONTAL_HATCH : + case wxPENSTYLE_HORIZONTAL_HATCH : style = HatchStyleHorizontal; break ; - case wxVERTICAL_HATCH : + case wxPENSTYLE_VERTICAL_HATCH : style = HatchStyleVertical; break ; - + default: + style = HatchStyleHorizontal; } m_penBrush = new HatchBrush ( @@ -701,28 +762,29 @@ wxGDIPlusBrushData::wxGDIPlusBrushData( wxGraphicsRenderer* renderer , const wxB } else if ( brush.IsHatch() ) { - HatchStyle style = HatchStyleHorizontal; + HatchStyle style; switch( brush.GetStyle() ) { - case wxBDIAGONAL_HATCH : + case wxBRUSHSTYLE_BDIAGONAL_HATCH : style = HatchStyleBackwardDiagonal; break ; - case wxCROSSDIAG_HATCH : + case wxBRUSHSTYLE_CROSSDIAG_HATCH : style = HatchStyleDiagonalCross; break ; - case wxFDIAGONAL_HATCH : + case wxBRUSHSTYLE_FDIAGONAL_HATCH : style = HatchStyleForwardDiagonal; break ; - case wxCROSS_HATCH : + case wxBRUSHSTYLE_CROSS_HATCH : style = HatchStyleCross; break ; - case wxHORIZONTAL_HATCH : + case wxBRUSHSTYLE_HORIZONTAL_HATCH : style = HatchStyleHorizontal; break ; - case wxVERTICAL_HATCH : + case wxBRUSHSTYLE_VERTICAL_HATCH : style = HatchStyleVertical; break ; - + default: + style = HatchStyleHorizontal; } m_brush = new HatchBrush ( @@ -734,10 +796,16 @@ wxGDIPlusBrushData::wxGDIPlusBrushData( wxGraphicsRenderer* renderer , const wxB else { wxBitmap* bmp = brush.GetStipple(); - if ( bmp && bmp->Ok() ) + if ( bmp && bmp->IsOk() ) { wxDELETE( m_brushImage ); - m_brushImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE()); + m_brushImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(), +#if wxUSE_PALETTE + (HPALETTE)bmp->GetPalette()->GetHPALETTE() +#else + NULL +#endif + ); m_brush = new TextureBrush(m_brushImage); } } @@ -824,13 +892,28 @@ wxGDIPlusBrushData::CreateRadialGradientBrush(wxDouble xo, wxDouble yo, // wxGDIPlusFont implementation //----------------------------------------------------------------------------- +void +wxGDIPlusFontData::Init(const wxString& name, + REAL size, + int style, + const wxColour& col, + Unit fontUnit) +{ + // This scaling is needed when we use unit other than the + // default UnitPoint. It works for both display and printing. + size *= 100.0f / 72.0f; + + m_font = new Font(name, size, style, fontUnit); + + m_textBrush = new SolidBrush(wxColourToColor(col)); +} + wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer, const wxGDIPlusContext* gc, const wxFont &font, const wxColour& col ) : wxGraphicsObjectRefData( renderer ) { - wxWCharBuffer s = font.GetFaceName().wc_str( *wxConvUI ); int style = FontStyleRegular; if ( font.GetStyle() == wxFONTSTYLE_ITALIC ) style |= FontStyleItalic; @@ -839,29 +922,17 @@ wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer, if ( font.GetWeight() == wxFONTWEIGHT_BOLD ) style |= FontStyleBold; - if ( gc->IsPrinting() ) - { - Graphics* context = gc->GetGraphics(); - - Unit fontUnit = context->GetPageUnit(); - // if fontUnit is UnitDisplay, then specify UnitPixel, otherwise - // you'll get a "InvalidParameter" from GDI+ - if ( fontUnit == UnitDisplay ) - fontUnit = UnitPixel; - - REAL points = font.GetPointSize(); - REAL size = points * (100.0 / 72.0); + Graphics* context = gc->GetGraphics(); - // NB: font unit should match context's unit. We can use UnitPixel, - // as that is what the print context should use. - m_font = new Font( s, size, style, fontUnit ); - } - else - { - m_font = new Font( s, font.GetPointSize(), style ); - } + Unit fontUnit = context->GetPageUnit(); + // if fontUnit is UnitDisplay, then specify UnitPixel, otherwise + // you'll get a "InvalidParameter" from GDI+ + if ( fontUnit == UnitDisplay ) + fontUnit = UnitPixel; - m_textBrush = new SolidBrush(wxColourToColor(col)); + // NB: font unit should match context's unit. We can use UnitPixel, + // as that is what the print context should use. + Init(font.GetFaceName(), font.GetPointSize(), style, col, fontUnit); } wxGDIPlusFontData::~wxGDIPlusFontData() @@ -894,7 +965,13 @@ wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, Bitmap* image = NULL; if ( bmp.GetMask() ) { - Bitmap interim((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE()) ; + Bitmap interim((HBITMAP)bmp.GetHBITMAP(), +#if wxUSE_PALETTE + (HPALETTE)bmp.GetPalette()->GetHPALETTE() +#else + NULL +#endif + ); size_t width = interim.GetWidth(); size_t height = interim.GetHeight(); @@ -950,7 +1027,13 @@ wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, } else { - image = Bitmap::FromHBITMAP((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE()); + image = Bitmap::FromHBITMAP((HBITMAP)bmp.GetHBITMAP(), +#if wxUSE_PALETTE + (HPALETTE)bmp.GetPalette()->GetHPALETTE() +#else + NULL +#endif + ); if ( bmp.HasAlpha() && GetPixelFormatSize(image->GetPixelFormat()) == 32 ) { size_t width = image->GetWidth(); @@ -973,12 +1056,50 @@ wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, m_bitmap = image; } +#if wxUSE_IMAGE + +wxImage wxGDIPlusBitmapData::ConvertToImage() const +{ + // We could use Bitmap::LockBits() and convert to wxImage directly but + // passing by wxBitmap is easier. It would be nice to measure performance + // of the two methods but for this the second one would need to be written + // first... + HBITMAP hbmp; + if ( m_bitmap->GetHBITMAP(Color(0xffffffff), &hbmp) != Gdiplus::Ok ) + return wxNullImage; + + wxBitmap bmp; + bmp.SetWidth(m_bitmap->GetWidth()); + bmp.SetHeight(m_bitmap->GetHeight()); + bmp.SetHBITMAP(hbmp); + bmp.SetDepth(IsAlphaPixelFormat(m_bitmap->GetPixelFormat()) ? 32 : 24); + return bmp.ConvertToImage(); +} + +#endif // wxUSE_IMAGE + wxGDIPlusBitmapData::~wxGDIPlusBitmapData() { delete m_bitmap; delete m_helper; } +// ---------------------------------------------------------------------------- +// wxGraphicsBitmap implementation +// ---------------------------------------------------------------------------- + +#if wxUSE_IMAGE + +wxImage wxGraphicsBitmap::ConvertToImage() const +{ + const wxGDIPlusBitmapData* const + data = static_cast(GetGraphicsData()); + + return data ? data->ConvertToImage() : wxNullImage; +} + +#endif // wxUSE_IMAGE + //----------------------------------------------------------------------------- // wxGDIPlusPath implementation //----------------------------------------------------------------------------- @@ -1220,9 +1341,6 @@ void * wxGDIPlusMatrixData::GetNativeMatrix() const // wxGDIPlusContext implementation //----------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusContext,wxGraphicsContext) -IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusMeasuringContext,wxGDIPlusContext) - class wxGDIPlusOffsetHelper { public : @@ -1243,70 +1361,53 @@ public : bool m_offset; } ; -wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc, wxDouble width, wxDouble height ) +wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer) { - Init(); - - m_context = new Graphics(hdc); - m_width = width; - m_height = height; - - SetDefaults(); + Init(new Graphics(hdc), width, height); } wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, const wxDC& dc ) : wxGraphicsContext(renderer) { - Init(); - wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl ); HDC hdc = (HDC) msw->GetHDC(); - - m_context = new Graphics(hdc); wxSize sz = dc.GetSize(); - m_width = sz.x; - m_height = sz.y; - SetDefaults(); + Init(new Graphics(hdc), sz.x, sz.y); } wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HWND hwnd ) : wxGraphicsContext(renderer) { - Init(); - m_context = new Graphics( hwnd); RECT rect = wxGetWindowRect(hwnd); - m_width = rect.right - rect.left; - m_height = rect.bottom - rect.top; - SetDefaults(); + Init(new Graphics(hwnd), rect.right - rect.left, rect.bottom - rect.top); + m_enableOffset = true; } wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, Graphics* gr ) : wxGraphicsContext(renderer) { - Init(); - m_context = gr; - SetDefaults(); + Init(gr, 0, 0); } -wxGDIPlusContext::wxGDIPlusContext() : wxGraphicsContext(NULL) +wxGDIPlusContext::wxGDIPlusContext(wxGraphicsRenderer* renderer) + : wxGraphicsContext(renderer) { - Init(); + // Derived class must call Init() later but just set m_context to NULL for + // safety to avoid crashing in our dtor if Init() ends up not being called. + m_context = NULL; } -void wxGDIPlusContext::Init() +void wxGDIPlusContext::Init(Graphics* graphics, int width, int height) { - m_context = NULL; + m_context = graphics; m_state1 = 0; - m_state2= 0; - m_height = 0; - m_width = 0; - m_isPrinting = false; -} + m_state2 = 0; + m_width = width; + m_height = height; + m_fontScaleRatio = 1.0; -void wxGDIPlusContext::SetDefaults() -{ m_context->SetTextRenderingHint(TextRenderingHintSystemDefault); m_context->SetPixelOffsetMode(PixelOffsetModeHalf); m_context->SetSmoothingMode(SmoothingModeHighQuality); @@ -1314,21 +1415,6 @@ void wxGDIPlusContext::SetDefaults() m_state2 = m_context->Save(); } -void wxGDIPlusContext::SetupForPrinting() -{ - //m_context->SetPageUnit(UnitDocument); - - // Setup page scale, based on DPI ratio. - // Antecedent should be 100dpi when the default page unit (UnitDisplay) - // is used. Page unit UnitDocument would require 300dpi instead. - // Note that calling SetPageScale() does not have effect on non-printing - // DCs (that is, any other than wxPrinterDC or wxEnhMetaFileDC). - REAL dpiRatio = 100.0 / m_context->GetDpiY(); - m_context->SetPageScale(dpiRatio); - - m_isPrinting = true; -} - wxGDIPlusContext::~wxGDIPlusContext() { if ( m_context ) @@ -1356,6 +1442,31 @@ void wxGDIPlusContext::ResetClip() m_context->ResetClip(); } +void wxGDIPlusContext::DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) +{ + if (m_composition == wxCOMPOSITION_DEST) + return; + + wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() ); + Brush *brush = m_brush.IsNull() ? NULL : ((wxGDIPlusBrushData*)m_brush.GetRefData())->GetGDIPlusBrush(); + Pen *pen = m_pen.IsNull() ? NULL : ((wxGDIPlusPenData*)m_pen.GetGraphicsData())->GetGDIPlusPen(); + + if ( brush ) + { + // the offset is used to fill only the inside of the rectangle and not paint underneath + // its border which may influence a transparent Pen + REAL offset = 0; + if ( pen ) + offset = pen->GetWidth(); + m_context->FillRectangle( brush, (REAL)x + offset/2, (REAL)y + offset/2, (REAL)w - offset, (REAL)h - offset); + } + + if ( pen ) + { + m_context->DrawRectangle( pen, (REAL)x, (REAL)y, (REAL)w, (REAL)h ); + } +} + void wxGDIPlusContext::StrokeLines( size_t n, const wxPoint2DDouble *points) { if (m_composition == wxCOMPOSITION_DEST) @@ -1445,6 +1556,12 @@ bool wxGDIPlusContext::SetAntialiasMode(wxAntialiasMode antialias) return true; } +bool wxGDIPlusContext::SetInterpolationQuality(wxInterpolationQuality WXUNUSED(interpolation)) +{ + // placeholder + return false; +} + bool wxGDIPlusContext::SetCompositionMode(wxCompositionMode op) { if ( m_composition == op ) @@ -1505,6 +1622,8 @@ void wxGDIPlusContext::PushState() void wxGDIPlusContext::PopState() { + wxCHECK_RET( !m_stateStack.empty(), wxT("No state to pop") ); + GraphicsState state = m_stateStack.top(); m_stateStack.pop(); m_context->Restore(state); @@ -1522,7 +1641,7 @@ void wxGDIPlusContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDo { Rect drawRect((REAL) x, (REAL)y, (REAL)w, (REAL)h); m_context->SetPixelOffsetMode( PixelOffsetModeNone ); - m_context->DrawImage(image, drawRect, 0 , 0 , image->GetWidth()-1, image->GetHeight()-1, UnitPixel ) ; + m_context->DrawImage(image, drawRect, 0 , 0 , image->GetWidth(), image->GetHeight(), UnitPixel ) ; m_context->SetPixelOffsetMode( PixelOffsetModeHalf ); } else @@ -1608,7 +1727,6 @@ wxGraphicsFont wxGDIPlusContext::CreateFont( const wxFont &font, return renderer->CreateGDIPlusFont(this, font, col); } - void wxGDIPlusContext::DoDrawFilledText(const wxString& str, wxDouble x, wxDouble y, const wxGraphicsBrush& brush) @@ -1650,12 +1768,7 @@ void wxGDIPlusContext::GetTextExtent( const wxString &str, wxDouble *width, wxDo f->GetFamily(&ffamily) ; - REAL factorY; - if ( !IsPrinting() ) - factorY = m_context->GetDpiY() / 72.0; - else - // when printing the page scaling already does the trick - factorY = 1.0; + REAL factorY = m_fontScaleRatio; REAL rDescent = ffamily.GetCellDescent(FontStyleRegular) * f->GetSize() / ffamily.GetEmHeight(FontStyleRegular); @@ -1744,6 +1857,9 @@ void wxGDIPlusContext::GetPartialTextExtents(const wxString& text, wxArrayDouble bool wxGDIPlusContext::ShouldOffset() const { + if ( !m_enableOffset ) + return false; + int penwidth = 0 ; if ( !m_pen.IsNull() ) { @@ -1785,6 +1901,32 @@ void wxGDIPlusContext::GetSize( wxDouble* width, wxDouble *height ) *height = m_height; } +//----------------------------------------------------------------------------- +// wxGDIPlusPrintingContext implementation +//----------------------------------------------------------------------------- + +wxGDIPlusPrintingContext::wxGDIPlusPrintingContext( wxGraphicsRenderer* renderer, + const wxDC& dc ) + : wxGDIPlusContext(renderer, dc) +{ + Graphics* context = GetGraphics(); + + //m_context->SetPageUnit(UnitDocument); + + // Setup page scale, based on DPI ratio. + // Antecedent should be 100dpi when the default page unit + // (UnitDisplay) is used. Page unit UnitDocument would require 300dpi + // instead. Note that calling SetPageScale() does not have effect on + // non-printing DCs (that is, any other than wxPrinterDC or + // wxEnhMetaFileDC). + REAL dpiRatio = 100.0 / context->GetDpiY(); + context->SetPageScale(dpiRatio); + + // We use this modifier when measuring fonts. It is needed because the + // page scale is modified above. + m_fontScaleRatio = context->GetDpiY() / 72.0; +} + //----------------------------------------------------------------------------- // wxGDIPlusRenderer implementation //----------------------------------------------------------------------------- @@ -1839,7 +1981,7 @@ void wxGDIPlusRenderer::Unload() if ( m_gditoken ) { GdiplusShutdown(m_gditoken); - m_gditoken = NULL; + m_gditoken = 0; } m_loaded = -1; // next Load() will try again } @@ -1847,15 +1989,16 @@ void wxGDIPlusRenderer::Unload() wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxWindowDC& dc) { ENSURE_LOADED_OR_RETURN(NULL); - return new wxGDIPlusContext(this, dc); + wxGDIPlusContext* context = new wxGDIPlusContext(this, dc); + context->EnableOffset(true); + return context; } #if wxUSE_PRINTING_ARCHITECTURE wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxPrinterDC& dc) { ENSURE_LOADED_OR_RETURN(NULL); - wxGDIPlusContext* context = new wxGDIPlusContext(this, dc); - context->SetupForPrinting(); + wxGDIPlusContext* context = new wxGDIPlusPrintingContext(this, dc); return context; } #endif @@ -1864,8 +2007,7 @@ wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxPrinterDC& dc) wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxEnhMetaFileDC& dc) { ENSURE_LOADED_OR_RETURN(NULL); - wxGDIPlusContext* context = new wxGDIPlusContext(this, dc); - context->SetupForPrinting(); + wxGDIPlusContext* context = new wxGDIPlusPrintingContext(this, dc); return context; } #endif @@ -1873,9 +2015,22 @@ wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxEnhMetaFileDC& dc) wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc) { ENSURE_LOADED_OR_RETURN(NULL); - return new wxGDIPlusContext(this, dc); + wxGDIPlusContext* context = new wxGDIPlusContext(this, dc); + context->EnableOffset(true); + return context; +} + +#if wxUSE_IMAGE +wxGraphicsContext * wxGDIPlusRenderer::CreateContextFromImage(wxImage& image) +{ + ENSURE_LOADED_OR_RETURN(NULL); + wxGDIPlusContext* context = new wxGDIPlusImageContext(this, image); + context->EnableOffset(true); + return context; } +#endif // wxUSE_IMAGE + wxGraphicsContext * wxGDIPlusRenderer::CreateMeasuringContext() { ENSURE_LOADED_OR_RETURN(NULL); @@ -1929,7 +2084,7 @@ wxGraphicsMatrix wxGDIPlusRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDoub wxGraphicsPen wxGDIPlusRenderer::CreatePen(const wxPen& pen) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsPen); - if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT ) + if ( !pen.IsOk() || pen.GetStyle() == wxTRANSPARENT ) return wxNullGraphicsPen; else { @@ -1942,7 +2097,7 @@ wxGraphicsPen wxGDIPlusRenderer::CreatePen(const wxPen& pen) wxGraphicsBrush wxGDIPlusRenderer::CreateBrush(const wxBrush& brush ) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush); - if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT ) + if ( !brush.IsOk() || brush.GetStyle() == wxTRANSPARENT ) return wxNullGraphicsBrush; else { @@ -1985,7 +2140,7 @@ wxGDIPlusRenderer::CreateGDIPlusFont( const wxGDIPlusContext* gc, const wxColour &col ) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont); - if ( font.Ok() ) + if ( font.IsOk() ) { wxGraphicsFont p; p.SetRefData(new wxGDIPlusFontData( this, gc, font, col )); @@ -1998,7 +2153,7 @@ wxGDIPlusRenderer::CreateGDIPlusFont( const wxGDIPlusContext* gc, wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmap( const wxBitmap &bitmap ) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap); - if ( bitmap.Ok() ) + if ( bitmap.IsOk() ) { wxGraphicsBitmap p; p.SetRefData(new wxGDIPlusBitmapData( this , bitmap )); @@ -2008,6 +2163,29 @@ wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmap( const wxBitmap &bitmap ) return wxNullGraphicsBitmap; } +#if wxUSE_IMAGE + +wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmapFromImage(const wxImage& image) +{ + ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap); + if ( image.IsOk() ) + { + // Notice that we rely on conversion from wxImage to wxBitmap here but + // we could probably do it more efficiently by converting from wxImage + // to GDI+ Bitmap directly, i.e. copying wxImage pixels to the buffer + // returned by Bitmap::LockBits(). However this would require writing + // code specific for this task while like this we can reuse existing + // code (see also wxGDIPlusBitmapData::ConvertToImage()). + wxGraphicsBitmap gb; + gb.SetRefData(new wxGDIPlusBitmapData(this, image)); + return gb; + } + else + return wxNullGraphicsBitmap; +} + +#endif // wxUSE_IMAGE + wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmapFromNativeBitmap( void *bitmap ) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap); @@ -2058,6 +2236,14 @@ WXHDC wxGCDC::AcquireHDC() if ( !gc ) return NULL; +#if wxUSE_CAIRO + // we can't get the HDC if it is not a GDI+ context + wxGraphicsRenderer* r1 = gc->GetRenderer(); + wxGraphicsRenderer* r2 = wxGraphicsRenderer::GetCairoRenderer(); + if (r1 == r2) + return NULL; +#endif + Graphics * const g = static_cast(gc->GetNativeContext()); return g ? g->GetHDC() : NULL; } @@ -2070,6 +2256,14 @@ void wxGCDC::ReleaseHDC(WXHDC hdc) wxGraphicsContext * const gc = GetGraphicsContext(); wxCHECK_RET( gc, "can't release HDC because there is no wxGraphicsContext" ); +#if wxUSE_CAIRO + // we can't get the HDC if it is not a GDI+ context + wxGraphicsRenderer* r1 = gc->GetRenderer(); + wxGraphicsRenderer* r2 = wxGraphicsRenderer::GetCairoRenderer(); + if (r1 == r2) + return; +#endif + Graphics * const g = static_cast(gc->GetNativeContext()); wxCHECK_RET( g, "can't release HDC because there is no Graphics" );