Changed wxMSW wxGraphicsContext font rendering and extent calculation to take into the account that the page scale has been manually changed when using print contexts (fixes #12830)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@66699 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Jaakko Salli
2011-01-17 10:11:49 +00:00
parent f8ecadbf74
commit eb40c2d836

View File

@@ -98,6 +98,8 @@ inline Color wxColourToColor(const wxColour& col)
// wxGraphicsPath implementation // wxGraphicsPath implementation
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class wxGDIPlusContext;
class wxGDIPlusPathData : public wxGraphicsPathData class wxGDIPlusPathData : public wxGraphicsPathData
{ {
public : public :
@@ -289,7 +291,10 @@ private :
class wxGDIPlusFontData : public wxGraphicsObjectRefData class wxGDIPlusFontData : public wxGraphicsObjectRefData
{ {
public: public:
wxGDIPlusFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col ); wxGDIPlusFontData( wxGraphicsRenderer* renderer,
const wxGDIPlusContext* gc,
const wxFont &font,
const wxColour& col );
~wxGDIPlusFontData(); ~wxGDIPlusFontData();
virtual Brush* GetGDIPlusBrush() { return m_textBrush; } virtual Brush* GetGDIPlusBrush() { return m_textBrush; }
@@ -302,7 +307,8 @@ private :
class wxGDIPlusContext : public wxGraphicsContext class wxGDIPlusContext : public wxGraphicsContext
{ {
public: public:
wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc , wxDouble width, wxDouble height ); wxGDIPlusContext( wxGraphicsRenderer* renderer, const wxDC& dc );
wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc, wxDouble width, wxDouble height );
wxGDIPlusContext( wxGraphicsRenderer* renderer, HWND hwnd ); wxGDIPlusContext( wxGraphicsRenderer* renderer, HWND hwnd );
wxGDIPlusContext( wxGraphicsRenderer* renderer, Graphics* gr); wxGDIPlusContext( wxGraphicsRenderer* renderer, Graphics* gr);
wxGDIPlusContext(); wxGDIPlusContext();
@@ -354,12 +360,21 @@ public:
virtual void PushState(); virtual void PushState();
virtual void PopState(); 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, virtual void GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
wxDouble *descent, wxDouble *externalLeading ) const; wxDouble *descent, wxDouble *externalLeading ) const;
virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const; virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
virtual bool ShouldOffset() const; virtual bool ShouldOffset() const;
virtual void GetSize( wxDouble* width, wxDouble *height ); virtual void GetSize( wxDouble* width, wxDouble *height );
Graphics* GetGraphics() const { return m_context; }
protected:
wxDouble m_fontScaleRatio;
private: private:
void Init(); void Init();
void SetDefaults(); void SetDefaults();
@@ -400,6 +415,114 @@ private:
DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusMeasuringContext) DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusMeasuringContext)
} ; } ;
class wxGDIPlusPrintingContext : public wxGDIPlusContext
{
public:
wxGDIPlusPrintingContext( wxGraphicsRenderer* renderer, const wxDC& dc );
virtual ~wxGDIPlusPrintingContext() { }
protected:
};
//-----------------------------------------------------------------------------
// wxGDIPlusRenderer declaration
//-----------------------------------------------------------------------------
class wxGDIPlusRenderer : public wxGraphicsRenderer
{
public :
wxGDIPlusRenderer()
{
m_loaded = -1;
m_gditoken = 0;
}
virtual ~wxGDIPlusRenderer()
{
if ( m_loaded == 1 )
{
Unload();
}
}
// Context
virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc);
virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc);
#if wxUSE_PRINTING_ARCHITECTURE
virtual wxGraphicsContext * CreateContext( const wxPrinterDC& dc);
#endif
#if wxUSE_ENH_METAFILE
virtual wxGraphicsContext * CreateContext( const wxEnhMetaFileDC& dc);
#endif
virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window );
virtual wxGraphicsContext * CreateContext( wxWindow* window );
virtual wxGraphicsContext * CreateMeasuringContext();
// Path
virtual wxGraphicsPath CreatePath();
// Matrix
virtual wxGraphicsMatrix CreateMatrix( wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
wxDouble tx=0.0, wxDouble ty=0.0);
virtual wxGraphicsPen CreatePen(const wxPen& pen) ;
virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
virtual wxGraphicsBrush
CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops);
virtual wxGraphicsBrush
CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc,
wxDouble radius,
const wxGraphicsGradientStops& stops);
// create a native bitmap representation
virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap );
// stub: should not be called directly
virtual wxGraphicsFont CreateFont( const wxFont& WXUNUSED(font),
const wxColour& WXUNUSED(col) )
{ wxFAIL; return wxNullGraphicsFont; }
// this is used to really create the font
wxGraphicsFont CreateGDIPlusFont( const wxGDIPlusContext* gc,
const wxFont &font,
const wxColour &col );
// create a graphics bitmap from a native bitmap
virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap );
// create a subimage from a native image representation
virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
protected :
bool EnsureIsLoaded();
void Load();
void Unload();
friend class wxGDIPlusRendererModule;
private :
int m_loaded;
ULONG_PTR m_gditoken;
DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusRenderer)
} ;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxGDIPlusPen implementation // wxGDIPlusPen implementation
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -718,14 +841,13 @@ wxGDIPlusBrushData::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
// wxGDIPlusFont implementation // wxGDIPlusFont implementation
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer, const wxFont &font, wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer,
const wxColour& col ) : wxGraphicsObjectRefData( renderer ) const wxGDIPlusContext* gc,
const wxFont &font,
const wxColour& col )
: wxGraphicsObjectRefData( renderer )
{ {
m_textBrush = NULL;
m_font = NULL;
wxWCharBuffer s = font.GetFaceName().wc_str( *wxConvUI ); wxWCharBuffer s = font.GetFaceName().wc_str( *wxConvUI );
int size = font.GetPointSize();
int style = FontStyleRegular; int style = FontStyleRegular;
if ( font.GetStyle() == wxFONTSTYLE_ITALIC ) if ( font.GetStyle() == wxFONTSTYLE_ITALIC )
style |= FontStyleItalic; style |= FontStyleItalic;
@@ -733,7 +855,25 @@ wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer, const wxFont
style |= FontStyleUnderline; style |= FontStyleUnderline;
if ( font.GetWeight() == wxFONTWEIGHT_BOLD ) if ( font.GetWeight() == wxFONTWEIGHT_BOLD )
style |= FontStyleBold; style |= FontStyleBold;
m_font = new Font( s , size , style );
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();
// 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)); m_textBrush = new SolidBrush(wxColourToColor(col));
} }
@@ -1138,6 +1278,22 @@ wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc, wxDou
SetDefaults(); SetDefaults();
} }
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();
}
wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HWND hwnd ) wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HWND hwnd )
: wxGraphicsContext(renderer) : wxGraphicsContext(renderer)
{ {
@@ -1169,6 +1325,7 @@ void wxGDIPlusContext::Init()
m_state2= 0; m_state2= 0;
m_height = 0; m_height = 0;
m_width = 0; m_width = 0;
m_fontScaleRatio = 1.0;
} }
void wxGDIPlusContext::SetDefaults() void wxGDIPlusContext::SetDefaults()
@@ -1178,14 +1335,6 @@ void wxGDIPlusContext::SetDefaults()
m_context->SetSmoothingMode(SmoothingModeHighQuality); m_context->SetSmoothingMode(SmoothingModeHighQuality);
m_state1 = m_context->Save(); m_state1 = m_context->Save();
m_state2 = m_context->Save(); m_state2 = m_context->Save();
// 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);
} }
wxGDIPlusContext::~wxGDIPlusContext() wxGDIPlusContext::~wxGDIPlusContext()
@@ -1459,6 +1608,14 @@ void wxGDIPlusContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxD
DeleteObject(iconInfo.hbmMask); 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, void wxGDIPlusContext::DoDrawFilledText(const wxString& str,
wxDouble x, wxDouble y, wxDouble x, wxDouble y,
const wxGraphicsBrush& brush) const wxGraphicsBrush& brush)
@@ -1500,7 +1657,7 @@ void wxGDIPlusContext::GetTextExtent( const wxString &str, wxDouble *width, wxDo
f->GetFamily(&ffamily) ; f->GetFamily(&ffamily) ;
REAL factorY = m_context->GetDpiY() / 72.0 ; REAL factorY = m_fontScaleRatio;
REAL rDescent = ffamily.GetCellDescent(FontStyleRegular) * REAL rDescent = ffamily.GetCellDescent(FontStyleRegular) *
f->GetSize() / ffamily.GetEmHeight(FontStyleRegular); f->GetSize() / ffamily.GetEmHeight(FontStyleRegular);
@@ -1629,97 +1786,32 @@ void wxGDIPlusContext::GetSize( wxDouble* width, wxDouble *height )
*width = m_width; *width = m_width;
*height = m_height; *height = m_height;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxGDIPlusRenderer declaration // wxGDIPlusPrintingContext implementation
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class wxGDIPlusRenderer : public wxGraphicsRenderer wxGDIPlusPrintingContext::wxGDIPlusPrintingContext( wxGraphicsRenderer* renderer,
const wxDC& dc )
: wxGDIPlusContext(renderer, dc)
{ {
public : Graphics* context = GetGraphics();
wxGDIPlusRenderer()
{
m_loaded = -1;
m_gditoken = 0;
}
virtual ~wxGDIPlusRenderer() //m_context->SetPageUnit(UnitDocument);
{
if ( m_loaded == 1 )
{
Unload();
}
}
// Context // 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);
virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc); // We use this modifier when measuring fonts. It is needed because the
// page scale is modified above.
virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc); m_fontScaleRatio = context->GetDpiY() / 72.0;
}
#if wxUSE_PRINTING_ARCHITECTURE
virtual wxGraphicsContext * CreateContext( const wxPrinterDC& dc);
#endif
#if wxUSE_ENH_METAFILE
virtual wxGraphicsContext * CreateContext( const wxEnhMetaFileDC& dc);
#endif
virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window );
virtual wxGraphicsContext * CreateContext( wxWindow* window );
virtual wxGraphicsContext * CreateMeasuringContext();
// Path
virtual wxGraphicsPath CreatePath();
// Matrix
virtual wxGraphicsMatrix CreateMatrix( wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
wxDouble tx=0.0, wxDouble ty=0.0);
virtual wxGraphicsPen CreatePen(const wxPen& pen) ;
virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
virtual wxGraphicsBrush
CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops);
virtual wxGraphicsBrush
CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc,
wxDouble radius,
const wxGraphicsGradientStops& stops);
// sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
// create a native bitmap representation
virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap );
// create a graphics bitmap from a native bitmap
virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap );
// create a subimage from a native image representation
virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
protected :
bool EnsureIsLoaded();
void Load();
void Unload();
friend class wxGDIPlusRendererModule;
private :
int m_loaded;
ULONG_PTR m_gditoken;
DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusRenderer)
} ;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxGDIPlusRenderer implementation // wxGDIPlusRenderer implementation
@@ -1783,18 +1875,15 @@ void wxGDIPlusRenderer::Unload()
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxWindowDC& dc) wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxWindowDC& dc)
{ {
ENSURE_LOADED_OR_RETURN(NULL); ENSURE_LOADED_OR_RETURN(NULL);
wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl ); return new wxGDIPlusContext(this, dc);
wxSize sz = dc.GetSize();
return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
} }
#if wxUSE_PRINTING_ARCHITECTURE #if wxUSE_PRINTING_ARCHITECTURE
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxPrinterDC& dc) wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxPrinterDC& dc)
{ {
ENSURE_LOADED_OR_RETURN(NULL); ENSURE_LOADED_OR_RETURN(NULL);
wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl ); wxGDIPlusContext* context = new wxGDIPlusPrintingContext(this, dc);
wxSize sz = dc.GetSize(); return context;
return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
} }
#endif #endif
@@ -1802,18 +1891,15 @@ wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxPrinterDC& dc)
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxEnhMetaFileDC& dc) wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxEnhMetaFileDC& dc)
{ {
ENSURE_LOADED_OR_RETURN(NULL); ENSURE_LOADED_OR_RETURN(NULL);
wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl ); wxGDIPlusContext* context = new wxGDIPlusPrintingContext(this, dc);
wxSize sz = dc.GetSize(); return context;
return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
} }
#endif #endif
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc) wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc)
{ {
ENSURE_LOADED_OR_RETURN(NULL); ENSURE_LOADED_OR_RETURN(NULL);
wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl ); return new wxGDIPlusContext(this, dc);
wxSize sz = dc.GetSize();
return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
} }
wxGraphicsContext * wxGDIPlusRenderer::CreateMeasuringContext() wxGraphicsContext * wxGDIPlusRenderer::CreateMeasuringContext()
@@ -1919,14 +2005,16 @@ wxGDIPlusRenderer::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
return p; return p;
} }
// sets the font wxGraphicsFont
wxGraphicsFont wxGDIPlusRenderer::CreateFont( const wxFont &font , const wxColour &col ) wxGDIPlusRenderer::CreateGDIPlusFont( const wxGDIPlusContext* gc,
const wxFont &font,
const wxColour &col )
{ {
ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont); ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont);
if ( font.Ok() ) if ( font.Ok() )
{ {
wxGraphicsFont p; wxGraphicsFont p;
p.SetRefData(new wxGDIPlusFontData( this , font, col )); p.SetRefData(new wxGDIPlusFontData( this, gc, font, col ));
return p; return p;
} }
else else