X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0a470e5ea537237f0562c3b2182ee293dec36eb3..d9b22d8fff794d8cadef74a2710be9e83c1adb5f:/src/msw/graphics.cpp diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index 77fa96e6b2..b8bc80a2e8 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -4,7 +4,6 @@ // Author: Stefan Csomor // Modified by: // Created: 2006-09-30 -// RCS-ID: $Id$ // Copyright: (c) 2006 Stefan Csomor // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -78,6 +77,31 @@ inline Color wxColourToColor(const wxColour& col) return Color(col.Alpha(), col.Red(), col.Green(), col.Blue()); } +// Do not use this pointer directly, it's only used by +// GetDrawTextStringFormat() and the cleanup code in wxGDIPlusRendererModule. +StringFormat* gs_drawTextStringFormat = NULL; + +// Get the string format used for the text drawing and measuring functions: +// notice that it must be the same one for all of them, otherwise the drawn +// text might be of different size than what measuring it returned. +inline StringFormat* GetDrawTextStringFormat() +{ + if ( !gs_drawTextStringFormat ) + { + gs_drawTextStringFormat = new StringFormat(StringFormat::GenericTypographic()); + + // This doesn't make any difference for DrawText() actually but we want + // this behaviour when measuring text. + gs_drawTextStringFormat->SetFormatFlags + ( + gs_drawTextStringFormat->GetFormatFlags() + | StringFormatFlagsMeasureTrailingSpaces + ); + } + + return gs_drawTextStringFormat; +} + } // anonymous namespace //----------------------------------------------------------------------------- @@ -272,7 +296,7 @@ private: GraphicsPath* m_brushPath; }; -class WXDLLIMPEXP_CORE wxGDIPlusBitmapData : public wxGraphicsObjectRefData +class WXDLLIMPEXP_CORE wxGDIPlusBitmapData : public wxGraphicsBitmapData { public: wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, Bitmap* bitmap ); @@ -280,6 +304,7 @@ public: ~wxGDIPlusBitmapData (); virtual Bitmap* GetGDIPlusBitmap() { return m_bitmap; } + virtual void* GetNativeBitmap() const { return m_bitmap; } #if wxUSE_IMAGE wxImage ConvertToImage() const; @@ -294,9 +319,13 @@ class wxGDIPlusFontData : public wxGraphicsObjectRefData { public: wxGDIPlusFontData( wxGraphicsRenderer* renderer, - const wxGDIPlusContext* gc, const wxFont &font, const wxColour& col ); + wxGDIPlusFontData(wxGraphicsRenderer* renderer, + const wxString& name, + REAL sizeInPixels, + int style, + const wxColour& col); ~wxGDIPlusFontData(); virtual Brush* GetGDIPlusBrush() { return m_textBrush; } @@ -309,7 +338,7 @@ private : REAL size, int style, const wxColour& col, - Unit fontUnit = UnitPixel); + Unit fontUnit); Brush* m_textBrush; Font* m_font; @@ -343,6 +372,13 @@ public: // stroke lines connecting each of the points virtual void StrokeLines( size_t n, const wxPoint2DDouble *points); + // We don't have any specific implementation for this one in wxMSW but + // override it just to avoid warnings about hiding the base class virtual. + virtual void StrokeLines( size_t n, const wxPoint2DDouble *beginPoints, const wxPoint2DDouble *endPoints) + { + wxGraphicsContext::StrokeLines(n, beginPoints, endPoints); + } + // draws a polygon virtual void DrawLines( size_t n, const wxPoint2DDouble *points, wxPolygonFillMode fillStyle = wxODDEVEN_RULE ); @@ -375,9 +411,6 @@ public: virtual void PushState(); virtual void PopState(); - // sets the font of this context - virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) const; - virtual void GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height, wxDouble *descent, wxDouble *externalLeading ) const; virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const; @@ -395,10 +428,7 @@ protected: 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); + virtual void DoDrawText(const wxString& str, wxDouble x, wxDouble y); Graphics* m_context; wxStack m_stateStack; @@ -540,17 +570,16 @@ public : virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ); #if wxUSE_IMAGE virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image); + virtual wxImage CreateImageFromBitmap(const wxGraphicsBitmap& bmp); #endif // wxUSE_IMAGE - // stub: should not be called directly - virtual wxGraphicsFont CreateFont( const wxFont& WXUNUSED(font), - const wxColour& WXUNUSED(col) ) - { wxFAIL; return wxNullGraphicsFont; } + virtual wxGraphicsFont CreateFont( const wxFont& font, + const wxColour& col); - // this is used to really create the font - wxGraphicsFont CreateGDIPlusFont( const wxGDIPlusContext* gc, - const wxFont &font, - const wxColour &col ); + virtual wxGraphicsFont CreateFont(double size, + const wxString& facename, + int flags = wxFONTFLAG_DEFAULT, + const wxColour& col = *wxBLACK); // create a graphics bitmap from a native bitmap virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap ); @@ -899,17 +928,12 @@ wxGDIPlusFontData::Init(const wxString& name, 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_font = new Font(name.wc_str(), size, style, fontUnit); m_textBrush = new SolidBrush(wxColourToColor(col)); } wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer, - const wxGDIPlusContext* gc, const wxFont &font, const wxColour& col ) : wxGraphicsObjectRefData( renderer ) @@ -922,17 +946,17 @@ wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer, if ( font.GetWeight() == wxFONTWEIGHT_BOLD ) style |= FontStyleBold; - 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; + Init(font.GetFaceName(), font.GetPointSize(), style, col, UnitPoint); +} - // 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(wxGraphicsRenderer* renderer, + const wxString& name, + REAL sizeInPixels, + int style, + const wxColour& col) : + wxGraphicsObjectRefData(renderer) +{ + Init(name, sizeInPixels, style, col, UnitPixel); } wxGDIPlusFontData::~wxGDIPlusFontData() @@ -951,13 +975,13 @@ wxGDIPlusFontData::~wxGDIPlusFontData() //----------------------------------------------------------------------------- wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, Bitmap* bitmap ) : - wxGraphicsObjectRefData( renderer ), m_bitmap( bitmap ) + wxGraphicsBitmapData( renderer ), m_bitmap( bitmap ) { m_helper = NULL; } wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, - const wxBitmap &bmp) : wxGraphicsObjectRefData( renderer ) + const wxBitmap &bmp) : wxGraphicsBitmapData( renderer ) { m_bitmap = NULL; m_helper = NULL; @@ -1084,22 +1108,6 @@ wxGDIPlusBitmapData::~wxGDIPlusBitmapData() 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 //----------------------------------------------------------------------------- @@ -1411,6 +1419,7 @@ void wxGDIPlusContext::Init(Graphics* graphics, int width, int height) m_context->SetTextRenderingHint(TextRenderingHintSystemDefault); m_context->SetPixelOffsetMode(PixelOffsetModeHalf); m_context->SetSmoothingMode(SmoothingModeHighQuality); + m_context->SetInterpolationMode(InterpolationModeHighQuality); m_state1 = m_context->Save(); m_state2 = m_context->Save(); } @@ -1556,10 +1565,44 @@ bool wxGDIPlusContext::SetAntialiasMode(wxAntialiasMode antialias) return true; } -bool wxGDIPlusContext::SetInterpolationQuality(wxInterpolationQuality WXUNUSED(interpolation)) +bool wxGDIPlusContext::SetInterpolationQuality(wxInterpolationQuality interpolation) { - // placeholder - return false; + if (m_interpolation == interpolation) + return true; + + InterpolationMode interpolationMode = InterpolationModeDefault; + switch (interpolation) + { + case wxINTERPOLATION_DEFAULT: + interpolationMode = InterpolationModeDefault; + break; + + case wxINTERPOLATION_NONE: + interpolationMode = InterpolationModeNearestNeighbor; + break; + + case wxINTERPOLATION_FAST: + interpolationMode = InterpolationModeLowQuality; + break; + + case wxINTERPOLATION_GOOD: + interpolationMode = InterpolationModeHighQuality; + break; + + case wxINTERPOLATION_BEST: + interpolationMode = InterpolationModeHighQualityBicubic; + break; + + default: + return false; + } + + if ( m_context->SetInterpolationMode(interpolationMode) != Gdiplus::Ok ) + return false; + + m_interpolation = interpolation; + + return true; } bool wxGDIPlusContext::SetCompositionMode(wxCompositionMode op) @@ -1719,17 +1762,8 @@ void wxGDIPlusContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxD DeleteObject(iconInfo.hbmMask); } -wxGraphicsFont wxGDIPlusContext::CreateFont( const wxFont &font, - const wxColour &col ) const -{ - wxGDIPlusRenderer* renderer = - static_cast(GetRenderer()); - return renderer->CreateGDIPlusFont(this, font, col); -} - -void wxGDIPlusContext::DoDrawFilledText(const wxString& str, - wxDouble x, wxDouble y, - const wxGraphicsBrush& brush) +void wxGDIPlusContext::DoDrawText(const wxString& str, + wxDouble x, wxDouble y ) { if (m_composition == wxCOMPOSITION_DEST) return; @@ -1742,18 +1776,15 @@ void wxGDIPlusContext::DoDrawFilledText(const wxString& str, wxGDIPlusFontData * const fontData = (wxGDIPlusFontData *)m_font.GetRefData(); - wxGDIPlusBrushData * const - brushData = (wxGDIPlusBrushData *)brush.GetRefData(); - + m_context->DrawString ( str.wc_str(*wxConvUI), // string to draw, always Unicode -1, // length: string is NUL-terminated fontData->GetGDIPlusFont(), PointF(x, y), - StringFormat::GenericTypographic(), - brushData ? brushData->GetGDIPlusBrush() - : fontData->GetGDIPlusBrush() + GetDrawTextStringFormat(), + fontData->GetGDIPlusBrush() ); } @@ -1770,12 +1801,14 @@ void wxGDIPlusContext::GetTextExtent( const wxString &str, wxDouble *width, wxDo REAL factorY = m_fontScaleRatio; - REAL rDescent = ffamily.GetCellDescent(FontStyleRegular) * - f->GetSize() / ffamily.GetEmHeight(FontStyleRegular); - REAL rAscent = ffamily.GetCellAscent(FontStyleRegular) * - f->GetSize() / ffamily.GetEmHeight(FontStyleRegular); - REAL rHeight = ffamily.GetLineSpacing(FontStyleRegular) * - f->GetSize() / ffamily.GetEmHeight(FontStyleRegular); + // Notice that we must use the real font style or the results would be + // incorrect for italic/bold fonts. + const INT style = f->GetStyle(); + const REAL size = f->GetSize(); + const REAL emHeight = ffamily.GetEmHeight(style); + REAL rDescent = ffamily.GetCellDescent(style) * size / emHeight; + REAL rAscent = ffamily.GetCellAscent(style) * size / emHeight; + REAL rHeight = ffamily.GetLineSpacing(style) * size / emHeight; if ( height ) *height = rHeight * factorY; @@ -1792,11 +1825,9 @@ void wxGDIPlusContext::GetTextExtent( const wxString &str, wxDouble *width, wxDo else { RectF layoutRect(0,0, 100000.0f, 100000.0f); - StringFormat strFormat( StringFormat::GenericTypographic() ); - strFormat.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces | strFormat.GetFormatFlags() ); RectF bounds ; - m_context->MeasureString((const wchar_t *) s , wcslen(s) , f, layoutRect, &strFormat, &bounds ) ; + m_context->MeasureString((const wchar_t *) s , wcslen(s) , f, layoutRect, GetDrawTextStringFormat(), &bounds ) ; if ( width ) *width = bounds.Width; if ( height ) @@ -1820,7 +1851,7 @@ void wxGDIPlusContext::GetPartialTextExtents(const wxString& text, wxArrayDouble wxASSERT_MSG(text.length() == len , wxT("GetPartialTextExtents not yet implemented for multichar situations")); RectF layoutRect(0,0, 100000.0f, 100000.0f); - StringFormat strFormat( StringFormat::GenericTypographic() ); + StringFormat strFormat( GetDrawTextStringFormat() ); size_t startPosition = 0; size_t remainder = len; @@ -1838,7 +1869,6 @@ void wxGDIPlusContext::GetPartialTextExtents(const wxString& text, wxArrayDouble ranges[i].Length = startPosition+i+1 ; } strFormat.SetMeasurableCharacterRanges(span,ranges); - strFormat.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces | strFormat.GetFormatFlags() ); m_context->MeasureCharacterRanges(ws, -1 , f,layoutRect, &strFormat,span,regions) ; RectF bbox ; @@ -2135,21 +2165,45 @@ wxGDIPlusRenderer::CreateRadialGradientBrush(wxDouble xo, wxDouble yo, } wxGraphicsFont -wxGDIPlusRenderer::CreateGDIPlusFont( const wxGDIPlusContext* gc, - const wxFont &font, - const wxColour &col ) +wxGDIPlusRenderer::CreateFont( const wxFont &font, + const wxColour &col ) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont); if ( font.IsOk() ) { wxGraphicsFont p; - p.SetRefData(new wxGDIPlusFontData( this, gc, font, col )); + p.SetRefData(new wxGDIPlusFontData( this, font, col )); return p; } else return wxNullGraphicsFont; } +wxGraphicsFont +wxGDIPlusRenderer::CreateFont(double size, + const wxString& facename, + int flags, + const wxColour& col) +{ + ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont); + + // Convert wxFont flags to GDI+ style: + int style = FontStyleRegular; + if ( flags & wxFONTFLAG_ITALIC ) + style |= FontStyleItalic; + if ( flags & wxFONTFLAG_UNDERLINED ) + style |= FontStyleUnderline; + if ( flags & wxFONTFLAG_BOLD ) + style |= FontStyleBold; + if ( flags & wxFONTFLAG_STRIKETHROUGH ) + style |= FontStyleStrikeout; + + + wxGraphicsFont f; + f.SetRefData(new wxGDIPlusFontData(this, facename, size, style, col)); + return f; +} + wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmap( const wxBitmap &bitmap ) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap); @@ -2184,8 +2238,19 @@ wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmapFromImage(const wxImage& image) return wxNullGraphicsBitmap; } + +wxImage wxGDIPlusRenderer::CreateImageFromBitmap(const wxGraphicsBitmap& bmp) +{ + ENSURE_LOADED_OR_RETURN(wxNullImage); + const wxGDIPlusBitmapData* const + data = static_cast(bmp.GetGraphicsData()); + + return data ? data->ConvertToImage() : wxNullImage; +} + #endif // wxUSE_IMAGE + wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmapFromNativeBitmap( void *bitmap ) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap); @@ -2217,8 +2282,19 @@ wxGraphicsBitmap wxGDIPlusRenderer::CreateSubBitmap( const wxGraphicsBitmap &bit class wxGDIPlusRendererModule : public wxModule { public: + wxGDIPlusRendererModule() + { + // We must be uninitialized before GDI+ DLL itself is unloaded. + AddDependency("wxGdiPlusModule"); + } + virtual bool OnInit() { return true; } - virtual void OnExit() { gs_GDIPlusRenderer.Unload(); } + virtual void OnExit() + { + wxDELETE(gs_drawTextStringFormat); + + gs_GDIPlusRenderer.Unload(); + } private: DECLARE_DYNAMIC_CLASS(wxGDIPlusRendererModule)