Implement clipping in wxSVGFileDC.
Support setting the clipping region and add update the documentation and the sample accordingly. Closes #14462. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72762 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -579,6 +579,7 @@ All (GUI):
|
|||||||
- Add missing styles support to wxWindow XRC hanlder (Steffen Olszewski).
|
- Add missing styles support to wxWindow XRC hanlder (Steffen Olszewski).
|
||||||
- Allow specifying all wxFlexGridSizer parameters in XRC (Steffen Olszewski).
|
- Allow specifying all wxFlexGridSizer parameters in XRC (Steffen Olszewski).
|
||||||
- Close wxLogWindow automatically if it's the last remaining top level window.
|
- Close wxLogWindow automatically if it's the last remaining top level window.
|
||||||
|
- Implement clipping for wxSVGFileDC (Steve Benbow).
|
||||||
|
|
||||||
wxGTK:
|
wxGTK:
|
||||||
|
|
||||||
|
@@ -54,10 +54,7 @@ public:
|
|||||||
wxFAIL_MSG(wxT("wxSVGFILEDC::Clear() Call not implemented \nNot sensible for an output file?"));
|
wxFAIL_MSG(wxT("wxSVGFILEDC::Clear() Call not implemented \nNot sensible for an output file?"));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void DestroyClippingRegion()
|
virtual void DestroyClippingRegion();
|
||||||
{
|
|
||||||
wxFAIL_MSG(wxT("wxSVGFILEDC::void Call not yet implemented"));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual wxCoord GetCharHeight() const;
|
virtual wxCoord GetCharHeight() const;
|
||||||
virtual wxCoord GetCharWidth() const;
|
virtual wxCoord GetCharWidth() const;
|
||||||
@@ -175,10 +172,7 @@ private:
|
|||||||
wxFAIL_MSG(wxT("wxSVGFILEDC::DoSetDeviceClippingRegion not yet implemented"));
|
wxFAIL_MSG(wxT("wxSVGFILEDC::DoSetDeviceClippingRegion not yet implemented"));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void DoSetClippingRegion( int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
|
virtual void DoSetClippingRegion(int x, int y, int width, int height);
|
||||||
{
|
|
||||||
wxFAIL_MSG(wxT("wxSVGFILEDC::DoSetClippingRegion not yet implemented"));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void DoGetSizeMM( int *width, int *height ) const;
|
virtual void DoGetSizeMM( int *width, int *height ) const;
|
||||||
|
|
||||||
@@ -193,6 +187,10 @@ private:
|
|||||||
// new one for the last pen/brush change.
|
// new one for the last pen/brush change.
|
||||||
void NewGraphicsIfNeeded();
|
void NewGraphicsIfNeeded();
|
||||||
|
|
||||||
|
// Open a new graphics group setting up all the attributes according to
|
||||||
|
// their current values in wxDC.
|
||||||
|
void DoStartNewGraphics();
|
||||||
|
|
||||||
wxFileOutputStream *m_outfile;
|
wxFileOutputStream *m_outfile;
|
||||||
wxString m_filename;
|
wxString m_filename;
|
||||||
int m_sub_images; // number of png format images we have
|
int m_sub_images; // number of png format images we have
|
||||||
@@ -201,7 +199,14 @@ private:
|
|||||||
int m_width, m_height;
|
int m_width, m_height;
|
||||||
double m_dpi;
|
double m_dpi;
|
||||||
|
|
||||||
private:
|
// The clipping nesting level is incremented by every call to
|
||||||
|
// SetClippingRegion() and reset when DestroyClippingRegion() is called.
|
||||||
|
size_t m_clipNestingLevel;
|
||||||
|
|
||||||
|
// Unique ID for every clipping graphics group: this is simply always
|
||||||
|
// incremented in each SetClippingRegion() call.
|
||||||
|
size_t m_clipUniqueId;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_CLASS(wxSVGFileDCImpl)
|
DECLARE_ABSTRACT_CLASS(wxSVGFileDCImpl)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -67,21 +67,52 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SetLogicalFunction(wxRasterOperationMode function);
|
void SetLogicalFunction(wxRasterOperationMode function);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the clipping region for this device context to the intersection of
|
||||||
|
the given region described by the parameters of this method and the previously
|
||||||
|
set clipping region.
|
||||||
|
Clipping is implemented in the SVG output using SVG group elements (<g>), with
|
||||||
|
nested group elements being used to represent clipping region intersections when
|
||||||
|
two or more calls are made to SetClippingRegion().
|
||||||
|
*/
|
||||||
|
void SetClippingRegion(wxCoord x, wxCoord y, wxCoord width,
|
||||||
|
wxCoord height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This is an overloaded member function, provided for convenience. It differs from the
|
||||||
|
above function only in what argument(s) it accepts.
|
||||||
|
*/
|
||||||
|
void SetClippingRegion(const wxPoint& pt, const wxSize& sz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This is an overloaded member function, provided for convenience. It differs from the
|
||||||
|
above function only in what argument(s) it accepts.
|
||||||
|
*/
|
||||||
|
void SetClippingRegion(const wxRect& rect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is not implemented in this DC class.
|
||||||
|
It could be implemented in future if a GetPoints() function were made available on wxRegion.
|
||||||
|
*/
|
||||||
|
void SetClippingRegion(const wxRegion& region);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Destroys the current clipping region so that none of the DC is clipped.
|
||||||
|
Since intersections arising from sequential calls to SetClippingRegion are represented
|
||||||
|
with nested SVG group elements (<g>), all such groups are closed when
|
||||||
|
DestroyClippingRegion is called.
|
||||||
|
*/
|
||||||
|
void DestroyClippingRegion();
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
/**
|
/**
|
||||||
Functions not implemented in this DC class.
|
Functions not implemented in this DC class.
|
||||||
*/
|
*/
|
||||||
void CrossHair(wxCoord x, wxCoord y);
|
void CrossHair(wxCoord x, wxCoord y);
|
||||||
void DestroyClippingRegion();
|
|
||||||
bool FloodFill(wxCoord x, wxCoord y, const wxColour& colour,
|
bool FloodFill(wxCoord x, wxCoord y, const wxColour& colour,
|
||||||
wxFloodFillStyle style = wxFLOOD_SURFACE);
|
wxFloodFillStyle style = wxFLOOD_SURFACE);
|
||||||
void GetClippingBox(wxCoord *x, wxCoord *y, wxCoord *width, wxCoord *height) const;
|
void GetClippingBox(wxCoord *x, wxCoord *y, wxCoord *width, wxCoord *height) const;
|
||||||
bool GetPixel(wxCoord x, wxCoord y, wxColour* colour) const;
|
bool GetPixel(wxCoord x, wxCoord y, wxColour* colour) const;
|
||||||
void SetClippingRegion(wxCoord x, wxCoord y, wxCoord width,
|
|
||||||
wxCoord height);
|
|
||||||
void SetClippingRegion(const wxPoint& pt, const wxSize& sz);
|
|
||||||
void SetClippingRegion(const wxRect& rect);
|
|
||||||
void SetClippingRegion(const wxRegion& region);
|
|
||||||
void SetPalette(const wxPalette& palette);
|
void SetPalette(const wxPalette& palette);
|
||||||
bool StartDoc(const wxString& message);
|
bool StartDoc(const wxString& message);
|
||||||
//@}
|
//@}
|
||||||
|
@@ -323,7 +323,7 @@ MyCanvas::MyCanvas(MyChild *parent, const wxPoint& pos, const wxSize& size)
|
|||||||
SetBackgroundColour(wxColour(wxT("WHITE")));
|
SetBackgroundColour(wxColour(wxT("WHITE")));
|
||||||
|
|
||||||
m_child = parent;
|
m_child = parent;
|
||||||
m_index = m_child->GetFrame()->GetCountOfChildren() % 8;
|
m_index = m_child->GetFrame()->GetCountOfChildren() % 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define the repainting behaviour
|
// Define the repainting behaviour
|
||||||
@@ -496,6 +496,68 @@ void MyCanvas::OnDraw(wxDC& dc)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
|
dc.SetTextForeground(wxT("RED"));
|
||||||
|
dc.DrawText(wxT("Red = Clipping Off"), 30, 5);
|
||||||
|
dc.SetTextForeground(wxT("GREEN"));
|
||||||
|
dc.DrawText(wxT("Green = Clipping On"), 30, 25);
|
||||||
|
|
||||||
|
dc.SetTextForeground(wxT("BLACK"));
|
||||||
|
|
||||||
|
dc.SetPen(*wxRED_PEN);
|
||||||
|
dc.SetBrush (wxBrush (wxT("SALMON"),wxBRUSHSTYLE_TRANSPARENT));
|
||||||
|
dc.DrawCheckMark ( 80,50,75,75);
|
||||||
|
dc.DrawRectangle ( 80,50,75,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.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.DestroyClippingRegion();
|
||||||
|
|
||||||
|
dc.DrawRectangle(wxRect(180,150,75,75));
|
||||||
|
dc.SetClippingRegion(wxRect(180,150,75,75)); // rect version
|
||||||
|
dc.DrawCheckMark ( 180,150,75,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)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Clipping by wxRegion not implemented for SVG. Should be
|
||||||
|
** possible, but need to access points that define the wxRegion
|
||||||
|
** from inside DoSetDeviceClippingRegion() and wxRegion does not
|
||||||
|
** implement anything like getPoints().
|
||||||
|
points[0].x = 180; points[0].y = 250;
|
||||||
|
points[1].x = 255; points[1].y = 250;
|
||||||
|
points[2].x = 180; points[2].y = 325;
|
||||||
|
points[3].x = 255; points[3].y = 325;
|
||||||
|
points[4].x = 180; points[4].y = 250;
|
||||||
|
|
||||||
|
dc.DrawLines (5, points);
|
||||||
|
wxRegion reg = wxRegion(5,points);
|
||||||
|
|
||||||
|
dc.SetClippingRegion(reg);
|
||||||
|
dc.DrawCheckMark ( 180,250,75,75);
|
||||||
|
dc.DestroyClippingRegion();
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if wxUSE_STATUSBAR
|
||||||
|
s = wxT("Clipping region");
|
||||||
|
#endif // wxUSE_STATUSBAR
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
wxString txtStr;
|
wxString txtStr;
|
||||||
wxCoord txtX, txtY, txtW, txtH, txtDescent, txtEL;
|
wxCoord txtX, txtY, txtW, txtH, txtDescent, txtEL;
|
||||||
wxCoord txtPad = 0;
|
wxCoord txtPad = 0;
|
||||||
@@ -538,7 +600,6 @@ void MyCanvas::OnDraw(wxDC& dc)
|
|||||||
s = wxT("Text position test page");
|
s = wxT("Text position test page");
|
||||||
#endif // wxUSE_STATUSBAR
|
#endif // wxUSE_STATUSBAR
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
#if wxUSE_STATUSBAR
|
#if wxUSE_STATUSBAR
|
||||||
m_child->SetStatusText(s);
|
m_child->SetStatusText(s);
|
||||||
|
@@ -130,6 +130,9 @@ void wxSVGFileDCImpl::Init (const wxString &filename, int Width, int Height, dou
|
|||||||
|
|
||||||
m_OK = true;
|
m_OK = true;
|
||||||
|
|
||||||
|
m_clipUniqueId = 0;
|
||||||
|
m_clipNestingLevel = 0;
|
||||||
|
|
||||||
m_mm_to_pix_x = dpi/25.4;
|
m_mm_to_pix_x = dpi/25.4;
|
||||||
m_mm_to_pix_y = dpi/25.4;
|
m_mm_to_pix_y = dpi/25.4;
|
||||||
|
|
||||||
@@ -470,6 +473,59 @@ void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxSVGFileDCImpl::DoSetClippingRegion( int x, int y, int width, int height )
|
||||||
|
{
|
||||||
|
wxString svg;
|
||||||
|
|
||||||
|
// End current graphics group to ensure proper xml nesting (e.g. so that
|
||||||
|
// graphics can be subsequently changed inside the clipping region)
|
||||||
|
svg << "</g>\n"
|
||||||
|
"<defs>\n"
|
||||||
|
"<clipPath id=\"clip" << m_clipNestingLevel << "\">\n"
|
||||||
|
"<rect id=\"cliprect" << m_clipNestingLevel << "\" "
|
||||||
|
"x=\"" << x << "\" "
|
||||||
|
"y=\"" << y << "\" "
|
||||||
|
"width=\"" << width << "\" "
|
||||||
|
"height=\"" << height << "\" "
|
||||||
|
"style=\"stroke: gray; fill: none;\"/>\n"
|
||||||
|
"</clipPath>\n"
|
||||||
|
"</defs>\n"
|
||||||
|
"<g style=\"clip-path: url(#clip" << m_clipNestingLevel << ");\">\n";
|
||||||
|
|
||||||
|
write(svg);
|
||||||
|
|
||||||
|
// Re-apply current graphics to ensure proper xml nesting
|
||||||
|
DoStartNewGraphics();
|
||||||
|
|
||||||
|
m_clipUniqueId++;
|
||||||
|
m_clipNestingLevel++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxSVGFileDCImpl::DestroyClippingRegion()
|
||||||
|
{
|
||||||
|
wxString svg;
|
||||||
|
|
||||||
|
// End current graphics element to ensure proper xml nesting (e.g. graphics
|
||||||
|
// might have been changed inside the clipping region)
|
||||||
|
svg << "</g>\n";
|
||||||
|
|
||||||
|
// Close clipping group elements
|
||||||
|
for ( size_t i = 0; i < m_clipUniqueId; i++ )
|
||||||
|
{
|
||||||
|
svg << "</g>";
|
||||||
|
}
|
||||||
|
svg << "\n";
|
||||||
|
|
||||||
|
write(svg);
|
||||||
|
|
||||||
|
// Re-apply current graphics (e.g. brush may have been changed inside one
|
||||||
|
// of the clipped regions - that change will have been lost after xml
|
||||||
|
// elements for the clipped region have been closed).
|
||||||
|
DoStartNewGraphics();
|
||||||
|
|
||||||
|
m_clipUniqueId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void wxSVGFileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , const wxFont *font) const
|
void wxSVGFileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , const wxFont *font) const
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -538,9 +594,16 @@ void wxSVGFileDCImpl::NewGraphicsIfNeeded()
|
|||||||
|
|
||||||
m_graphics_changed = false;
|
m_graphics_changed = false;
|
||||||
|
|
||||||
|
write(wxS("</g>\n"));
|
||||||
|
|
||||||
|
DoStartNewGraphics();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxSVGFileDCImpl::DoStartNewGraphics()
|
||||||
|
{
|
||||||
wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast;
|
wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast;
|
||||||
|
|
||||||
sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour(), m_brush.GetStyle() )
|
sBrush = wxS("<g style=\"") + wxBrushString ( m_brush.GetColour(), m_brush.GetStyle() )
|
||||||
+ wxPenString(m_pen.GetColour(), m_pen.GetStyle());
|
+ wxPenString(m_pen.GetColour(), m_pen.GetStyle());
|
||||||
|
|
||||||
switch ( m_pen.GetCap() )
|
switch ( m_pen.GetCap() )
|
||||||
|
Reference in New Issue
Block a user