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