From 21661d51d83e681fe5065e2b83a0c8329eb44fec Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 8 Feb 2019 16:16:02 +0100 Subject: [PATCH 1/2] Remove unnecessary wxGDIPlusPrintingContext dtor No real changes. --- src/msw/graphics.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index 4d201c7a9f..ea6291eb8e 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -507,7 +507,6 @@ class wxGDIPlusPrintingContext : public wxGDIPlusContext { public: wxGDIPlusPrintingContext( wxGraphicsRenderer* renderer, const wxDC& dc ); - virtual ~wxGDIPlusPrintingContext() { } protected: }; From bf515d769a12b0c04fa1638565e0661096d77435 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 8 Feb 2019 16:49:37 +0100 Subject: [PATCH 2/2] Fix size of text drawing using wxGraphicsContext when printing When using both wxEnhMetaFileDC (used for print preview) and wxPrinterDC, a global scale factor was applied to the graphics context in wxGDIPlusPrintingContext ctor and this changes size of the text rendered using size specified in point units. To prevent this from happening, stop applying this scale factor in the base class GetTextExtent() and apply it instead when setting fonts in the derived wxGDIPlusPrintingContext only. This ensures that the results are consistent between GetTextExtent() and DrawText() and also keeps the font scale hack entirely in wxGDIPlusPrintingContext without affecting the base class. It's still not totally clear why do we have to do this at all even although we specify the font sizes in UnitPoint units which ought to be DPI-independent -- but somehow are not. But at least the output is correct now and the code is arguably more clear than before. This fixes a regression with text size when printing or previewing introduced by d5020362ffb99608eacd2492d621cad20b1075a7 Closes #18338. --- src/msw/graphics.cpp | 83 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 14 deletions(-) diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index ea6291eb8e..e5309c9bf7 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -336,6 +336,14 @@ public: REAL size, int style, const wxColour& col); + + // This ctor takes ownership of the brush. + wxGDIPlusFontData(wxGraphicsRenderer* renderer, + const wxString& name, + REAL size, + int style, + Brush* textBrush); + ~wxGDIPlusFontData(); virtual Brush* GetGDIPlusBrush() { return m_textBrush; } @@ -347,7 +355,16 @@ private : void Init(const wxString& name, REAL size, int style, - const wxColour& col); + Brush* textBrush); + + // Common part of ctors taking wxColour. + void Init(const wxString& name, + REAL size, + int style, + const wxColour& col) + { + Init(name, size, style, new SolidBrush(wxColourToColor(col))); + } Brush* m_textBrush; Font* m_font; @@ -432,9 +449,6 @@ public: Graphics* GetGraphics() const { return m_context; } protected: - - 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); @@ -507,7 +521,41 @@ class wxGDIPlusPrintingContext : public wxGDIPlusContext { public: wxGDIPlusPrintingContext( wxGraphicsRenderer* renderer, const wxDC& dc ); -protected: + + // Override to scale the font proportionally to the DPI. + virtual void SetFont(const wxGraphicsFont& font) wxOVERRIDE + { + // The casts here are safe because we're only supposed to be passed + // fonts created by this renderer. + Font* const f = static_cast(font.GetRefData())->GetGDIPlusFont(); + Brush* const b = static_cast(font.GetRefData())->GetGDIPlusBrush(); + + // To scale the font, we need to create a new one which means + // retrieving all the parameters originally used to create the font. + FontFamily ffamily; + f->GetFamily(&ffamily); + + WCHAR familyName[LF_FACESIZE]; + ffamily.GetFamilyName(familyName); + + wxGraphicsFont fontScaled; + fontScaled.SetRefData(new wxGDIPlusFontData + ( + GetRenderer(), + familyName, + f->GetSize() / m_fontScaleRatio, + f->GetStyle(), + b->Clone() + )); + wxGDIPlusContext::SetFont(fontScaled); + } + +private: + // This is logically const ratio between this context DPI and the standard + // one which is used for scaling the fonts used with this context: without + // this, the fonts wouldn't have the correct size, even though we + // explicitly create them using UnitPoint units. + wxDouble m_fontScaleRatio; }; //----------------------------------------------------------------------------- @@ -982,7 +1030,7 @@ void wxGDIPlusFontData::Init(const wxString& name, REAL size, int style, - const wxColour& col) + Brush* textBrush) { #if wxUSE_PRIVATE_FONTS // If the user has registered any private fonts, they should be used in @@ -1014,7 +1062,7 @@ wxGDIPlusFontData::Init(const wxString& name, m_font = new Font(name.wc_str(), size, style, UnitPoint); } - m_textBrush = new SolidBrush(wxColourToColor(col)); + m_textBrush = textBrush; } wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer, @@ -1045,6 +1093,16 @@ wxGDIPlusFontData::wxGDIPlusFontData(wxGraphicsRenderer* renderer, Init(name, size, style, col); } +wxGDIPlusFontData::wxGDIPlusFontData(wxGraphicsRenderer* renderer, + const wxString& name, + REAL size, + int style, + Brush* brush) + : wxGraphicsObjectRefData(renderer) +{ + Init(name, size, style, brush); +} + wxGDIPlusFontData::~wxGDIPlusFontData() { delete m_textBrush; @@ -1686,7 +1744,6 @@ void wxGDIPlusContext::Init(Graphics* graphics, int width, int height) m_state2 = 0; m_width = width; m_height = height; - m_fontScaleRatio = 1.0; m_context->SetTextRenderingHint(TextRenderingHintSystemDefault); m_context->SetPixelOffsetMode(PixelOffsetModeHalf); @@ -2118,8 +2175,6 @@ void wxGDIPlusContext::GetTextExtent( const wxString &str, wxDouble *width, wxDo FontFamily ffamily ; f->GetFamily(&ffamily) ; - REAL factorY = m_fontScaleRatio; - // Notice that we must use the real font style or the results would be // incorrect for italic/bold fonts. const INT style = f->GetStyle(); @@ -2130,11 +2185,11 @@ void wxGDIPlusContext::GetTextExtent( const wxString &str, wxDouble *width, wxDo REAL rHeight = ffamily.GetLineSpacing(style) * size / emHeight; if ( height && str.empty() ) - *height = rHeight * factorY; + *height = rHeight; if ( descent ) - *descent = rDescent * factorY; + *descent = rDescent; if ( externalLeading ) - *externalLeading = (rHeight - rAscent - rDescent) * factorY; + *externalLeading = rHeight - rAscent - rDescent; } // measuring empty strings is not guaranteed, so do it by hand @@ -2277,7 +2332,7 @@ wxGDIPlusPrintingContext::wxGDIPlusPrintingContext( wxGraphicsRenderer* renderer // We use this modifier when measuring fonts. It is needed because the // page scale is modified above. - m_fontScaleRatio = context->GetDpiY() / 72.0; + m_fontScaleRatio = context->GetDpiY() / 96.0; } //-----------------------------------------------------------------------------