1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        svgtest.cpp
3 // Purpose:     SVG sample
4 // Author:      Chris Elliott
5 // Licence:     wxWindows licence
6 /////////////////////////////////////////////////////////////////////////////
7 
8 // ===========================================================================
9 // declarations
10 // ===========================================================================
11 
12 // ---------------------------------------------------------------------------
13 // headers
14 // ---------------------------------------------------------------------------
15 
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
18 
19 
20 #ifndef WX_PRECOMP
21 #include "wx/wx.h"
22 #endif
23 
24 #include "wx/dcsvg.h"
25 #include "wx/notebook.h"
26 
27 #include "SVGlogo24.xpm"
28 
29 #ifndef wxHAS_IMAGES_IN_RESOURCES
30     #include "../sample.xpm"
31 #endif
32 
33 #include <math.h>
34 
35 // ---------------------------------------------------------------------------
36 // classes
37 // ---------------------------------------------------------------------------
38 
39 class MyApp : public wxApp
40 {
41 public:
42     bool OnInit() wxOVERRIDE;
43 };
44 
45 // Existing pages:
46 enum Page
47 {
48     Page_Lines,
49     Page_Polygons,
50     Page_Text,
51     Page_Arcs,
52     Page_Checkmarks,
53     Page_ScaledText,
54     Page_Bitmaps,
55     Page_Clipping,
56     Page_TextPos,
57     Page_Max
58 };
59 
60 static const char* pageNames[] =
61 {
62     "Lines",
63     "Polygons",
64     "Text",
65     "Arcs",
66     "Checkmarks",
67     "Scaled text",
68     "Bitmaps",
69     "Clipping",
70     "Text position",
71 };
72 
73 wxCOMPILE_TIME_ASSERT( WXSIZEOF(pageNames) == Page_Max, PageNamesMismatch );
74 
75 static const char* pageDescriptions[] =
76 {
77      "Green Cross, Cyan Line and spline",
78      "Blue rectangle, red edge, clear rounded rectangle, gold ellipse, gold and clear stars",
79      "Swiss, Times text; red text, rotated and colored orange",
80      "This is an arc test page",
81      "Two check marks",
82      "Scaling test page",
83      "Icon and Bitmap ",
84      "Clipping region",
85      "Text position test page",
86 };
87 
88 wxCOMPILE_TIME_ASSERT( WXSIZEOF(pageDescriptions) == Page_Max, PageDescriptionsMismatch );
89 
90 class MyPage : public wxScrolledWindow
91 {
92 public:
93     MyPage(wxNotebook *parent, int index);
94     virtual void OnDraw(wxDC& dc) wxOVERRIDE;
95     bool OnSave(wxString);
96 private:
97     int m_index;
98 };
99 
100 class MyFrame : public wxFrame
101 {
102 public:
103     MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
104             const wxPoint& pos, const wxSize& size);
105 
106     void FileSavePicture(wxCommandEvent& event);
107     void OnAbout(wxCommandEvent& event);
108     void OnQuit(wxCommandEvent& event);
109 private:
110     wxNotebook *m_notebook;
111 
112     wxDECLARE_EVENT_TABLE();
113 };
114 
115 // ---------------------------------------------------------------------------
116 // event tables
117 // ---------------------------------------------------------------------------
118 
119 wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
120     EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
121     EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
122     EVT_MENU(wxID_SAVE, MyFrame::FileSavePicture)
123 wxEND_EVENT_TABLE()
124 
125 // ===========================================================================
126 // implementation
127 // ===========================================================================
128 
129 // ---------------------------------------------------------------------------
130 // MyApp
131 // ---------------------------------------------------------------------------
132 
133 wxIMPLEMENT_APP(MyApp);
134 
OnInit()135 bool MyApp::OnInit()
136 {
137     // Create the main frame window
138 
139     MyFrame* frame = new MyFrame(NULL, -1, "SVG Demo",
140                                  wxDefaultPosition, wxSize(500, 400));
141 
142     frame->Show(true);
143 
144     return true;
145 }
146 
147 // ---------------------------------------------------------------------------
148 // MyFrame
149 // ---------------------------------------------------------------------------
150 
151 // Define my frame constructor
152 
MyFrame(wxWindow * parent,const wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size)153 MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
154                  const wxPoint& pos, const wxSize& size)
155         : wxFrame(parent, id, title, pos, size)
156 {
157     SetIcon(wxICON(sample));
158 
159     #if wxUSE_STATUSBAR
160     CreateStatusBar();
161     #endif // wxUSE_STATUSBAR
162 
163     // Make a menubar
164     wxMenu *file_menu = new wxMenu;
165 
166     file_menu->Append(wxID_SAVE);
167     file_menu->Append(wxID_EXIT);
168 
169     wxMenu *help_menu = new wxMenu;
170     help_menu->Append(wxID_ABOUT);
171 
172     wxMenuBar *menu_bar = new wxMenuBar;
173 
174     menu_bar->Append(file_menu, "&File");
175     menu_bar->Append(help_menu, "&Help");
176 
177     // Associate the menu bar with the frame
178     SetMenuBar(menu_bar);
179 
180     // Create a notebook
181     m_notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_TOP);
182 
183     //Add SVG Windows to a notebook
184     for (int i = 0; i < Page_Max; ++i)
185     {
186         m_notebook->AddPage(new MyPage(m_notebook, i), pageNames[i]);
187 
188     }
189 }
190 
OnQuit(wxCommandEvent & WXUNUSED (event))191 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
192 {
193     Close();
194 }
195 
OnAbout(wxCommandEvent & WXUNUSED (event))196 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
197 {
198     (void)wxMessageBox("wxWidgets SVG sample\n"
199         "Authors:\n"
200         "   Chris Elliott (c) 2002-2009\n"
201         "   Prashant Kumar Nirmal (c) 2017\n"
202         "Usage: click File|Save to Save the Selected SVG Test",
203         "About SVG Test");
204 }
205 
FileSavePicture(wxCommandEvent & WXUNUSED (event))206 void MyFrame::FileSavePicture(wxCommandEvent& WXUNUSED(event))
207 {
208 #if wxUSE_FILEDLG
209     MyPage * const page = (MyPage *) m_notebook->GetCurrentPage();
210 
211     wxFileDialog dialog(this, "Save Picture as", wxEmptyString,
212         m_notebook->GetPageText(m_notebook->GetSelection()),
213         "SVG vector picture files (*.svg)|*.svg",
214         wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
215 
216     if (dialog.ShowModal() == wxID_OK)
217     {
218         if (!page->OnSave ( dialog.GetPath() ))
219         {
220             return;
221         }
222     }
223     return;
224 #endif // wxUSE_FILEDLG
225 }
226 
227 // ---------------------------------------------------------------------------
228 // MyPage
229 // ---------------------------------------------------------------------------
230 
231 // Define a constructor for my page
MyPage(wxNotebook * parent,int index)232 MyPage::MyPage(wxNotebook *parent, int index)
233     : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL|wxHSCROLL)
234 {
235     SetBackgroundColour(*wxWHITE);
236     SetScrollbars(20, 20, 50, 50);
237     m_index = index;
238 }
239 
OnSave(wxString filename)240 bool MyPage::OnSave(wxString filename)
241 {
242     wxSVGFileDC svgDC (filename, 600, 650);
243     OnDraw (svgDC);
244     return svgDC.IsOk();
245 }
246 
247 // Define the repainting behaviour
OnDraw(wxDC & dc)248 void MyPage::OnDraw(wxDC& dc)
249 {
250      // vars to use ...
251     wxPen wP;
252     wxBrush wB;
253     wxPoint points[6];
254     wxColour wC;
255 
256     dc.SetFont(*wxSWISS_FONT);
257     dc.SetPen(*wxGREEN_PEN);
258 
259     switch (m_index)
260     {
261         case Page_Lines:
262             // draw lines to make a cross
263             dc.DrawLine(0, 0, 200, 200);
264             dc.DrawLine(200, 0, 0, 200);
265             // draw point colored line and spline
266             wP = *wxCYAN_PEN;
267             wP.SetWidth(3);
268             dc.SetPen(wP);
269 
270             dc.DrawPoint (25,15);
271             dc.DrawLine(50, 30, 200, 30);
272             dc.DrawSpline(50, 200, 50, 100, 200, 10);
273             break;
274 
275         case Page_Polygons:
276             // draw standard shapes
277             dc.SetBrush(*wxCYAN_BRUSH);
278             dc.SetPen(*wxRED_PEN);
279             dc.DrawRectangle(10, 10, 100, 70);
280             wB = wxBrush ("DARK ORCHID", wxBRUSHSTYLE_TRANSPARENT);
281             dc.SetBrush (wB);
282             dc.DrawRoundedRectangle(50, 50, 100, 70, 20);
283             dc.SetBrush (wxBrush("GOLDENROD") );
284             dc.DrawEllipse(100, 100, 100, 50);
285 
286             points[0].x = 100; points[0].y = 200;
287             points[1].x = 70; points[1].y = 260;
288             points[2].x = 160; points[2].y = 230;
289             points[3].x = 40; points[3].y = 230;
290             points[4].x = 130; points[4].y = 260;
291             points[5].x = 100; points[5].y = 200;
292 
293             dc.DrawPolygon(5, points);
294             dc.DrawLines (6, points, 160);
295             break;
296 
297         case Page_Text:
298             // draw text in Arial or similar font
299             dc.DrawLine(50,25,50,35);
300             dc.DrawLine(45,30,55,30);
301             dc.DrawText("This is a Swiss-style string", 50, 30);
302             wC = dc.GetTextForeground();
303             dc.SetTextForeground ("FIREBRICK");
304 
305             // no effect in msw ??
306             dc.SetTextBackground ("WHEAT");
307             dc.DrawText("This is a Red string", 50, 200);
308             dc.DrawRotatedText("This is a 45 deg string", 50, 200, 45);
309             dc.DrawRotatedText("This is a 90 deg string", 50, 200, 90);
310             dc.SetFont(wxFontInfo(18)
311                         .FaceName("Times New Roman")
312                         .Family(wxFONTFAMILY_ROMAN)
313                         .Italic().Bold());
314             dc.SetTextForeground (wC);
315             dc.DrawText("This is a Times-style string", 50, 60);
316             break;
317 
318         case Page_Arcs:
319             // four arcs start and end points, center
320             dc.SetBrush(*wxGREEN_BRUSH);
321             dc.DrawArc ( 200,300, 370,230, 300,300 );
322             dc.SetBrush(*wxBLUE_BRUSH);
323             dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270,270 );
324             dc.SetDeviceOrigin(-10,-10);
325             dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270,270 );
326             dc.SetDeviceOrigin(0,0);
327 
328             wP.SetColour ("CADET BLUE");
329             dc.SetPen(wP);
330             dc.DrawArc ( 75,125, 110, 40, 75, 75 );
331 
332             wP.SetColour ("SALMON");
333             dc.SetPen(wP);
334             dc.SetBrush(*wxRED_BRUSH);
335             //top left corner, width and height, start and end angle
336                                  // 315 same center and x-radius as last pie-arc, half Y radius
337             dc.DrawEllipticArc(25,50,100,50,180.0,45.0);
338 
339             wP = *wxCYAN_PEN;
340             wP.SetWidth(3);
341             dc.SetPen(wP);
342                                  //wxBRUSHSTYLE_TRANSPARENT));
343             dc.SetBrush (wxBrush ("SALMON"));
344             dc.DrawEllipticArc(300,  0,200,100, 0.0,145.0);
345                                  //same end point
346             dc.DrawEllipticArc(300, 50,200,100,90.0,145.0);
347             dc.DrawEllipticArc(300,100,200,100,90.0,345.0);
348 
349             break;
350 
351         case Page_Checkmarks:
352             dc.DrawCheckMark ( 30,30,25,25);
353             dc.SetBrush (wxBrush ("SALMON",wxBRUSHSTYLE_TRANSPARENT));
354             dc.DrawCheckMark ( 80,50,75,75);
355             dc.DrawRectangle ( 80,50,75,75);
356             break;
357 
358         case Page_ScaledText:
359             dc.SetFont(wxFontInfo(18)
360                         .FaceName("Times New Roman")
361                         .Family(wxFONTFAMILY_ROMAN)
362                         .Italic().Bold());
363             dc.DrawLine(0, 0, 200, 200);
364             dc.DrawLine(200, 0, 0, 200);
365             dc.DrawText("This is an 18pt string", 50, 60);
366 
367             // rescale and draw in blue
368             wP = *wxCYAN_PEN;
369             dc.SetPen(wP);
370             dc.SetUserScale (2.0,0.5);
371             dc.SetDeviceOrigin(200,0);
372             dc.DrawLine(0, 0, 200, 200);
373             dc.DrawLine(200, 0, 0, 200);
374             dc.DrawText("This is an 18pt string 2 x 0.5 UserScaled", 50, 60);
375             dc.SetUserScale (2.0,2.0);
376             dc.SetDeviceOrigin(200,200);
377             dc.DrawText("This is an 18pt string 2 x 2 UserScaled", 50, 60);
378 
379             wP = *wxRED_PEN;
380             dc.SetPen(wP);
381             dc.SetUserScale (1.0,1.0);
382             dc.SetDeviceOrigin(0,10);
383             dc.SetMapMode (wxMM_METRIC); //svg ignores this
384             dc.DrawLine(0, 0, 200, 200);
385             dc.DrawLine(200, 0, 0, 200);
386             dc.DrawText("This is an 18pt string in MapMode", 50, 60);
387             break;
388 
389         case Page_Bitmaps:
390             dc.DrawIcon( wxICON(sample), 10, 10 );
391             dc.DrawBitmap ( wxBitmap(svgbitmap_xpm), 50,15);
392             break;
393 
394         case Page_Clipping:
395             dc.SetTextForeground("RED");
396             dc.DrawText("Red = Clipping Off", 30, 5);
397             dc.SetTextForeground("GREEN");
398             dc.DrawText("Green = Clipping On", 30, 25);
399 
400             dc.SetTextForeground("BLACK");
401 
402             dc.SetPen(*wxRED_PEN);
403             dc.SetBrush (wxBrush ("SALMON",wxBRUSHSTYLE_TRANSPARENT));
404             dc.DrawCheckMark ( 80,50,75,75);
405             dc.DrawRectangle ( 80,50,75,75);
406 
407             dc.SetPen(*wxGREEN_PEN);
408 
409             // Clipped checkmarks
410             dc.DrawRectangle(180,50,75,75);
411             dc.SetClippingRegion(180,50,75,75);                   // x,y,width,height version
412             dc.DrawCheckMark ( 180,50,75,75);
413             dc.DestroyClippingRegion();
414 
415             dc.DrawRectangle(wxRect(80,150,75,75));
416             dc.SetClippingRegion(wxPoint(80,150),wxSize(75,75));  // pt,size version
417             dc.DrawCheckMark ( 80,150,75,75);
418             dc.DestroyClippingRegion();
419 
420             dc.DrawRectangle(wxRect(180,150,75,75));
421             dc.SetClippingRegion(wxRect(180,150,75,75));          // rect version
422             dc.DrawCheckMark ( 180,150,75,75);
423             dc.DestroyClippingRegion();
424 
425             dc.DrawRectangle(wxRect( 80,250,50,65));
426             dc.DrawRectangle(wxRect(105,260,50,65));
427             dc.SetClippingRegion(wxRect( 80,250,50,65));  // second call to SetClippingRegion
428             dc.SetClippingRegion(wxRect(105,260,50,65));  // forms intersection with previous
429             dc.DrawCheckMark(80,250,75,75);
430             dc.DestroyClippingRegion();                   // only one call to destroy (there's no stack)
431 
432             /*
433             ** Clipping by wxRegion not implemented for SVG.   Should be
434             ** possible, but need to access points that define the wxRegion
435             ** from inside DoSetDeviceClippingRegion() and wxRegion does not
436             ** implement anything like getPoints().
437             points[0].x = 180; points[0].y = 250;
438             points[1].x = 255; points[1].y = 250;
439             points[2].x = 180; points[2].y = 325;
440             points[3].x = 255; points[3].y = 325;
441             points[4].x = 180; points[4].y = 250;
442 
443             dc.DrawLines (5, points);
444             wxRegion reg = wxRegion(5,points);
445 
446             dc.SetClippingRegion(reg);
447             dc.DrawCheckMark ( 180,250,75,75);
448             dc.DestroyClippingRegion();
449             */
450 
451             break;
452 
453         case Page_TextPos:
454             wxString txtStr;
455             wxCoord txtX, txtY, txtW, txtH, txtDescent, txtEL;
456             wxCoord txtPad = 0;
457 
458             wP = *wxRED_PEN;
459             dc.SetPen(wP);
460             //dc.SetBackgroundMode(wxBRUSHSTYLE_SOLID);
461             //dc.SetTextBackground(*wxBLUE);
462 
463             // Horizontal text
464             txtStr = "Horizontal string";
465             dc.GetTextExtent(txtStr, &txtW, &txtH, &txtDescent, &txtEL);
466             txtX = 50;
467             txtY = 300;
468             dc.DrawRectangle(txtX, txtY, txtW + 2*txtPad, txtH + 2*txtPad);
469             dc.DrawText(txtStr, txtX + txtPad, txtY + txtPad);
470 
471             // Vertical text
472             txtStr = "Vertical string";
473             dc.GetTextExtent(txtStr, &txtW, &txtH, &txtDescent, &txtEL);
474             txtX = 50;
475             txtY = 250;
476             dc.DrawRectangle(txtX, txtY - (txtW + 2*txtPad), txtH + 2*txtPad, txtW + 2*txtPad);
477             dc.DrawRotatedText(txtStr, txtX + txtPad, txtY - txtPad, 90);
478 
479             // 45 degree text
480             txtStr = "45 deg string";
481             dc.GetTextExtent(txtStr, &txtW, &txtH, &txtDescent, &txtEL);
482             double lenW = (double)(txtW + 2*txtPad) / sqrt(2.0);
483             double lenH = (double)(txtH + 2*txtPad) / sqrt(2.0);
484             double padding = (double)txtPad / sqrt(2.0);
485             txtX = 150;
486             txtY = 200;
487             dc.DrawLine(txtX - padding, txtY, txtX + lenW, txtY - lenW); // top
488             dc.DrawLine(txtX + lenW, txtY - lenW, txtX - padding + lenH + lenW, txtY + (lenH - lenW));
489             dc.DrawLine(txtX - padding, txtY, txtX - padding + lenH, txtY + lenH);
490             dc.DrawLine(txtX - padding + lenH, txtY + lenH, txtX - padding + lenH + lenW, txtY + (lenH - lenW)); // bottom
491             dc.DrawRotatedText(txtStr, txtX, txtY, 45);
492             break;
493     }
494 
495    wxLogStatus("%s", pageDescriptions[m_index]);
496 }
497 
498