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
//-----------------------------------------------------------------------------
GraphicsPath* m_brushPath;
};
-class WXDLLIMPEXP_CORE wxGDIPlusBitmapData : public wxGraphicsObjectRefData
+class WXDLLIMPEXP_CORE wxGDIPlusBitmapData : public wxGraphicsBitmapData
{
public:
wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, Bitmap* bitmap );
~wxGDIPlusBitmapData ();
virtual Bitmap* GetGDIPlusBitmap() { return m_bitmap; }
+ virtual void* GetNativeBitmap() const { return m_bitmap; }
+
+#if wxUSE_IMAGE
+ wxImage ConvertToImage() const;
+#endif // wxUSE_IMAGE
private :
Bitmap* m_bitmap;
{
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; }
REAL size,
int style,
const wxColour& col,
- Unit fontUnit = UnitPixel);
+ Unit fontUnit);
Brush* m_textBrush;
Font* m_font;
// 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 );
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;
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<GraphicsState> m_stateStack;
wxDECLARE_NO_COPY_CLASS(wxGDIPlusContext);
};
+#if wxUSE_IMAGE
+
+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:
virtual wxGraphicsContext * CreateContext( wxWindow* window );
+#if wxUSE_IMAGE
+ virtual wxGraphicsContext * CreateContextFromImage(wxImage& image);
+#endif // wxUSE_IMAGE
+
virtual wxGraphicsContext * CreateMeasuringContext();
// Path
// create a native bitmap representation
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 );
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 )
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()
//-----------------------------------------------------------------------------
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;
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;
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();
}
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)
DeleteObject(iconInfo.hbmMask);
}
-wxGraphicsFont wxGDIPlusContext::CreateFont( const wxFont &font,
- const wxColour &col ) const
-{
- wxGDIPlusRenderer* renderer =
- static_cast<wxGDIPlusRenderer*>(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;
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()
);
}
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;
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 )
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;
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 ;
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);
}
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);
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;
+}
+
+
+wxImage wxGDIPlusRenderer::CreateImageFromBitmap(const wxGraphicsBitmap& bmp)
+{
+ ENSURE_LOADED_OR_RETURN(wxNullImage);
+ const wxGDIPlusBitmapData* const
+ data = static_cast<wxGDIPlusBitmapData*>(bmp.GetGraphicsData());
+
+ return data ? data->ConvertToImage() : wxNullImage;
+}
+
+#endif // wxUSE_IMAGE
+
+
wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmapFromNativeBitmap( void *bitmap )
{
ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
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)