X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/364197e882e328fff368d91a33b1fe2ffc1f7857..0a470e5ea537237f0562c3b2182ee293dec36eb3:/src/msw/graphics.cpp?ds=sidebyside diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index b09c1dca14..77fa96e6b2 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -281,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; @@ -297,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; }; @@ -309,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(); @@ -377,10 +390,11 @@ protected: wxDouble m_fontScaleRatio; -private: - void Init(); - void SetDefaults(); + // 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, @@ -394,13 +408,42 @@ private: wxDECLARE_NO_COPY_CLASS(wxGDIPlusContext); }; -class wxGDIPlusMeasuringContext : public wxGDIPlusContext +#if wxUSE_IMAGE + +class wxGDIPlusImageContext : public wxGDIPlusContext { public: - wxGDIPlusMeasuringContext( wxGraphicsRenderer* renderer ) : wxGDIPlusContext( renderer , m_hdc = GetDC(NULL), 1000, 1000 ) + 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(); } - wxGDIPlusMeasuringContext() + +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 ) { } @@ -462,6 +505,10 @@ public : virtual wxGraphicsContext * CreateContext( wxWindow* window ); +#if wxUSE_IMAGE + virtual wxGraphicsContext * CreateContextFromImage(wxImage& image); +#endif // wxUSE_IMAGE + virtual wxGraphicsContext * CreateMeasuringContext(); // Path @@ -491,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), @@ -842,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; @@ -865,17 +930,9 @@ wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer, if ( fontUnit == UnitDisplay ) fontUnit = UnitPixel; - REAL points = font.GetPointSize(); - - // This scaling is needed when we use unit other than the - // default UnitPoint. It works for both display and printing. - REAL size = points * (100.0 / 72.0); - // 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 ); - - m_textBrush = new SolidBrush(wxColourToColor(col)); + Init(font.GetFaceName(), font.GetPointSize(), style, col, fontUnit); } wxGDIPlusFontData::~wxGDIPlusFontData() @@ -999,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 //----------------------------------------------------------------------------- @@ -1269,66 +1364,50 @@ public : 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_enableOffset = true; - 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_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); @@ -1941,6 +2020,17 @@ wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc) 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); @@ -2073,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);