mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-08-17 17:02:51 +08:00
Support pen and brush styles in wxSVGGraphicsContext
SVG does not allow redefining patterns with the same ID, so write each pattern only once.
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
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 <pattern> 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<wxString> m_usedBrushPatterns;
|
||||
|
||||
static size_t ms_clipUniqueId;
|
||||
static size_t ms_gradientUniqueId;
|
||||
|
||||
|
||||
+16
-9
@@ -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)
|
||||
|
||||
+32
-4
@@ -786,6 +786,21 @@ wxSVGGraphicsPenData::wxSVGGraphicsPenData(wxGraphicsRenderer* renderer,
|
||||
m_pen.SetColour(info.GetColour());
|
||||
m_pen.SetWidth(static_cast<int>(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<wxSVGGraphicsBrushData*>(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(" <path d=\"%s\" fill=\"none\" %s stroke-width=\"%d\"%s/>\n"),
|
||||
data->GetDString(), stroke, m_currentPen.GetWidth(), transform);
|
||||
wxS(" <path d=\"%s\" fill=\"none\" %s stroke-width=\"%d\" %s%s/>\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<wxSVGGraphicsBrushData*>(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(" <path d=\"%s\" %s fill-rule=\"%s\" stroke=\"none\"%s/>\n"),
|
||||
data->GetDString(), fill, rule, transform);
|
||||
wxS(" <path d=\"%s\" %s fill-rule=\"%s\" stroke=\"none\" %s%s/>\n"),
|
||||
data->GetDString(), fill, rule, penPattern, transform);
|
||||
|
||||
m_writer->Write(s);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user