[Git][wxwidgets/wxwidgets][master] 17 commits: CMake: Update cotire CMake minimum version to 3.5

1 view
Skip to first unread message

Vadim Zeitlin (@_VZ_)

unread,
Sep 14, 2025, 9:35:12 AMSep 14
to wx-commi...@googlegroups.com


Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets


Commits:
647b57f3 by Chris Mayo at 2025-09-09T19:49:55+01:00
CMake: Update cotire CMake minimum version to 3.5

- - - - -
47e132ec by Chris Mayo at 2025-09-09T19:49:55+01:00
CMake: Stop including CMakeParseArguments module

A placeholder for compatibility with CMake < 3.5.

- - - - -
5442b0c3 by Maarten Bent at 2025-09-09T21:45:37+02:00
Avoid using the style attribute in wxSVGFileDC

When an online SVG is opened in a browser, the browser might not want to process
the style attributes because there is no valid Content Security Policy (CSP).

Use the attributes directly inside the svg elements.
This passes the W3C validator, except for the 'white-space' attribute. So keep this one inside a style attribute.

- - - - -
04841732 by Maarten Bent at 2025-09-09T21:45:39+02:00
Use wxMemoryDC in wxSVGFileDC for text metrics

This replaces using the deprecated wxScreenDC, and seems to have the correct DPI for text metric calculations.

Fixes #25707

- - - - -
d9b94736 by Maarten Bent at 2025-09-09T21:45:40+02:00
Calculate bounding box in more wxSVGFileDC drawing functions

- - - - -
8b3df6ce by Maarten Bent at 2025-09-09T21:45:40+02:00
Remove incorrect FromDIP from wxSVGFileDC

Input for wxDC functions and constructor are in DPI-independent pixels, so no scaling should be performed.
This ensures the SVG will get the same size on every platform.

- - - - -
de938ccf by Maarten Bent at 2025-09-09T21:45:41+02:00
Update SVG header created by wxSVGFileDC

Use DOCTYPE of svg1.1.
Use the wxWidgets version instead of the wxSVGVersion version in the description.

- - - - -
83f6b2f2 by Maarten Bent at 2025-09-09T22:17:42+02:00
Allow to create a SVG in wxSVGFileDC with empty filename

This allows to render a SVG without writing it to a file, and can for example be useful to get the final size of the SVG.

Rename m_OK to m_writeError to better reflect its purpose.

Don't create the bitmap handler when it will not be used.

- - - - -
b80da783 by Vadim Zeitlin at 2025-09-13T15:41:57+02:00
Allow specifying initial contents of TestFile

This will be used in the next commit.

- - - - -
9886f14f by Vadim Zeitlin at 2025-09-13T15:42:13+02:00
Don't leave temporary files after running "Load" unit test

This test created temporary files but never deleted them.

Fix this by using TestFile helper class, which also simplifies the test
code.

- - - - -
8bf1d311 by Maarten Bent at 2025-09-14T14:23:19+02:00
Make svg sample DPI aware

Set the initial wxDC font so it will be the same across platforms.

- - - - -
15343900 by Maarten Bent at 2025-09-14T14:23:21+02:00
Use correct FromDIP in drawing sample

Use FromDIP of the wxDC, not the wxWindow.

- - - - -
700defdd by Maarten Bent at 2025-09-14T14:23:21+02:00
Save SVG files with the actual drawing size

First render to a temporary wxSVGFileDC, then use the size of the bounding box as input for the actual SVG size.
Use a slightly larger size to account for lines drawn with a bigger wxPen width.

- - - - -
656afd8c by Maarten Bent at 2025-09-14T14:23:22+02:00
Add and use a wxSVGFileDC constructor accepting wxSize

Add a constant for the default SVG dpi resolution.

- - - - -
7ed4c5ca by Maarten Bent at 2025-09-14T14:24:14+02:00
Move svg sample draw function to anonymous namespace

To prevent accidentally using (wxWindow::)FromDIP instead of dc.FromDIP().

- - - - -
ad4b3b18 by Vadim Zeitlin at 2025-09-14T15:03:05+02:00
Merge branch 'cmake4' of github.com:cjmayo/wxWidgets

Improve CMake 4 compatibility.

See #25781.

- - - - -
0e8fcfe8 by Vadim Zeitlin at 2025-09-14T15:05:21+02:00
Merge branch 'wxsvgfiledc-improvements' of github.com:MaartenBent/wxWidgets

Many wxSVGFileDC improvements:

- Avoid using the style attribute in the generated SVG because sometimes
browsers will not parse this when there is not Content Security
Policy.

- Try to fix text metric issues and differences between SVGs generated
when using X11 and Wayland by using wxMemoryDC instead of wxScreenDC.

- Fix incorrect FromDIP() usage in the samples.

- Update drawing and svg samples, save the SVG with full drawing size.

See #25723.

- - - - -


10 changed files:

- build/cmake/functions.cmake
- build/cmake/modules/cotire.cmake
- build/cmake/modules/cotire_test/CMakeLists.txt
- include/wx/dcsvg.h
- interface/wx/dcsvg.h
- samples/drawing/drawing.cpp
- samples/svg/svgtest.cpp
- src/common/dcsvg.cpp
- tests/misc/garbage.cpp
- tests/testfile.h


Changes:

=====================================
build/cmake/functions.cmake
=====================================
@@ -8,7 +8,6 @@
#############################################################################

include(CMakeDependentOption)
-include(CMakeParseArguments) # For compatibility with CMake < 3.4
include(ExternalProject)
include(CMakePrintHelpers)



=====================================
build/cmake/modules/cotire.cmake
=====================================
@@ -37,7 +37,7 @@ set(__COTIRE_INCLUDED TRUE)
if (NOT CMAKE_SCRIPT_MODE_FILE)
cmake_policy(PUSH)
endif()
-cmake_minimum_required(VERSION 2.8.12)
+cmake_minimum_required(VERSION 3.5)
if (NOT CMAKE_SCRIPT_MODE_FILE)
cmake_policy(POP)
endif()
@@ -111,7 +111,6 @@ if (POLICY CMP0055)
cmake_policy(SET CMP0055 NEW)
endif()

-include(CMakeParseArguments)
include(ProcessorCount)

function (cotire_get_configuration_types _configsVar)


=====================================
build/cmake/modules/cotire_test/CMakeLists.txt
=====================================
@@ -1,6 +1,6 @@
# cotire example project

-cmake_minimum_required(VERSION 2.8.12)
+cmake_minimum_required(VERSION 3.5)

if (POLICY CMP0058)
# Ninja requires custom command byproducts to be explicit
@@ -10,11 +10,8 @@ endif()
project (CotireExample)

set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/..")
-
-if (NOT CMAKE_VERSION VERSION_LESS "3.1.0")
- set (CMAKE_CXX_STANDARD "98")
- set (CMAKE_CXX_EXTENSIONS OFF)
-endif()
+set (CMAKE_CXX_STANDARD "98")
+set (CMAKE_CXX_EXTENSIONS OFF)

include(cotire)



=====================================
include/wx/dcsvg.h
=====================================
@@ -20,7 +20,10 @@

#include <memory>

+#if WXWIN_COMPATIBILITY_3_2
#define wxSVGVersion wxT("v0101")
+#endif
+constexpr double wxSVG_DEFAULT_DPI = 72.0;

enum wxSVGShapeRenderingMode
{
@@ -88,12 +91,12 @@ class WXDLLIMPEXP_CORE wxSVGFileDCImpl : public wxDCImpl
{
public:
wxSVGFileDCImpl(wxSVGFileDC* owner, const wxString& filename,
- int width = 320, int height = 240, double dpi = 72.0,
+ int width = 320, int height = 240, double dpi = wxSVG_DEFAULT_DPI,
const wxString& title = wxString());

virtual ~wxSVGFileDCImpl();

- bool IsOk() const override { return m_OK; }
+ bool IsOk() const override { return !m_writeError; }

virtual bool CanDrawBitmap() const override { return true; }
virtual bool CanGetTextExtent() const override { return true; }
@@ -269,7 +272,7 @@ private:
void DoStartNewGraphics();

wxString m_filename;
- bool m_OK;
+ bool m_writeError;
bool m_graphics_changed; // set by Set{Brush,Pen}()
int m_width, m_height;
double m_dpi;
@@ -299,12 +302,20 @@ public:
wxSVGFileDC(const wxString& filename,
int width = 320,
int height = 240,
- double dpi = 72.0,
+ double dpi = wxSVG_DEFAULT_DPI,
const wxString& title = wxString())
: wxDC(new wxSVGFileDCImpl(this, filename, width, height, dpi, title))
{
}

+ wxSVGFileDC(const wxSize size,
+ const wxString& filename = wxString(),
+ const wxString& title = wxString(),
+ double dpi = wxSVG_DEFAULT_DPI)
+ : wxDC(new wxSVGFileDCImpl(this, filename, size.x, size.y, dpi, title))
+ {
+ }
+
// wxSVGFileDC-specific methods:

// Use a custom bitmap handler: takes ownership of the handler.


=====================================
interface/wx/dcsvg.h
=====================================
@@ -21,6 +21,13 @@ enum wxSVGShapeRenderingMode
wxSVG_SHAPE_RENDERING_OPTIMISE_SPEED = wxSVG_SHAPE_RENDERING_OPTIMIZE_SPEED
};

+/**
+ Value indicating the default dpi resolution of wxSVGFileDC.
+
+ @since 3.3.2
+ */
+constexpr double wxSVG_DEFAULT_DPI = 72.0;
+

/**
@class wxSVGFileDC
@@ -59,10 +66,24 @@ public:
/**
Initializes a wxSVGFileDC with the given @a filename, @a width and
@a height at @a dpi resolution, and an optional @a title.
+
The title provides a readable name for the SVG document.
+ The filename is allowed to be empty, in which case no SVG file will be written.
*/
wxSVGFileDC(const wxString& filename, int width = 320, int height = 240,
- double dpi = 72, const wxString& title = wxString());
+ double dpi = wxSVG_DEFAULT_DPI, const wxString& title = wxString());
+
+ /**
+ Initializes a wxSVGFileDC with the given @a size, an optional @a filename,
+ an optional @a title, and an optional @a dpi resolution.
+
+ The title provides a readable name for the SVG document.
+ The filename is allowed to be empty, in which case no SVG file will be written.
+
+ @since 3.3.2
+ */
+ wxSVGFileDC(const wxSize size, const wxString& filename = wxString(),
+ const wxString& title = wxString(), double dpi = wxSVG_DEFAULT_DPI);

/**
Draws a rectangle the size of the SVG using the wxDC::SetBackground() brush.


=====================================
samples/drawing/drawing.cpp
=====================================
@@ -1806,7 +1806,7 @@ void MyCanvas::DrawSystemColours(wxDC& dc)
}

int lineHeight = textSize.GetHeight();
- wxCoord x(FromDIP(10));
+ wxCoord x(dc.FromDIP(10));
wxRect r(textSize.GetWidth() + x, x, dc.FromDIP(100), lineHeight);

dc.DrawText("System colours", x, r.y);
@@ -1895,7 +1895,7 @@ void MyCanvas::DrawDatabaseColours(wxDC& dc)
}

int lineHeight = textSize.GetHeight();
- wxCoord x(FromDIP(10));
+ wxCoord x(dc.FromDIP(10));
wxRect r(textSize.GetWidth() + x, x, dc.FromDIP(100), lineHeight);

wxString title = "wxColourDatabase colours";
@@ -1971,7 +1971,7 @@ void MyCanvas::DrawCursors(wxDC& dc)
constexpr int stockNamesCount = WXSIZEOF(stockNames);
m_cursorRects.resize(stockNamesCount);

- wxCoord x(FromDIP(10));
+ wxCoord x(dc.FromDIP(10));
wxCoord y = x;

dc.SetBackgroundMode(wxTRANSPARENT);
@@ -1980,7 +1980,7 @@ void MyCanvas::DrawCursors(wxDC& dc)
wxSystemSettings::GetMetric(wxSYS_CURSOR_Y, this)),
x, y);

- const int w = FromDIP(200);
+ const int w = dc.FromDIP(200);
const int h = wxSystemSettings::GetMetric(wxSYS_CURSOR_Y, this);
const int margin = dc.GetCharWidth();

@@ -2790,13 +2790,16 @@ void MyFrame::OnSave(wxCommandEvent& WXUNUSED(event))
wxGraphicsRenderer* tempRenderer = m_canvas->GetRenderer();
m_canvas->UseGraphicRenderer(nullptr);
#endif
- wxSVGFileDC svgdc(dlg.GetPath(),
- canvasSize.GetWidth(),
- canvasSize.GetHeight(),
- 72,
- "Drawing sample");
- svgdc.SetBitmapHandler(new wxSVGBitmapEmbedHandler());
- m_canvas->Draw(svgdc);
+ wxSize svgSize;
+ wxSVGFileDC tempSvgDC(svgSize);
+ m_canvas->Draw(tempSvgDC);
+
+ svgSize = wxSize(tempSvgDC.MaxX(), tempSvgDC.MaxY());
+ svgSize.IncBy(15); // account for wxPen width exceeding bounds
+
+ wxSVGFileDC svgDC(svgSize, dlg.GetPath(), "Drawing sample");
+ svgDC.SetBitmapHandler(new wxSVGBitmapEmbedHandler());
+ m_canvas->Draw(svgDC);
#if wxUSE_GRAPHICS_CONTEXT
m_canvas->UseGraphicRenderer(tempRenderer);
#endif


=====================================
samples/svg/svgtest.cpp
=====================================
@@ -92,7 +92,7 @@ class MyPage : public wxScrolledWindow
public:
MyPage(wxNotebook *parent, int index);
virtual void OnDraw(wxDC& dc) override;
- bool OnSave(wxString);
+ bool OnSave(const wxString& filename);
private:
int m_index;
};
@@ -100,8 +100,7 @@ private:
class MyFrame : public wxFrame
{
public:
- MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
- const wxPoint& pos, const wxSize& size);
+ MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title);

void FileSavePicture(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
@@ -136,9 +135,8 @@ bool MyApp::OnInit()
{
// Create the main frame window

- MyFrame* frame = new MyFrame(nullptr, -1, "SVG Demo",
- wxDefaultPosition, wxSize(500, 400));
-
+ MyFrame* frame = new MyFrame(nullptr, -1, "SVG Demo");
+ frame->SetSize(frame->FromDIP(wxSize(600, 500)));
frame->Show(true);

return true;
@@ -150,15 +148,14 @@ bool MyApp::OnInit()

// Define my frame constructor

-MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
- const wxPoint& pos, const wxSize& size)
- : wxFrame(parent, id, title, pos, size)
+MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title)
+ : wxFrame(parent, id, title)
{
SetIcon(wxICON(sample));

- #if wxUSE_STATUSBAR
+#if wxUSE_STATUSBAR
CreateStatusBar();
- #endif // wxUSE_STATUSBAR
+#endif // wxUSE_STATUSBAR

// Make a menubar
wxMenu *file_menu = new wxMenu;
@@ -184,7 +181,6 @@ MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
for (int i = 0; i < Page_Max; ++i)
{
m_notebook->AddPage(new MyPage(m_notebook, i), pageNames[i]);
-
}
}

@@ -230,129 +226,142 @@ void MyFrame::FileSavePicture(wxCommandEvent& WXUNUSED(event))

// Define a constructor for my page
MyPage::MyPage(wxNotebook *parent, int index)
- : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL|wxHSCROLL)
+ : wxScrolledWindow(parent)
{
SetBackgroundColour(*wxWHITE);
SetScrollbars(20, 20, 50, 50);
m_index = index;
}

-bool MyPage::OnSave(wxString filename)
+bool MyPage::OnSave(const wxString& filename)
{
- wxSVGFileDC svgDC (filename, 600, 650);
- OnDraw (svgDC);
+ wxSize svgSize;
+ wxSVGFileDC tempSvgDC(svgSize);
+ OnDraw(tempSvgDC);
+
+ svgSize = wxSize(tempSvgDC.MaxX(), tempSvgDC.MaxY());
+ svgSize.IncBy(15); // account for wxPen width exceeding bounds
+
+ wxSVGFileDC svgDC(svgSize, filename, pageNames[m_index]);
+ svgDC.SetBitmapHandler(new wxSVGBitmapEmbedHandler());
+ OnDraw(svgDC);
+
return svgDC.IsOk();
}

-// Define the repainting behaviour
-void MyPage::OnDraw(wxDC& dc)
+namespace
+{
+
+// Define this function in an anonymous namespace, to prevent accidentally
+// using (wxWindow::)FromDIP instead of dc.FromDIP().
+void DrawOnDC(wxDC& dc, const int index)
{
- // vars to use ...
+ // vars to use ...
wxPen wP;
wxBrush wB;
wxPoint points[6];
wxColour wC;

- dc.SetFont(*wxSWISS_FONT);
+ dc.SetFont(wxFontInfo(9).FaceName("Arial").Family(wxFONTFAMILY_SWISS));
dc.SetPen(*wxGREEN_PEN);

- switch (m_index)
+ switch (index)
{
case Page_Lines:
// draw lines to make a cross
- dc.DrawLine(0, 0, 200, 200);
- dc.DrawLine(200, 0, 0, 200);
+ dc.DrawLine(dc.FromDIP(0), dc.FromDIP(0), dc.FromDIP(200), dc.FromDIP(200));
+ dc.DrawLine(dc.FromDIP(200), dc.FromDIP(0), dc.FromDIP(0), dc.FromDIP(200));
// draw point colored line and spline
wP = *wxCYAN_PEN;
wP.SetWidth(3);
dc.SetPen(wP);

- dc.DrawPoint (25,15);
- dc.DrawLine(50, 30, 200, 30);
- dc.DrawSpline(50, 200, 50, 100, 200, 10);
+ dc.DrawPoint(dc.FromDIP(25), dc.FromDIP(15));
+ dc.DrawLine(dc.FromDIP(50), dc.FromDIP(30), dc.FromDIP(200), dc.FromDIP(30));
+ dc.DrawSpline(dc.FromDIP(50), dc.FromDIP(200), dc.FromDIP(50), dc.FromDIP(100), dc.FromDIP(200), dc.FromDIP(10));
break;

case Page_Polygons:
// draw standard shapes
dc.SetBrush(*wxCYAN_BRUSH);
dc.SetPen(*wxRED_PEN);
- dc.DrawRectangle(10, 10, 100, 70);
+ dc.DrawRectangle(dc.FromDIP(10), dc.FromDIP(10), dc.FromDIP(100), dc.FromDIP(70));
wB = wxBrush ("DARK ORCHID", wxBRUSHSTYLE_TRANSPARENT);
dc.SetBrush (wB);
- dc.DrawRoundedRectangle(50, 50, 100, 70, 20);
+ dc.DrawRoundedRectangle(dc.FromDIP(50), dc.FromDIP(50), dc.FromDIP(100), dc.FromDIP(70), dc.FromDIP(20));
dc.SetBrush (wxBrush("GOLDENROD") );
- dc.DrawEllipse(100, 100, 100, 50);
+ dc.DrawEllipse(dc.FromDIP(100), dc.FromDIP(100), dc.FromDIP(100), dc.FromDIP(50));

- points[0].x = 100; points[0].y = 200;
- points[1].x = 70; points[1].y = 260;
- points[2].x = 160; points[2].y = 230;
- points[3].x = 40; points[3].y = 230;
- points[4].x = 130; points[4].y = 260;
- points[5].x = 100; points[5].y = 200;
+ points[0].x = dc.FromDIP(100); points[0].y = dc.FromDIP(200);
+ points[1].x = dc.FromDIP(70); points[1].y = dc.FromDIP(260);
+ points[2].x = dc.FromDIP(160); points[2].y = dc.FromDIP(230);
+ points[3].x = dc.FromDIP(40); points[3].y = dc.FromDIP(230);
+ points[4].x = dc.FromDIP(130); points[4].y = dc.FromDIP(260);
+ points[5].x = dc.FromDIP(100); points[5].y = dc.FromDIP(200);

dc.DrawPolygon(5, points);
- dc.DrawLines (6, points, 160);
+ dc.DrawLines(6, points, dc.FromDIP(160));
break;

case Page_Text:
// draw text in Arial or similar font
- dc.DrawLine(50,25,50,35);
- dc.DrawLine(45,30,55,30);
- dc.DrawText("This is a Swiss-style string", 50, 30);
+ dc.DrawLine(dc.FromDIP(50), dc.FromDIP(25), dc.FromDIP(50), dc.FromDIP(35));
+ dc.DrawLine(dc.FromDIP(45), dc.FromDIP(30), dc.FromDIP(55), dc.FromDIP(30));
+ dc.DrawText("This is a Swiss-style string", dc.FromDIP(50), dc.FromDIP(30));
wC = dc.GetTextForeground();
dc.SetTextForeground ("FIREBRICK");

// no effect in msw ??
dc.SetTextBackground ("WHEAT");
- dc.DrawText("This is a Red string", 50, 200);
- dc.DrawRotatedText("This is a 45 deg string", 50, 200, 45);
- dc.DrawRotatedText("This is a 90 deg string", 50, 200, 90);
+ dc.DrawText("This is a Red string", dc.FromDIP(50), dc.FromDIP(200));
+ dc.DrawRotatedText("This is a 45 deg string", dc.FromDIP(50), dc.FromDIP(200), 45);
+ dc.DrawRotatedText("This is a 90 deg string", dc.FromDIP(50), dc.FromDIP(200), 90);
dc.SetFont(wxFontInfo(18)
.FaceName("Times New Roman")
.Family(wxFONTFAMILY_ROMAN)
.Italic().Bold());
dc.SetTextForeground (wC);
- dc.DrawText("This is a Times-style string", 50, 60);
+ dc.DrawText("This is a Times-style string", dc.FromDIP(50), dc.FromDIP(60));
break;

case Page_Arcs:
// four arcs start and end points, center
dc.SetBrush(*wxGREEN_BRUSH);
- dc.DrawArc ( 200,300, 370,230, 300,300 );
+ dc.DrawArc(dc.FromDIP(200), dc.FromDIP(300), dc.FromDIP(370), dc.FromDIP(230), dc.FromDIP(300), dc.FromDIP(300));
dc.SetBrush(*wxBLUE_BRUSH);
- dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270,270 );
+ dc.DrawArc(dc.FromDIP(270 - 50), dc.FromDIP(270 - 86), dc.FromDIP(270 - 86), dc.FromDIP(270 - 50), dc.FromDIP(270), dc.FromDIP(270));
dc.SetDeviceOrigin(-10,-10);
- dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270,270 );
+ dc.DrawArc(dc.FromDIP(270 - 50), dc.FromDIP(270 - 86), dc.FromDIP(270 - 86), dc.FromDIP(270 - 50), dc.FromDIP(270), dc.FromDIP(270));
dc.SetDeviceOrigin(0,0);

wP.SetColour ("CADET BLUE");
dc.SetPen(wP);
- dc.DrawArc ( 75,125, 110, 40, 75, 75 );
+ dc.DrawArc(dc.FromDIP(75), dc.FromDIP(125), dc.FromDIP(110), dc.FromDIP(40), dc.FromDIP(75), dc.FromDIP(75));

wP.SetColour ("SALMON");
dc.SetPen(wP);
dc.SetBrush(*wxRED_BRUSH);
//top left corner, width and height, start and end angle
// 315 same center and x-radius as last pie-arc, half Y radius
- dc.DrawEllipticArc(25,50,100,50,180.0,45.0);
+ dc.DrawEllipticArc(dc.FromDIP(25), dc.FromDIP(50), dc.FromDIP(100), dc.FromDIP(50), 180.0, 45.0);

wP = *wxCYAN_PEN;
wP.SetWidth(3);
dc.SetPen(wP);
//wxBRUSHSTYLE_TRANSPARENT));
dc.SetBrush (wxBrush ("SALMON"));
- dc.DrawEllipticArc(300, 0,200,100, 0.0,145.0);
+ dc.DrawEllipticArc(dc.FromDIP(300), dc.FromDIP(0), dc.FromDIP(200), dc.FromDIP(100), 0.0, 145.0);
//same end point
- dc.DrawEllipticArc(300, 50,200,100,90.0,145.0);
- dc.DrawEllipticArc(300,100,200,100,90.0,345.0);
+ dc.DrawEllipticArc(dc.FromDIP(300), dc.FromDIP(50), dc.FromDIP(200), dc.FromDIP(100), 90.0, 145.0);
+ dc.DrawEllipticArc(dc.FromDIP(300), dc.FromDIP(100), dc.FromDIP(200), dc.FromDIP(100), 90.0, 345.0);

break;

case Page_Checkmarks:
- dc.DrawCheckMark ( 30,30,25,25);
+ dc.DrawCheckMark(dc.FromDIP(30), dc.FromDIP(30), dc.FromDIP(25), dc.FromDIP(25));
dc.SetBrush (wxBrush ("SALMON",wxBRUSHSTYLE_TRANSPARENT));
- dc.DrawCheckMark ( 80,50,75,75);
- dc.DrawRectangle ( 80,50,75,75);
+ dc.DrawCheckMark(dc.FromDIP(80), dc.FromDIP(50), dc.FromDIP(75), dc.FromDIP(75));
+ dc.DrawRectangle(dc.FromDIP(80), dc.FromDIP(50), dc.FromDIP(75), dc.FromDIP(75));
break;

case Page_ScaledText:
@@ -360,74 +369,74 @@ void MyPage::OnDraw(wxDC& dc)
.FaceName("Times New Roman")
.Family(wxFONTFAMILY_ROMAN)
.Italic().Bold());
- dc.DrawLine(0, 0, 200, 200);
- dc.DrawLine(200, 0, 0, 200);
- dc.DrawText("This is an 18pt string", 50, 60);
+ dc.DrawLine(dc.FromDIP(0), dc.FromDIP(0), dc.FromDIP(200), dc.FromDIP(200));
+ dc.DrawLine(dc.FromDIP(200), dc.FromDIP(0), dc.FromDIP(0), dc.FromDIP(200));
+ dc.DrawText("This is an 18pt string", dc.FromDIP(50), dc.FromDIP(60));

// rescale and draw in blue
wP = *wxCYAN_PEN;
dc.SetPen(wP);
dc.SetUserScale (2.0,0.5);
- dc.SetDeviceOrigin(200,0);
- dc.DrawLine(0, 0, 200, 200);
- dc.DrawLine(200, 0, 0, 200);
- dc.DrawText("This is an 18pt string 2 x 0.5 UserScaled", 50, 60);
+ dc.SetDeviceOrigin(dc.FromDIP(200), dc.FromDIP(0));
+ dc.DrawLine(dc.FromDIP(0), dc.FromDIP(0), dc.FromDIP(200), dc.FromDIP(200));
+ dc.DrawLine(dc.FromDIP(200), dc.FromDIP(0), dc.FromDIP(0), dc.FromDIP(200));
+ dc.DrawText("This is an 18pt string 2 x 0.5 UserScaled", dc.FromDIP(50), dc.FromDIP(60));
dc.SetUserScale (2.0,2.0);
- dc.SetDeviceOrigin(200,200);
- dc.DrawText("This is an 18pt string 2 x 2 UserScaled", 50, 60);
+ dc.SetDeviceOrigin(dc.FromDIP(200), dc.FromDIP(200));
+ dc.DrawText("This is an 18pt string 2 x 2 UserScaled", dc.FromDIP(50), dc.FromDIP(60));

wP = *wxRED_PEN;
dc.SetPen(wP);
dc.SetUserScale (1.0,1.0);
- dc.SetDeviceOrigin(0,10);
+ dc.SetDeviceOrigin(dc.FromDIP(0), dc.FromDIP(10));
dc.SetMapMode (wxMM_METRIC); //svg ignores this
- dc.DrawLine(0, 0, 200, 200);
- dc.DrawLine(200, 0, 0, 200);
- dc.DrawText("This is an 18pt string in MapMode", 50, 60);
+ dc.DrawLine(dc.FromDIP(0), dc.FromDIP(0), dc.FromDIP(200), dc.FromDIP(200));
+ dc.DrawLine(dc.FromDIP(200), dc.FromDIP(0), dc.FromDIP(0), dc.FromDIP(200));
+ dc.DrawText("This is an 18pt string in MapMode", dc.FromDIP(50), dc.FromDIP(60));
break;

case Page_Bitmaps:
- dc.DrawIcon( wxICON(sample), 10, 10 );
- dc.DrawBitmap ( wxBitmap(svgbitmap_xpm), 50,15);
+ dc.DrawIcon(wxICON(sample), dc.FromDIP(10), dc.FromDIP(10));
+ dc.DrawBitmap(wxBitmap(svgbitmap_xpm), dc.FromDIP(50), dc.FromDIP(15));
break;

case Page_Clipping:
dc.SetTextForeground("RED");
- dc.DrawText("Red = Clipping Off", 30, 5);
+ dc.DrawText("Red = Clipping Off", dc.FromDIP(30), dc.FromDIP(5));
dc.SetTextForeground("GREEN");
- dc.DrawText("Green = Clipping On", 30, 25);
+ dc.DrawText("Green = Clipping On", dc.FromDIP(30), dc.FromDIP(25));

dc.SetTextForeground("BLACK");

dc.SetPen(*wxRED_PEN);
dc.SetBrush (wxBrush ("SALMON",wxBRUSHSTYLE_TRANSPARENT));
- dc.DrawCheckMark ( 80,50,75,75);
- dc.DrawRectangle ( 80,50,75,75);
+ dc.DrawCheckMark(dc.FromDIP(80), dc.FromDIP(50), dc.FromDIP(75), dc.FromDIP(75));
+ dc.DrawRectangle(dc.FromDIP(80), dc.FromDIP(50), dc.FromDIP(75), dc.FromDIP(75));

dc.SetPen(*wxGREEN_PEN);

// Clipped checkmarks
- dc.DrawRectangle(180,50,75,75);
- dc.SetClippingRegion(180,50,75,75); // x,y,width,height version
- dc.DrawCheckMark ( 180,50,75,75);
+ dc.DrawRectangle(dc.FromDIP(180), dc.FromDIP(50), dc.FromDIP(75), dc.FromDIP(75));
+ dc.SetClippingRegion(dc.FromDIP(180), dc.FromDIP(50), dc.FromDIP(75), dc.FromDIP(75)); // x,y,width,height version
+ dc.DrawCheckMark(dc.FromDIP(180), dc.FromDIP(50), dc.FromDIP(75), dc.FromDIP(75));
dc.DestroyClippingRegion();

- dc.DrawRectangle(wxRect(80,150,75,75));
- dc.SetClippingRegion(wxPoint(80,150),wxSize(75,75)); // pt,size version
- dc.DrawCheckMark ( 80,150,75,75);
+ dc.DrawRectangle(wxRect(dc.FromDIP(wxPoint(80, 150)), dc.FromDIP(wxSize(75, 75))));
+ dc.SetClippingRegion(dc.FromDIP(wxPoint(80, 150)), dc.FromDIP(wxSize(75, 75))); // pt,size version
+ dc.DrawCheckMark(dc.FromDIP(80), dc.FromDIP(150), dc.FromDIP(75), dc.FromDIP(75));
dc.DestroyClippingRegion();

- dc.DrawRectangle(wxRect(180,150,75,75));
- dc.SetClippingRegion(wxRect(180,150,75,75)); // rect version
- dc.DrawCheckMark ( 180,150,75,75);
+ dc.DrawRectangle(wxRect(dc.FromDIP(wxPoint(180, 150)), dc.FromDIP(wxSize(75, 75))));
+ dc.SetClippingRegion(wxRect(dc.FromDIP(wxPoint(180, 150)), dc.FromDIP(wxSize(75, 75)))); // rect version
+ dc.DrawCheckMark(dc.FromDIP(180), dc.FromDIP(150), dc.FromDIP(75), dc.FromDIP(75));
dc.DestroyClippingRegion();

- dc.DrawRectangle(wxRect( 80,250,50,65));
- dc.DrawRectangle(wxRect(105,260,50,65));
- dc.SetClippingRegion(wxRect( 80,250,50,65)); // second call to SetClippingRegion
- dc.SetClippingRegion(wxRect(105,260,50,65)); // forms intersection with previous
- dc.DrawCheckMark(80,250,75,75);
- dc.DestroyClippingRegion(); // only one call to destroy (there's no stack)
+ dc.DrawRectangle(wxRect(dc.FromDIP(wxPoint(80, 250)), dc.FromDIP(wxSize(50, 65))));
+ dc.DrawRectangle(wxRect(dc.FromDIP(wxPoint(105, 260)), dc.FromDIP(wxSize(50, 65))));
+ dc.SetClippingRegion(wxRect(dc.FromDIP(wxPoint(80, 250)), dc.FromDIP(wxSize(50, 65)))); // second call to SetClippingRegion
+ dc.SetClippingRegion(wxRect(dc.FromDIP(wxPoint(105, 260)), dc.FromDIP(wxSize(50, 65)))); // forms intersection with previous
+ dc.DrawCheckMark(dc.FromDIP(80), dc.FromDIP(250), dc.FromDIP(75), dc.FromDIP(75));
+ dc.DestroyClippingRegion(); // only one call to destroy (there's no stack)

/*
** Clipping by wxRegion not implemented for SVG. Should be
@@ -463,16 +472,16 @@ void MyPage::OnDraw(wxDC& dc)
// Horizontal text
txtStr = "Horizontal string";
dc.GetTextExtent(txtStr, &txtW, &txtH, &txtDescent, &txtEL);
- txtX = 50;
- txtY = 300;
+ txtX = dc.FromDIP(50);
+ txtY = dc.FromDIP(200);
dc.DrawRectangle(txtX, txtY, txtW + 2*txtPad, txtH + 2*txtPad);
dc.DrawText(txtStr, txtX + txtPad, txtY + txtPad);

// Vertical text
txtStr = "Vertical string";
dc.GetTextExtent(txtStr, &txtW, &txtH, &txtDescent, &txtEL);
- txtX = 50;
- txtY = 250;
+ txtX = dc.FromDIP(50);
+ txtY = dc.FromDIP(150);
dc.DrawRectangle(txtX, txtY - (txtW + 2*txtPad), txtH + 2*txtPad, txtW + 2*txtPad);
dc.DrawRotatedText(txtStr, txtX + txtPad, txtY - txtPad, 90);

@@ -482,8 +491,8 @@ void MyPage::OnDraw(wxDC& dc)
double lenW = (double)(txtW + 2*txtPad) / sqrt(2.0);
double lenH = (double)(txtH + 2*txtPad) / sqrt(2.0);
double padding = (double)txtPad / sqrt(2.0);
- txtX = 150;
- txtY = 200;
+ txtX = dc.FromDIP(150);
+ txtY = dc.FromDIP(100);
dc.DrawLine(txtX - int(padding), txtY, txtX + int(lenW), txtY - int(lenW)); // top
dc.DrawLine(txtX + int(lenW), txtY - int(lenW), txtX - int(padding + lenH + lenW), txtY + int(lenH - lenW));
dc.DrawLine(txtX - int(padding), txtY, txtX - int(padding + lenH), txtY + int(lenH));
@@ -491,7 +500,14 @@ void MyPage::OnDraw(wxDC& dc)
dc.DrawRotatedText(txtStr, txtX, txtY, 45);
break;
}
-
- wxLogStatus(pageDescriptions[m_index]);
}

+} // namespace
+
+// Define the repainting behaviour
+void MyPage::OnDraw(wxDC& dc)
+{
+ DrawOnDC(dc, m_index);
+
+ wxLogStatus(pageDescriptions[m_index]);
+}


=====================================
src/common/dcsvg.cpp
=====================================
@@ -13,7 +13,6 @@

#ifndef WX_PRECOMP
#include "wx/dcmemory.h"
- #include "wx/dcscreen.h"
#include "wx/icon.h"
#include "wx/image.h"
#include "wx/math.h"
@@ -25,7 +24,6 @@
#include "wx/filename.h"
#include "wx/mstream.h"
#include "wx/scopedarray.h"
-#include "wx/display.h"
#include "wx/private/rescale.h"

#if wxUSE_MARKUP
@@ -86,7 +84,7 @@ wxString Col2SVG(wxColour c, float* opacity = nullptr)
wxString GetPenStroke(const wxColour& c, int style = wxPENSTYLE_SOLID)
{
float opacity;
- wxString s = wxS("stroke:") + Col2SVG(c, &opacity) + wxS(";");
+ wxString s = wxString::Format(wxS("stroke=\"%s\""), Col2SVG(c, &opacity));

switch ( style )
{
@@ -96,10 +94,10 @@ wxString GetPenStroke(const wxColour& c, int style = wxPENSTYLE_SOLID)
case wxPENSTYLE_LONG_DASH:
case wxPENSTYLE_DOT_DASH:
case wxPENSTYLE_USER_DASH:
- s += wxString::Format(wxS(" stroke-opacity:%s;"), NumStr(opacity));
+ s += wxString::Format(wxS(" stroke-opacity=\"%s\""), NumStr(opacity));
break;
case wxPENSTYLE_TRANSPARENT:
- s += wxS(" stroke-opacity:0.0;");
+ s += wxS(" stroke-opacity=\"0.0\"");
break;
default:
wxASSERT_MSG(false, wxS("wxSVGFileDC::Requested Pen Style not available"));
@@ -112,7 +110,7 @@ wxString GetPenStroke(const wxColour& c, int style = wxPENSTYLE_SOLID)
wxString GetBrushFill(const wxColour& c, int style = wxBRUSHSTYLE_SOLID)
{
float opacity;
- wxString s = wxS("fill:") + Col2SVG(c, &opacity) + wxS(";");
+ wxString s = wxString::Format(wxS("fill=\"%s\""), Col2SVG(c, &opacity));

switch ( style )
{
@@ -123,10 +121,10 @@ wxString GetBrushFill(const wxColour& c, int style = wxBRUSHSTYLE_SOLID)
case wxBRUSHSTYLE_CROSS_HATCH:
case wxBRUSHSTYLE_VERTICAL_HATCH:
case wxBRUSHSTYLE_HORIZONTAL_HATCH:
- s += wxString::Format(wxS(" fill-opacity:%s;"), NumStr(opacity));
+ s += wxString::Format(wxS(" fill-opacity=\"%s\""), NumStr(opacity));
break;
case wxBRUSHSTYLE_TRANSPARENT:
- s += wxS(" fill-opacity:0.0;");
+ s += wxS(" fill-opacity=\"0.0\"");
break;
default:
wxASSERT_MSG(false, wxS("wxSVGFileDC::Requested Brush Style not available"));
@@ -175,7 +173,7 @@ wxString GetPenPattern(const wxPen& pen)
{
s << dashes[i];
if (i < count - 1)
- s << ",";
+ s << wxS(",");
}
}
s += wxS("\"");
@@ -205,33 +203,33 @@ wxString GetPenStyle(const wxPen& pen)
{
wxString penStyle;

- penStyle += wxString::Format(wxS("stroke-width:%d;"), pen.GetWidth());
+ penStyle += wxString::Format(wxS("stroke-width=\"%d\""), pen.GetWidth());

switch (pen.GetCap())
{
case wxCAP_PROJECTING:
- penStyle += wxS(" stroke-linecap:square;");
+ penStyle += wxS(" stroke-linecap=\"square\"");
break;
case wxCAP_BUTT:
- penStyle += wxS(" stroke-linecap:butt;");
+ penStyle += wxS(" stroke-linecap=\"butt\"");
break;
case wxCAP_ROUND:
default:
- penStyle += wxS(" stroke-linecap:round;");
+ penStyle += wxS(" stroke-linecap=\"round\"");
break;
}

switch (pen.GetJoin())
{
case wxJOIN_BEVEL:
- penStyle += wxS(" stroke-linejoin:bevel;");
+ penStyle += wxS(" stroke-linejoin=\"bevel\"");
break;
case wxJOIN_MITER:
- penStyle += wxS(" stroke-linejoin:miter;");
+ penStyle += wxS(" stroke-linejoin=\"miter\"");
break;
case wxJOIN_ROUND:
default:
- penStyle += wxS(" stroke-linejoin:round;");
+ penStyle += wxS(" stroke-linejoin=\"round\"");
break;
}

@@ -348,11 +346,11 @@ wxString CreateBrushFill(const wxBrush& brush, wxSVGShapeRenderingMode mode)

float opacity;
wxString brushColourStr = Col2SVG(brush.GetColour(), &opacity);
- wxString brushStrokeStr = wxS("stroke-width:1; stroke-linecap:round; stroke-linejoin:round;");
+ wxString brushStrokeStr = wxS("stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\"");

s += wxString::Format(wxS(" <pattern id=\"%s\" patternUnits=\"userSpaceOnUse\" width=\"8\" height=\"8\">\n"),
patternName);
- s += wxString::Format(wxS(" <path style=\"stroke:%s; stroke-opacity:%s; %s\" %s %s/>\n"),
+ s += wxString::Format(wxS(" <path stroke=\"%s\" stroke-opacity=\"%s\" %s %s %s/>\n"),
brushColourStr, NumStr(opacity), brushStrokeStr, pattern, GetRenderMode(mode));
s += wxS(" </pattern>\n");
}
@@ -360,31 +358,28 @@ wxString CreateBrushFill(const wxBrush& brush, wxSVGShapeRenderingMode mode)
return s;
}

-void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font)
+wxMemoryDC GetTextMetricDC(const wxFont& font)
{
- const double screenDPI = sDC.GetPPI().y;
- const double scale = screenDPI / SVG_DPI.y;
+ wxMemoryDC dc;
+ const double dcDPI = dc.GetPPI().y;
+ const double scale = dcDPI / 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.)
+ // The SVG is DPI-independent so we want text metrics for the default (96) DPI.
//
// 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.
wxFont scaledFont = font;
scaledFont.SetFractionalPointSize(scaledFont.GetFractionalPointSize() / scale);
- sDC.SetFont(scaledFont);
+ dc.SetFont(scaledFont);
}
else
{
- sDC.SetFont(font);
+ dc.SetFont(font);
}
+
+ return dc;
}

} // anonymous namespace
@@ -527,15 +522,15 @@ void wxSVGFileDCImpl::Init(const wxString& filename, int width, int height,

m_dpi = dpi;

- m_OK = true;
+ m_writeError = false;

m_clipUniqueId = 0;
m_clipNestingLevel = 0;

m_gradientUniqueId = 0;

- m_mm_to_pix_x = dpi / 25.4;
- m_mm_to_pix_y = dpi / 25.4;
+ m_mm_to_pix_x = m_dpi / 25.4;
+ m_mm_to_pix_y = m_dpi / 25.4;

m_backgroundBrush = *wxTRANSPARENT_BRUSH;
m_textForegroundColour = *wxBLACK;
@@ -559,17 +554,15 @@ 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("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.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), dpiSize.GetWidth(), dpiSize.GetHeight());
+ NumStr(m_width / m_dpi * 2.54), NumStr(m_height / m_dpi * 2.54), m_width, m_height);
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");
+ s += wxString::Format(wxS("<desc>Created with %s</desc>\n\n"), wxVERSION_STRING);
+ s += wxS("<g fill=\"black\" stroke=\"black\" stroke-width=\"1\">\n");
write(s);
}

@@ -601,14 +594,12 @@ wxSize wxSVGFileDCImpl::GetPPI() const

wxSize wxSVGFileDCImpl::FromDIP(const wxSize& sz) const
{
- const wxSize baseline = wxDisplay::GetStdPPI();
- return wxRescaleCoord(sz).From(baseline).To(SVG_DPI);
+ return sz;
}

wxSize wxSVGFileDCImpl::ToDIP(const wxSize& sz) const
{
- const wxSize baseline = wxDisplay::GetStdPPI();
- return wxRescaleCoord(sz).From(SVG_DPI).To(baseline);
+ return sz;
}

void wxSVGFileDCImpl::Clear()
@@ -616,8 +607,7 @@ void wxSVGFileDCImpl::Clear()
{
wxDCBrushChanger setBackground(*GetOwner(), m_backgroundBrush);
wxDCPenChanger setTransp(*GetOwner(), *wxTRANSPARENT_PEN);
- const wxSize dpiSize = FromDIP(wxSize(m_width, m_height));
- DoDrawRectangle(0, 0, dpiSize.GetWidth(), dpiSize.GetHeight());
+ DoDrawRectangle(0, 0, m_width, m_height);
}

NewGraphicsIfNeeded();
@@ -657,7 +647,7 @@ void wxSVGFileDCImpl::DoDrawLines(int n, const wxPoint points[], wxCoord xoffset
CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
}

- s += wxString::Format(wxS("\" style=\"fill:none\" %s %s/>\n"),
+ s += wxString::Format(wxS("\" fill=\"none\" %s %s/>\n"),
GetRenderMode(m_renderingMode), GetPenPattern(m_pen));

write(s);
@@ -716,7 +706,7 @@ void wxSVGFileDCImpl::DoDrawSpline(const wxPointList* points)
if ( AreAutomaticBoundingBoxUpdatesEnabled() )
CalcBoundingBox(wxRound(p2.m_x), wxRound(p2.m_y));

- s += wxString::Format("\" style=\"fill:none\" %s %s/>\n",
+ s += wxString::Format("\" fill=\"none\" %s %s/>\n",
GetRenderMode(m_renderingMode), GetPenPattern(m_pen));
write(s);
}
@@ -728,7 +718,7 @@ void wxSVGFileDCImpl::DoDrawPoint(wxCoord x, wxCoord y)

wxString s;

- s = wxS(" <g style=\"stroke-width:1; stroke-linecap:round;\">\n ");
+ s = wxS(" <g stroke-width=\"1\" stroke-linecap=\"round\">\n ");
write(s);

DoDrawLine(x, y, x, y);
@@ -792,21 +782,20 @@ void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoor
if (textDecoration.empty())
textDecoration = wxS(" none");

- wxString style = wxS("style=\"");
- style += wxString::Format(wxS("font-family:%s; "), m_font.GetFaceName());
- style += wxString::Format(wxS("font-weight:%d; "), m_font.GetWeight());
- style += wxString::Format(wxS("font-style:%s; "), fontstyle);
- style += wxString::Format(wxS("font-size:%spt; "), NumStr(m_font.GetFractionalPointSize()));
- style += wxString::Format(wxS("text-decoration:%s; "), textDecoration);
- style += wxString::Format(wxS("%s %s stroke-width:0; "),
+ wxString style;
+ style += wxString::Format(wxS("font-family=\"%s\" "), m_font.GetFaceName());
+ style += wxString::Format(wxS("font-weight=\"%d\" "), m_font.GetWeight());
+ style += wxString::Format(wxS("font-style=\"%s\" "), fontstyle);
+ style += wxString::Format(wxS("font-size=\"%spt\" "), NumStr(m_font.GetFractionalPointSize()));
+ style += wxString::Format(wxS("text-decoration=\"%s\" "), textDecoration);
+ style += wxString::Format(wxS("%s %s stroke-width=\"0\" "),
GetBrushFill(m_textForegroundColour),
GetPenStroke(m_textForegroundColour));
- style += wxS("white-space: pre;");
- style += wxS("\"");

- // this is deprecated in favour of "white-space: pre", keep it for now to
+ // "xml:space" is deprecated in favour of "white-space: pre", keep it for now to
// support SVG viewers that do not support the new tag
- style += wxS(" xml:space=\"preserve\"");
+ style += wxS("xml:space=\"preserve\" ");
+ style += wxS("style=\"white-space: pre;\" ");

// Draw all text line by line
const wxArrayString lines = wxSplit(sText, '\n', '\0');
@@ -826,7 +815,7 @@ void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoor
{
// draw text background
const wxString rectStyle = wxString::Format(
- wxS("style=\"%s %s stroke-width:1;\""),
+ wxS("%s %s stroke-width=\"1\""),
GetBrushFill(m_textBackgroundColour),
GetPenStroke(m_textBackgroundColour));

@@ -897,7 +886,7 @@ void wxSVGFileDCImpl::DoDrawPolygon(int n, const wxPoint points[],
CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
}

- s += wxString::Format(wxS("\" %s %s %s style=\"fill-rule:%s;\"/>\n"),
+ s += wxString::Format(wxS("\" %s %s %s fill-rule=\"%s\"/>\n"),
GetRenderMode(m_renderingMode), GetPenPattern(m_pen), GetBrushPattern(m_brush),
fillStyle == wxODDEVEN_RULE ? wxS("evenodd") : wxS("nonzero"));

@@ -1028,6 +1017,12 @@ void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
GetRenderMode(m_renderingMode), GetPenPattern(m_pen));

write(s);
+
+ if ( AreAutomaticBoundingBoxUpdatesEnabled() )
+ {
+ double r = wxMax(r1, r2);
+ CalcBoundingBox(xc - r, yc - r, xc + r, yc + r);
+ }
}

void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord h, double sa, double ea)
@@ -1122,6 +1117,9 @@ void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord
wxString arcLine = wxString::Format(wxS("%s\" %s %s/>\n"),
arcPath, GetRenderMode(m_renderingMode), GetPenPattern(m_pen));
write(arcLine);
+
+ if ( AreAutomaticBoundingBoxUpdatesEnabled() )
+ CalcBoundingBox(x, y, x + w, y + h);
}

void wxSVGFileDCImpl::DoGradientFillLinear(const wxRect& rect,
@@ -1145,9 +1143,9 @@ void wxSVGFileDCImpl::DoGradientFillLinear(const wxRect& rect,
s += wxS(" <defs>\n");
s += wxString::Format(wxS(" <linearGradient id=\"gradient%zu\" x1=\"%d%%\" y1=\"%d%%\" x2=\"%d%%\" y2=\"%d%%\">\n"),
m_gradientUniqueId, x1, y1, x2, y2);
- s += wxString::Format(wxS(" <stop offset=\"0%%\" style=\"stop-color:%s; stop-opacity:%s\"/>\n"),
+ s += wxString::Format(wxS(" <stop offset=\"0%%\" stop-color=\"%s\" stop-opacity=\"%s\"/>\n"),
initCol, NumStr(initOpacity));
- s += wxString::Format(wxS(" <stop offset=\"100%%\" style=\"stop-color:%s; stop-opacity:%s\"/>\n"),
+ s += wxString::Format(wxS(" <stop offset=\"100%%\" stop-color=\"%s\" stop-opacity=\"%s\"/>\n"),
destCol, NumStr(destOpacity));
s += wxS(" </linearGradient>\n");
s += wxS(" </defs>\n");
@@ -1185,9 +1183,9 @@ void wxSVGFileDCImpl::DoGradientFillConcentric(const wxRect& rect,
s += wxS(" <defs>\n");
s += wxString::Format(wxS(" <radialGradient id=\"gradient%zu\" cx=\"%s%%\" cy=\"%s%%\" fx=\"%s%%\" fy=\"%s%%\">\n"),
m_gradientUniqueId, NumStr(cx), NumStr(cy), NumStr(fx), NumStr(fd));
- s += wxString::Format(wxS(" <stop offset=\"0%%\" style=\"stop-color:%s; stop-opacity:%s\" />\n"),
+ s += wxString::Format(wxS(" <stop offset=\"0%%\" stop-color=\"%s\" stop-opacity=\"%s\" />\n"),
initCol, NumStr(initOpacity));
- s += wxString::Format(wxS(" <stop offset=\"100%%\" style=\"stop-color:%s; stop-opacity:%s\" />\n"),
+ s += wxString::Format(wxS(" <stop offset=\"100%%\" stop-color=\"%s\" stop-opacity=\"%s\" />\n"),
destCol, NumStr(destOpacity));
s += wxS(" </radialGradient>\n");
s += wxS(" </defs>\n");
@@ -1242,10 +1240,10 @@ void wxSVGFileDCImpl::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord width, w
"y=\"" << y << "\" "
"width=\"" << width << "\" "
"height=\"" << height << "\" "
- "style=\"stroke: gray; fill: none;\"/>\n"
+ "stroke=\"gray\" fill=\"none\"/>\n"
" </clipPath>\n"
"</defs>\n"
- "<g style=\"clip-path: url(#clip" << m_clipNestingLevel << ");\">\n";
+ "<g clip-path=\"url(#clip" << m_clipNestingLevel << ")\">\n";

write(svg);

@@ -1293,27 +1291,18 @@ void wxSVGFileDCImpl::DoGetTextExtent(const wxString& string,
wxCoord* externalLeading,
const wxFont* theFont) const
{
- wxScreenDC sDC;
- SetScaledScreenDCFont(sDC, theFont ? *theFont : m_font);
-
- sDC.GetTextExtent(string, x, y, descent, externalLeading);
+ GetTextMetricDC(theFont ? *theFont : m_font).
+ GetTextExtent(string, x, y, descent, externalLeading);
}

wxCoord wxSVGFileDCImpl::GetCharHeight() const
{
- wxScreenDC sDC;
- SetScaledScreenDCFont(sDC, m_font);
-
- return sDC.GetCharHeight();
-
+ return GetTextMetricDC(m_font).GetCharHeight();
}

wxCoord wxSVGFileDCImpl::GetCharWidth() const
{
- wxScreenDC sDC;
- SetScaledScreenDCFont(sDC, m_font);
-
- return sDC.GetCharWidth();
+ return GetTextMetricDC(m_font).GetCharWidth();
}

void wxSVGFileDCImpl::ComputeScaleAndOrigin()
@@ -1384,7 +1373,7 @@ void wxSVGFileDCImpl::DoStartNewGraphics()
{
wxString s;

- s = wxString::Format(wxS("<g style=\"%s %s %s\" transform=\"translate(%d %d) scale(%s %s)\">\n"),
+ s = wxString::Format(wxS("<g %s %s %s transform=\"translate(%d %d) scale(%s %s)\">\n"),
GetPenStyle(m_pen),
GetBrushFill(m_brush.GetColour(), m_brush.GetStyle()),
GetPenStroke(m_pen.GetColour(), m_pen.GetStyle()),
@@ -1443,27 +1432,31 @@ void wxSVGFileDCImpl::DoDrawBitmap(const wxBitmap& bmp, wxCoord x, wxCoord y,
{
NewGraphicsIfNeeded();

+ if ( AreAutomaticBoundingBoxUpdatesEnabled() )
+ CalcBoundingBox(x, y, x + bmp.GetWidth(), y + bmp.GetHeight());
+
+ if ( !m_outfile )
+ return;
+
// If we don't have any bitmap handler yet, use the default one.
if ( !m_bmp_handler )
m_bmp_handler.reset(new wxSVGBitmapFileHandler(m_filename));

- m_OK = m_outfile && m_outfile->IsOk();
- if (!m_OK)
- return;
-
- m_bmp_handler->ProcessBitmap(bmp, x, y, *m_outfile);
- m_OK = m_outfile->IsOk();
+ m_writeError = m_bmp_handler->ProcessBitmap(bmp, x, y, *m_outfile);
}

void wxSVGFileDCImpl::write(const wxString& s)
{
- m_OK = m_outfile && m_outfile->IsOk();
- if (!m_OK)
+ if ( !m_outfile )
return;

- const wxCharBuffer buf = s.utf8_str();
- m_outfile->Write(buf, strlen((const char*)buf));
- m_OK = m_outfile->IsOk();
+ if ( m_outfile->IsOk() )
+ {
+ const wxCharBuffer buf = s.utf8_str();
+ m_outfile->Write(buf, strlen((const char*)buf));
+ }
+
+ m_writeError = !m_outfile->IsOk();
}

#endif // wxUSE_SVG


=====================================
tests/misc/garbage.cpp
=====================================
@@ -12,6 +12,8 @@

#include "testprec.h"

+#include "testfile.h"
+

#include "wx/filename.h"
#include "wx/image.h"
@@ -146,17 +148,10 @@ TEST_CASE("Load", "[garbage]")
data[i] = rand();

// write it to a file
- wxString garbagename = wxFileName::CreateTempFileName("garbage");
- CHECK(!garbagename.empty());
-
- wxFile garbage(garbagename, wxFile::write);
- CHECK(garbage.IsOpened());
-
- CHECK(garbage.Write(data, size) == size);
- garbage.Close();
+ TestFile tf(data, size);

// try to load it by name
- DoLoadGarbageFile(garbagename);
+ DoLoadGarbageFile(tf.GetName());

// try to load it from a wxInputStream
wxMemoryInputStream stream(data, size);


=====================================
tests/testfile.h
=====================================
@@ -27,11 +27,12 @@ inline std::ostream& operator<<(std::ostream& o, const wxFileName& fn)
class TestFile
{
public:
- TestFile()
+ // Ctor creates the file and initializes with the provided temporary data.
+ explicit TestFile(const void* data = "Before", size_t size = 6)
{
wxFile file;
m_name = wxFileName::CreateTempFileName(wxT("wxtest"), &file);
- file.Write("Before", 6);
+ file.Write(data, size);
}

~TestFile() { if (wxFileExists(m_name)) wxRemoveFile(m_name); }



View it on GitLab: https://gitlab.com/wxwidgets/wxwidgets/-/compare/c15b5cf5fe0ffc2dae398d7bbb03ca0510804555...0e8fcfe8e32eab0cf203f99c090fb38206606099

--
View it on GitLab: https://gitlab.com/wxwidgets/wxwidgets/-/compare/c15b5cf5fe0ffc2dae398d7bbb03ca0510804555...0e8fcfe8e32eab0cf203f99c090fb38206606099
You're receiving this email because of your account on gitlab.com.


Reply all
Reply to author
Forward
0 new messages