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).
|
||||
- Allow specifying all wxFlexGridSizer parameters in XRC (Steffen Olszewski).
|
||||
- Close wxLogWindow automatically if it's the last remaining top level window.
|
||||
- Implement clipping for wxSVGFileDC (Steve Benbow).
|
||||
|
||||
wxGTK:
|
||||
|
||||
|
@@ -54,10 +54,7 @@ public:
|
||||
wxFAIL_MSG(wxT("wxSVGFILEDC::Clear() Call not implemented \nNot sensible for an output file?"));
|
||||
}
|
||||
|
||||
virtual void DestroyClippingRegion()
|
||||
{
|
||||
wxFAIL_MSG(wxT("wxSVGFILEDC::void Call not yet implemented"));
|
||||
}
|
||||
virtual void DestroyClippingRegion();
|
||||
|
||||
virtual wxCoord GetCharHeight() const;
|
||||
virtual wxCoord GetCharWidth() const;
|
||||
@@ -175,10 +172,7 @@ private:
|
||||
wxFAIL_MSG(wxT("wxSVGFILEDC::DoSetDeviceClippingRegion not yet implemented"));
|
||||
}
|
||||
|
||||
virtual void DoSetClippingRegion( int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
|
||||
{
|
||||
wxFAIL_MSG(wxT("wxSVGFILEDC::DoSetClippingRegion not yet implemented"));
|
||||
}
|
||||
virtual void DoSetClippingRegion(int x, int y, int width, int height);
|
||||
|
||||
virtual void DoGetSizeMM( int *width, int *height ) const;
|
||||
|
||||
@@ -193,6 +187,10 @@ private:
|
||||
// new one for the last pen/brush change.
|
||||
void NewGraphicsIfNeeded();
|
||||
|
||||
// Open a new graphics group setting up all the attributes according to
|
||||
// their current values in wxDC.
|
||||
void DoStartNewGraphics();
|
||||
|
||||
wxFileOutputStream *m_outfile;
|
||||
wxString m_filename;
|
||||
int m_sub_images; // number of png format images we have
|
||||
@@ -201,7 +199,14 @@ private:
|
||||
int m_width, m_height;
|
||||
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)
|
||||
};
|
||||
|
||||
|
@@ -67,21 +67,52 @@ public:
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void CrossHair(wxCoord x, wxCoord y);
|
||||
void DestroyClippingRegion();
|
||||
bool FloodFill(wxCoord x, wxCoord y, const wxColour& colour,
|
||||
wxFloodFillStyle style = wxFLOOD_SURFACE);
|
||||
void GetClippingBox(wxCoord *x, wxCoord *y, wxCoord *width, wxCoord *height) 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);
|
||||
bool StartDoc(const wxString& message);
|
||||
//@}
|
||||
|
@@ -323,7 +323,7 @@ MyCanvas::MyCanvas(MyChild *parent, const wxPoint& pos, const wxSize& size)
|
||||
SetBackgroundColour(wxColour(wxT("WHITE")));
|
||||
|
||||
m_child = parent;
|
||||
m_index = m_child->GetFrame()->GetCountOfChildren() % 8;
|
||||
m_index = m_child->GetFrame()->GetCountOfChildren() % 9;
|
||||
}
|
||||
|
||||
// Define the repainting behaviour
|
||||
@@ -496,6 +496,68 @@ void MyCanvas::OnDraw(wxDC& dc)
|
||||
break;
|
||||
|
||||
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;
|
||||
wxCoord txtX, txtY, txtW, txtH, txtDescent, txtEL;
|
||||
wxCoord txtPad = 0;
|
||||
@@ -538,7 +600,6 @@ void MyCanvas::OnDraw(wxDC& dc)
|
||||
s = wxT("Text position test page");
|
||||
#endif // wxUSE_STATUSBAR
|
||||
break;
|
||||
|
||||
}
|
||||
#if wxUSE_STATUSBAR
|
||||
m_child->SetStatusText(s);
|
||||
|
@@ -130,6 +130,9 @@ void wxSVGFileDCImpl::Init (const wxString &filename, int Width, int Height, dou
|
||||
|
||||
m_OK = true;
|
||||
|
||||
m_clipUniqueId = 0;
|
||||
m_clipNestingLevel = 0;
|
||||
|
||||
m_mm_to_pix_x = 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
|
||||
|
||||
{
|
||||
@@ -538,9 +594,16 @@ void wxSVGFileDCImpl::NewGraphicsIfNeeded()
|
||||
|
||||
m_graphics_changed = false;
|
||||
|
||||
write(wxS("</g>\n"));
|
||||
|
||||
DoStartNewGraphics();
|
||||
}
|
||||
|
||||
void wxSVGFileDCImpl::DoStartNewGraphics()
|
||||
{
|
||||
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());
|
||||
|
||||
switch ( m_pen.GetCap() )
|
||||
|
Reference in New Issue
Block a user