Improve wxSVGFileDC on macOS: use correct scaling.

See #22390.
This commit is contained in:
Vadim Zeitlin 2022-05-05 17:29:20 +02:00
commit 84e15a8fd2
2 changed files with 257 additions and 249 deletions

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,8 @@
#include "wx/filename.h"
#include "wx/mstream.h"
#include "wx/scopedarray.h"
#include "wx/display.h"
#include "wx/private/rescale.h"
#if wxUSE_MARKUP
#include "wx/private/markupparser.h"
@ -38,6 +40,8 @@
namespace
{
static const wxSize SVG_DPI(96, 96);
// This function returns a string representation of a floating point number in
// C locale (i.e. always using "." for the decimal separator) and with the
// fixed precision (which is 2 for some unknown reason but this is what it was
@ -359,19 +363,18 @@ wxString CreateBrushFill(const wxBrush& brush, wxSVGShapeRenderingMode mode)
void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font)
{
// When using DPI-independent pixels, the results of GetTextExtent() and
// similar don't depend on DPI anyhow.
#ifndef wxHAS_DPI_INDEPENDENT_PIXELS
static const int SVG_DPI = 96;
const double screenDPI = sDC.GetPPI().y;
const double scale = screenDPI / SVG_DPI;
if ( scale > 1 )
const double scale = screenDPI / SVG_DPI.y;
if ( scale != 1 )
{
// wxScreenDC uses the DPI of the main screen to determine the text
// extent and character width/height. Because the SVG should be
// DPI-independent we want the text extent of the default (96) DPI.
//
// Even when using DPI Independent pixels (like macOS), we still need to
// scale because macOS DPI (72) is different than SVG DPI (96).
// (wxScreenDC returns the standard DPI also on Retina screens.)
//
// We can't just divide the returned sizes by the scale factor, because
// text does not scale linear (at least on Windows). Therefore, we scale
// the font size instead.
@ -380,7 +383,6 @@ void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font)
sDC.SetFont(scaledFont);
}
else
#endif // !wxHAS_DPI_INDEPENDENT_PIXELS
{
sDC.SetFont(font);
}
@ -558,11 +560,14 @@ void wxSVGFileDCImpl::Init(const wxString& filename, int width, int height,
else
m_outfile.reset(new wxFileOutputStream(m_filename));
const wxSize dpiSize = FromDIP(wxSize(m_width, m_height));
wxString s;
s += wxS("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
s += wxS("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n\n");
s += wxS("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"");
s += wxString::Format(wxS(" width=\"%scm\" height=\"%scm\" viewBox=\"0 0 %d %d\">\n"), NumStr(m_width / dpi * 2.54), NumStr(m_height / dpi * 2.54), m_width, m_height);
s += wxString::Format(wxS(" width=\"%scm\" height=\"%scm\" viewBox=\"0 0 %d %d\">\n"),
NumStr(m_width / dpi * 2.54), NumStr(m_height / dpi * 2.54), dpiSize.GetWidth(), dpiSize.GetHeight());
s += wxString::Format(wxS("<title>%s</title>\n"), title);
s += wxString(wxS("<desc>Picture generated by wxSVG ")) + wxSVGVersion + wxS("</desc>\n\n");
s += wxS("<g style=\"fill:black; stroke:black; stroke-width:1\">\n");
@ -597,12 +602,14 @@ wxSize wxSVGFileDCImpl::GetPPI() const
wxSize wxSVGFileDCImpl::FromDIP(const wxSize& sz) const
{
return sz;
const wxSize baseline = wxDisplay::GetStdPPI();
return wxRescaleCoord(sz).From(baseline).To(SVG_DPI);
}
wxSize wxSVGFileDCImpl::ToDIP(const wxSize& sz) const
{
return sz;
const wxSize baseline = wxDisplay::GetStdPPI();
return wxRescaleCoord(sz).From(SVG_DPI).To(baseline);
}
void wxSVGFileDCImpl::Clear()
@ -610,7 +617,8 @@ void wxSVGFileDCImpl::Clear()
{
wxDCBrushChanger setBackground(*GetOwner(), m_backgroundBrush);
wxDCPenChanger setTransp(*GetOwner(), *wxTRANSPARENT_PEN);
DoDrawRectangle(0, 0, m_width, m_height);
const wxSize dpiSize = FromDIP(wxSize(m_width, m_height));
DoDrawRectangle(0, 0, dpiSize.GetWidth(), dpiSize.GetHeight());
}
NewGraphicsIfNeeded();