diff --git a/include/wx/private/svg.h b/include/wx/private/svg.h index f9095c7657..0f6387f553 100644 --- a/include/wx/private/svg.h +++ b/include/wx/private/svg.h @@ -26,6 +26,7 @@ #endif #include +#include class WXDLLIMPEXP_FWD_CORE wxBitmap; @@ -46,7 +47,7 @@ wxString GetPenStroke(const wxColour& c, int style = wxPENSTYLE_SOLID); wxString GetBrushFill(const wxColour& c, int style = wxBRUSHSTYLE_SOLID); // Returns a element definition for hatched brushes, or empty. -wxString CreateBrushFill(const wxBrush& brush, wxSVGShapeRenderingMode mode); +wxString CreateBrushFill(const wxBrush& brush, wxSVGShapeRenderingMode mode, wxString& patternName); // Returns a "shape-rendering=..." attribute fragment. wxString GetRenderMode(wxSVGShapeRenderingMode style); @@ -123,6 +124,9 @@ public: // handler on first use). Sets the write-error flag on failure. void WriteBitmap(const wxBitmap& bmp, wxCoord x, wxCoord y); + // Writes a brush fill pattern if it has not been written before + void WriteBrushFill(const wxBrush& brush); + // Returns the next gradient/clip id and increments the shared counter. size_t GetNextGradientId() { return ms_gradientUniqueId++; } size_t GetNextClipId() { return ms_clipUniqueId++; } @@ -182,6 +186,8 @@ private: int m_layerDepth = 0; int m_clipNestingLevel = 0; + std::set m_usedBrushPatterns; + static size_t ms_clipUniqueId; static size_t ms_gradientUniqueId; diff --git a/src/common/dcsvg.cpp b/src/common/dcsvg.cpp index f957aebfc4..441f93812b 100644 --- a/src/common/dcsvg.cpp +++ b/src/common/dcsvg.cpp @@ -319,10 +319,10 @@ wxString GetRenderMode(wxSVGShapeRenderingMode style) return s; } -wxString CreateBrushFill(const wxBrush& brush, wxSVGShapeRenderingMode mode) +wxString CreateBrushFill(const wxBrush& brush, wxSVGShapeRenderingMode mode, wxString& patternName) { wxString s; - wxString patternName = GetBrushStyleName(brush); + patternName = GetBrushStyleName(brush); if (!patternName.empty()) { @@ -1455,13 +1455,7 @@ void wxSVGFileDCImpl::SetBrush(const wxBrush& brush) m_writer->MarkGraphicsChanged(); - wxString pattern = CreateBrushFill(m_brush, m_writer->GetShapeRenderingMode()); - if ( !pattern.empty() ) - { - NewGraphicsIfNeeded(); - - write(pattern); - } + m_writer->WriteBrushFill(m_brush); } void wxSVGFileDCImpl::SetPen(const wxPen& pen) @@ -1815,6 +1809,19 @@ void wxSVGWriter::WriteBitmap(const wxBitmap& bmp, wxCoord x, wxCoord y) m_writeError = true; } +void wxSVGWriter::WriteBrushFill(const wxBrush& brush) +{ + if ( !brush.IsOk() ) + return; + + wxString patternName; + wxString pattern = CreateBrushFill(brush, GetShapeRenderingMode(), patternName); + if ( !pattern.empty() && !patternName.empty() && m_usedBrushPatterns.insert(patternName).second ) + { + Write(pattern); + } +} + #if wxUSE_GRAPHICS_CONTEXT bool wxSVGWriter::SetCompositionMode(wxCompositionMode mode) diff --git a/src/common/svggc.cpp b/src/common/svggc.cpp index 638a28600e..ab65352c8d 100644 --- a/src/common/svggc.cpp +++ b/src/common/svggc.cpp @@ -786,6 +786,21 @@ wxSVGGraphicsPenData::wxSVGGraphicsPenData(wxGraphicsRenderer* renderer, m_pen.SetColour(info.GetColour()); m_pen.SetWidth(static_cast(info.GetWidth() + 0.5)); m_pen.SetStyle(info.GetStyle()); + m_pen.SetCap(info.GetCap()); + m_pen.SetJoin(info.GetJoin()); + + if (m_pen.GetStyle() == wxPENSTYLE_USER_DASH) + { + wxDash* dashes; + if (int nb_dashes = info.GetDashes(&dashes)) + m_pen.SetDashes(nb_dashes, dashes); + } + + if (m_pen.GetStyle() == wxPENSTYLE_STIPPLE) + { + m_pen.SetStipple(info.GetStipple()); + } + } wxSVGGraphicsBrushData::wxSVGGraphicsBrushData(wxGraphicsRenderer* renderer, const wxBrush& brush) @@ -1307,7 +1322,11 @@ void wxSVGGraphicsContext::SetBrush(const wxGraphicsBrush& brush) auto* data = static_cast(brush.GetRefData()); if ( data != nullptr ) + { + m_writer->WriteBrushFill(data->GetBrush()); + SyncBrushToDC(data->GetBrush()); + } } void wxSVGGraphicsContext::SetFont(const wxGraphicsFont& font) @@ -1408,11 +1427,12 @@ void wxSVGGraphicsContext::StrokePath(const wxGraphicsPath& path) m_currentPen.GetStyle()); } + const wxString penPattern = wxSVG::GetPenPattern(m_currentPen); const wxString transform = GetCurrentTransformAttr(); const wxString s = wxString::Format( - wxS(" \n"), - data->GetDString(), stroke, m_currentPen.GetWidth(), transform); + wxS(" \n"), + data->GetDString(), stroke, m_currentPen.GetWidth(), penPattern, transform); m_writer->Write(s); @@ -1435,6 +1455,13 @@ void wxSVGGraphicsContext::FillPath(const wxGraphicsPath& path, wxPolygonFillMod if ( !m_brush.IsNull() ) fill = m_writer->WriteGraphicsBrushFill(m_brush); + if ( fill.empty() ) + { + auto* brushData = static_cast(m_brush.GetRefData()); + if ( brushData ) + fill = wxSVG::GetBrushPattern(brushData->GetBrush()); + } + if ( fill.empty() ) { fill = m_currentBrush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT @@ -1443,13 +1470,14 @@ void wxSVGGraphicsContext::FillPath(const wxGraphicsPath& path, wxPolygonFillMod m_currentBrush.GetStyle()); } + const wxString penPattern = wxSVG::GetPenPattern(m_currentPen); const wxString transform = GetCurrentTransformAttr(); const wxString rule = (fillStyle == wxODDEVEN_RULE) ? wxS("evenodd") : wxS("nonzero"); const wxString s = wxString::Format( - wxS(" \n"), - data->GetDString(), fill, rule, transform); + wxS(" \n"), + data->GetDString(), fill, rule, penPattern, transform); m_writer->Write(s);