From: Chris Elliott Date: Wed, 19 Jun 2002 09:16:19 +0000 (+0000) Subject: wxSVGDC class test sample X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/cdf3a589b2bb01c3ca1dc4e35661d864b2a2c227 wxSVGDC class test sample git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15882 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/contrib/samples/svg/Makefile.in b/contrib/samples/svg/Makefile.in new file mode 100644 index 0000000000..a34d871ea6 --- /dev/null +++ b/contrib/samples/svg/Makefile.in @@ -0,0 +1,16 @@ +# Makefile for plot sample. +# $Id$ + +top_srcdir = @top_srcdir@/.. +top_builddir = ../../.. +program_dir = contrib/samples/svg + +PROGRAM=svgtest + +OBJECTS=svgtest.o + +APPEXTRALIBS=$(top_builddir)/lib/libwx_dcsvg.@WX_TARGET_LIBRARY_TYPE@ +APPEXTRADEFS=-I$(top_srcdir)/contrib/include + +include $(top_builddir)/src/makeprog.env + diff --git a/contrib/samples/svg/SVGlogo24.bmp b/contrib/samples/svg/SVGlogo24.bmp new file mode 100644 index 0000000000..5c6e4a9693 Binary files /dev/null and b/contrib/samples/svg/SVGlogo24.bmp differ diff --git a/contrib/samples/svg/SVGlogo24.xpm b/contrib/samples/svg/SVGlogo24.xpm new file mode 100644 index 0000000000..113067233a --- /dev/null +++ b/contrib/samples/svg/SVGlogo24.xpm @@ -0,0 +1,310 @@ +/* XPM */ +static char *svgbitmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"64 48 256 2", +" c #550000", +". c #5c0000", +"X c #5f000a", +"o c #5c033a", +"O c #5a3615", +"+ c #640000", +"@ c #640009", +"# c #680605", +"$ c #680807", +"% c #6d0e0e", +"& c #630015", +"* c #690717", +"= c #6d110e", +"- c #6e1412", +"; c #701513", +": c #721b16", +"> c #741c1a", +", c #650021", +"< c #65022b", +"1 c #65003d", +"2 c #650034", +"3 c #6b1132", +"4 c #711535", +"5 c #76221c", +"6 c #78211e", +"7 c #642939", +"8 c #643929", +"9 c #663336", +"0 c #772220", +"q c #792522", +"w c #7b2a23", +"e c #7d2d29", +"r c #7f312a", +"t c #5d004f", +"y c #560059", +"u c #5b005c", +"i c #5a0054", +"p c #5e0061", +"a c #64004a", +"s c #650046", +"d c #640150", +"f c #64025d", +"g c #660d58", +"h c #671746", +"j c #651352", +"k c #640064", +"l c #640069", +"z c #6d0e6c", +"x c #680767", +"c c #6e0f71", +"v c #6c106b", +"b c #6c1665", +"n c #711a6c", +"m c #731b72", +"M c #682847", +"N c #6d2653", +"B c #75236d", +"V c #7c2d74", +"C c #7d2c7a", +"Z c #782278", +"A c #7e3177", +"S c #565600", +"D c #5c5c00", +"F c #5e6100", +"G c #614416", +"H c #655f06", +"J c #655a0b", +"K c #70463b", +"L c #6e4538", +"P c #646400", +"I c #656a00", +"U c #6c6c0d", +"Y c #676708", +"T c #6d6914", +"R c #6d720f", +"E c #707014", +"W c #78781e", +"Q c #75771a", +"! c #75602d", +"~ c #7a7a23", +"^ c #7b7b2d", +"/ c #812e2a", +"( c #82392d", +") c #81332d", +"_ c #853a34", +"` c #843834", +"' c #833a7b", +"] c #8a443a", +"[ c #884438", +"{ c #8e4a42", +"} c #8d4542", +"| c #8b4055", +" . c #914e48", +".. c #94564a", +"X. c #955250", +"o. c #985b54", +"O. c #995d55", +"+. c #894679", +"@. c #90506f", +"#. c #995c7d", +"$. c #97624d", +"%. c #9e6a5b", +"&. c #9c6756", +"*. c #9e6460", +"=. c #8d6a64", +"-. c #a06a5d", +";. c #a1715d", +":. c #a26a66", +">. c #a97c6c", +",. c #a67568", +"<. c #ac7b74", +"1. c #ab7674", +"2. c #812f81", +"3. c #853a82", +"4. c #823081", +"5. c #8a4284", +"6. c #8d4a84", +"7. c #8f5080", +"8. c #945689", +"9. c #965792", +"0. c #9a6389", +"q. c #9d6397", +"w. c #a2658e", +"e. c #a16a99", +"r. c #a5778f", +"t. c #a77799", +"y. c #ad78aa", +"u. c #a76daa", +"i. c #81812b", +"p. c #878738", +"a. c #888837", +"s. c #8d8d40", +"d. c #919145", +"f. c #919149", +"g. c #979753", +"h. c #9c9c5a", +"j. c #9b9b54", +"k. c #9f8671", +"l. c #9b856c", +"z. c #aa826b", +"x. c #ae8772", +"c. c #b1847a", +"v. c #b08c75", +"b. c #b3897f", +"n. c #b19374", +"m. c #b6997d", +"M. c #a99e77", +"N. c #a1a25b", +"B. c #a4a465", +"V. c #abab73", +"C. c #adad79", +"Z. c #b6a079", +"A. c #b2b278", +"S. c #ab878d", +"D. c #ac8396", +"F. c #b78c86", +"G. c #b69182", +"H. c #b99c83", +"J. c #bc9a8b", +"K. c #bb9592", +"L. c #b183ab", +"P. c #b38ca3", +"I. c #bd98b7", +"U. c #b791a9", +"Y. c #bba385", +"T. c #bca696", +"R. c #bbbb8c", +"E. c #b8b785", +"W. c #bebe94", +"Q. c #bfa5a7", +"!. c #c19c97", +"~. c #c0a88d", +"^. c #c3a896", +"/. c #c3b48f", +"(. c #c7b698", +"). c #c6aba5", +"_. c #c6aab7", +"`. c #ccb7a8", +"'. c #cdb8b5", +"]. c #d0bbab", +"[. c #d1bbb3", +"{. c #c29bc2", +"}. c #caa9c6", +"|. c #d7bfd0", +" X c #d2b8ca", +".X c #c2c28e", +"XX c #c8c294", +"oX c #cbc59c", +"OX c #ccca9b", +"+X c #c4c595", +"@X c #cccaa3", +"#X c #ccc8a7", +"$X c #d0cba5", +"%X c #d3cbab", +"&X c #d1c5aa", +"*X c #d3c3b3", +"=X c #d8c4ba", +"-X c #d8cbbb", +";X c #d5cab7", +":X c #d4d4ab", +">X c #d6dcaa", +",X c #d8dbad", +" % % % ; % % ; % % ; % % ; % % % % % % % ; % % % % % % % % % ; % % % % ; % % % = = % % % % = % % % % % ; % % ; % % ; % % ; % / ", +"% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # ", +"% + + + + + + + + + + + + + + + + + + = % = = % % % @ + + + + + + + + + + + % % % $ = $ % + + + + + + + # + + + + + + # + + + % ", +"% + + + + + + + + + + + + # + + + + % rXUXSXDXcXcXaX6 . + + + + + + + + + 6 oX$X@XoXXXOXZ.# + + + + + + + + + + + + + + + + + % ", +"% + + + + + + + + + + + + + # + + + . F.IXIXIXIXPXPX,.. + + + + + + + + + %.qX3X6X,XX&.+ + + + + + + + + + + + + + + + + + ; ", +"% + + + + + + + # + + + + + + + + + + ` UXPXaX[.aXPX;X@ + + + + + + + + $ (.0X(.m./..wXM.+ + + + + + + + + + + + + # + + + + + ; ", +"; + + + + + + + + + + + + # + + + + + . :.IXSX- . [.IXG.. + + + + + + + v.nXH.. = XX6X] + + + + + + + + + + + + + + + + + + + % ", +"; + + + + + + + + + + + + + + + + + + + > SXIXO. *.PXaX; + + + + + + ; %XjX.. ..6X(.= + + + + # + + + + + + + + + + + + + # % ", +"% + + + + + + + # + + + + # + + + + + + + !.IX[.. ; zXJXO.. + + + + . O.kX#X= + m.9Xz.. + + + + + + + + + + + + + + + # + + + % ", +"% + + + + + + + + + + + + + + + + + + + + } IXGXr J.IX).+ + + + + + ^.bXx. w :X.mX(.+ $ (.9X$.. + + + + + + + + + + + + + + + + + + + + ; ", +"% + + + + + + + + + + + # + + + + + + + + @ q GXPX . ,.KX-X$ + + $ #XbX&. [ 7X$X: + + + + + + + # + + + + + + + + # + + # + % ", +"; + + + + + + + + + + + + + + + + + + + + + + ).IX^.. q vXMX{ . . .kX5X> . n.jXn.+ + + + + + + + + + + + + + + + + + + + + + ; ", +"% + # + + + + + + + + % > ; $ + + + + + + + . o.PXvX> . ^.KXJ.+ + J.BXH.. : %X8X[ . + + + + + . $ / { ._ : + + + + + + + + + % ", +"% + + + + + + + > ,.`.aXpXpX].x.( + + + + + + - sXPX:. ..HXyX; : yXlX] &.jX(.$ + + + + . ; <.-XxXVXVXkX1XH.[ + + + + + + + % ", +"; + + + + + # 1.vXIXKXxXhXpXlXBX0Xm.: + + + + F.IX[.+ % tXHXO.%.MX&X% + /.jX;.. + + + + ..sXIXJXaX].^.%XgXNX8Xn.- + + + + + % ", +"% + + + + % ).IXPX`.O.e ; 6 ] v.1XnXoX( + + + + ` GXFX` c.HX;XyXmX>. r 8X3Xw + + + . 1.PXPX].X.% @ + + e >.1XjX/.: + + + + % ", +"% + + + @ ^.IXcXo.. + # + + 5 m.qX$X( . + + + [.PXb. ` lXxXlXgXe z.nXY.+ + + . :.IXGX,.@ $ w ) ; + w #X8X/.% + + + % ", +"* + + . 1.IXDX` > c.].2X%XH.] . . ;.,X(.5 . + . :.PXaX% + `.MXxX^.+ = %XjX.. + _ PXPXO. ; c.-XlXlXyX~.[ ;.3X7X>.$ + + + % ", +"v 2 + / UXUX} .sXHXMXxXlXBXkXm.) ..OX6Xn.+ + . > vXLXX. &.MXmXO. ..jX#X; + + # [.IX<. r eXPXCXpX-XpXMXgXjX3X..+ + + + * g ", +"c l t w.IXDXe ,.PXFXG.w _ >.1XjX3XqX7X ~.1XZ.;.( - $ + + . { HXvXq . T.J.. w 2XgX_ . + + '.IXX. `.IXJ.# . + + + . ( w . @ < d l l k c ", +"c k k f x }.IXeX3 X J.JX;X: . . = - + . + + + + + + % -XKX,. ` 6 ,.bX(.$ + + > UXdX+ } IX=X$ + + + @ + + . & 1 f l l l k k c ", +"v k k k p z rXIX}.f d _.LX(.- + + + + + + + + + + + . <.KX*X$ . + $ `.bX;. + X.IXK.. !.IXX.. + + + @ , 1 f l l k k l k k k c ", +"c k k k k f m rXPXI.u n [.ZXT.< & @ + + + + + + + + + e vXcX] . . ] kX3X6 + + . 1.IX*.@ sXsX% @ , 2 d f f p p p f p p p f f k c ", +"c k k k k k f ' dXKXP.u n ;XNXP.f f a 1 < , & @ @ + + + (.KXF.. + G.BXH.+ + + . K.IX| 4 KX_.f f l l l l 6.6.6.6.6.+.+.+.+.+.z z ", +"c k k k k k k k 3.vXLXt.y C 2XnXt.p l l l l k k f a a o #.HXuX4 h 2XkX@.o a a t {.IX4.Z PXI.p k k k k z yXjXjX9XqX3X6X>XXN.I E ", +"U P P P F D G M 2.x p p p U.nX&Xm p S.6X(.B p l k k k k k p e.mXlX0.p l k k k k x fXIXC x dXJX9.u p f z '.*X;X3XqXk.O B.>Xa.H R ", +"R P P U p.B.+XkXDXU.N i u f U.nX).b k K.6XT.b p k k k l l f Z hXpXm k k k k k k p y.IXI.y 9.KXFXq.x p p x A ).jX+XY Q +#include + +#include "bitmaps/new.xpm" +#include "bitmaps/save.xpm" +#include "bitmaps/help.xpm" +#include "SVGlogo24.xpm" + +class MyChild; + +// Define a new application +class MyApp : public wxApp +{ + public: + bool OnInit(); +}; + +// Define a new frame +class MyFrame : public wxMDIParentFrame +{ + public: + int nWinCreated; + + wxList m_children; + + MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title, + const wxPoint& pos, const wxSize& size, const long style); + + void InitToolBar(wxToolBar* toolBar); + + void OnSize(wxSizeEvent& event); + void OnAbout(wxCommandEvent& event); + void OnNewWindow(wxCommandEvent& event); + void OnQuit(wxCommandEvent& event); + void OnClose(wxCloseEvent& event); + void FileSavePicture (wxCommandEvent & WXUNUSED(event) ) ; + + DECLARE_EVENT_TABLE() +}; + + +class MyCanvas : public wxScrolledWindow +{ + public: + int m_index ; + + MyChild * m_child ; + MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size); + virtual void OnDraw(wxDC& dc); + + DECLARE_EVENT_TABLE() +}; + +class MyChild: public wxMDIChildFrame +{ + public: + MyCanvas *m_canvas; + MyFrame *m_frame ; + + //////////////////// Methods + + MyChild(wxMDIParentFrame *parent, const wxString& title, const wxPoint& pos, const wxSize& size, const long style); + ~MyChild(); + + void OnActivate(wxActivateEvent& event); + void OnQuit(wxCommandEvent& event); + void OnClose(wxCloseEvent& event); + bool OnSave(wxString filename) ; + + DECLARE_EVENT_TABLE() +}; + +// menu items ids +enum +{ + MDI_QUIT = 100, + MDI_NEW_WINDOW, + MDI_SAVE, + MDI_REFRESH, + MDI_CHILD_QUIT, + MDI_ABOUT +}; + + +IMPLEMENT_APP(MyApp) + +// --------------------------------------------------------------------------- +// global variables +// --------------------------------------------------------------------------- + +MyFrame *frame = (MyFrame *) NULL; + +// --------------------------------------------------------------------------- +// event tables +// --------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame) +EVT_MENU(MDI_ABOUT, MyFrame::OnAbout) +EVT_MENU(MDI_NEW_WINDOW, MyFrame::OnNewWindow) +EVT_MENU(MDI_QUIT, MyFrame::OnQuit) +EVT_MENU (MDI_SAVE, MyFrame::FileSavePicture) +EVT_CLOSE(MyFrame::OnClose) + +EVT_SIZE(MyFrame::OnSize) +END_EVENT_TABLE() + +// =========================================================================== +// implementation +// =========================================================================== + +// --------------------------------------------------------------------------- +// MyApp +// --------------------------------------------------------------------------- + +// Initialise this in OnInit, not statically +bool MyApp::OnInit() +{ + // Create the main frame window + + frame = new MyFrame((wxFrame *)NULL, -1, wxT("SVG Demo"), + wxPoint(-1, -1), wxSize(500, 400), + wxDEFAULT_FRAME_STYLE | wxHSCROLL | wxVSCROLL); + + + // Make a menubar + wxMenu *file_menu = new wxMenu; + + file_menu->Append(MDI_NEW_WINDOW, wxT("&New test\tCtrl+N")); + file_menu->Append(MDI_QUIT, wxT("&Exit\tAlt+X")); + + wxMenu *help_menu = new wxMenu; + help_menu->Append(MDI_ABOUT, wxT("&About")); + + wxMenuBar *menu_bar = new wxMenuBar; + + menu_bar->Append(file_menu, wxT("&File")); + menu_bar->Append(help_menu, wxT("&Help")); + + // Associate the menu bar with the frame + frame->SetMenuBar(menu_bar); + + frame->CreateStatusBar(); + + frame->Show(TRUE); + + SetTopWindow(frame); + + return TRUE; +} + + +// --------------------------------------------------------------------------- +// MyFrame +// --------------------------------------------------------------------------- + +// Define my frame constructor +MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title, + const wxPoint& pos, const wxSize& size, const long style) + : wxMDIParentFrame(parent, id, title, pos, size, style) +{ + nWinCreated = 0 ; + + // Give it an icon + SetIcon(wxICON(mondrian)); + + CreateToolBar(wxNO_BORDER | wxTB_FLAT | wxTB_HORIZONTAL); + InitToolBar(GetToolBar()); + +} + + +void MyFrame::OnClose(wxCloseEvent& event) +{ + if ( !event.CanVeto() ) + { + event.Skip(); + return ; + } + if ( m_children.Number () < 1 ) + { + event.Skip(); + return ; + } + // now try the children + wxNode * pNode = m_children.GetFirst (); + wxNode * pNext ; + MyChild * pChild ; + while ( pNode ) + { + pNext = pNode -> GetNext (); + pChild = (MyChild*) pNode -> Data (); + if (pChild -> Close ()) + { + delete pNode ; + } + else + { + event.Veto(); + return; + } + pNode = pNext ; + } + event.Skip(); +} + + +void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(); +} + + +void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) +{ + (void)wxMessageBox(wxT("wxWindows 2.0 SVG 1.0 Test\n" + "Author: Chris Elliott (c) 2002\n" + "Usage: svg.exe \nClick File | New to show tests\n\n"), wxT("About SVG Test")); +} + + +void MyFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event) ) +{ + // Make another frame, containing a canvas + MyChild *subframe ; + + m_children.Append (new MyChild(frame, wxT("SVG Frame"), + wxPoint(-1, -1), wxSize(-1, -1), + wxDEFAULT_FRAME_STYLE ) ) ; + + subframe = (MyChild *) m_children.GetLast() -> Data (); + wxString title; + title.Printf(wxT("SVG Test Window %d"), nWinCreated ); + // counts number of children previously, even if now closed + nWinCreated ++ ; + + // Give it a title and icon + subframe->SetTitle(title); + subframe->SetIcon(wxICON(mondrian)); + + // Make a menubar + wxMenu *file_menu = new wxMenu; + + file_menu->Append(MDI_NEW_WINDOW, wxT("&Another test\tCtrl+N")); + file_menu->Append(MDI_SAVE, wxT("&Save\tCtrl+S"), wxT("Save in SVG format")); + file_menu->Append(MDI_CHILD_QUIT, wxT("&Close child\tCtrl+F4")); + file_menu->Append(MDI_QUIT, wxT("&Exit\tAlt+X")); + + wxMenu *help_menu = new wxMenu; + help_menu->Append(MDI_ABOUT, wxT("&About")); + + wxMenuBar *menu_bar = new wxMenuBar; + + menu_bar->Append(file_menu, wxT("&File")); + menu_bar->Append(help_menu, wxT("&Help")); + + // Associate the menu bar with the frame + subframe->SetMenuBar(menu_bar); + + subframe->Show(TRUE); +} + + +void MyFrame::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + int w, h; + GetClientSize(&w, &h); + + GetClientWindow()->SetSize(0, 0, w, h); +} + + +void MyFrame::InitToolBar(wxToolBar* toolBar) +{ + const int maxBitmaps = 3 ; + wxBitmap* bitmaps[maxBitmaps]; + + bitmaps[0] = new wxBitmap( new_xpm ); + bitmaps[1] = new wxBitmap( save_xpm ); + bitmaps[2] = new wxBitmap( help_xpm ); + + int width = 16; + int currentX = 5; + + toolBar->AddTool( MDI_NEW_WINDOW, *(bitmaps[0]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, wxT("New SVG test window")); + currentX += width + 5; + toolBar->AddTool( MDI_SAVE, *bitmaps[1], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, wxT("Save test in SVG format")); + currentX += width + 5; + toolBar->AddSeparator(); + toolBar->AddTool(MDI_ABOUT, *bitmaps[2], wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, wxT("Help")); + + toolBar->Realize(); + + int i; + for (i = 0; i < maxBitmaps; i++) + delete bitmaps[i]; +} + + +void MyFrame::FileSavePicture (wxCommandEvent & WXUNUSED(event) ) +{ + MyChild * pChild = (MyChild *)GetActiveChild (); + if (pChild == NULL) + { + return ; + } + + wxFileDialog dialog(this, wxT("Save Picture as"), wxEmptyString, pChild->GetTitle(), + wxT("SVG vector picture files (*.svg)|*.svg"), + wxSAVE|wxOVERWRITE_PROMPT); + + if (dialog.ShowModal() == wxID_OK) + { + if (!pChild -> OnSave ( dialog.GetPath() )) + { + return ; + } + } + return ; +} + + +// Note that MDI_NEW_WINDOW and MDI_ABOUT commands get passed +// to the parent window for processing, so no need to +// duplicate event handlers here. +BEGIN_EVENT_TABLE(MyChild, wxMDIChildFrame) + EVT_MENU(MDI_CHILD_QUIT, MyChild::OnQuit) + EVT_CLOSE(MyChild::OnClose) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) + +END_EVENT_TABLE() + +// --------------------------------------------------------------------------- +// MyCanvas +// --------------------------------------------------------------------------- + +// Define a constructor for my canvas +MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size) +: wxScrolledWindow(parent, -1, pos, size, +wxSUNKEN_BORDER|wxVSCROLL|wxHSCROLL) +{ + m_child = (MyChild *) parent ; + SetBackgroundColour(wxColour("WHITE")); + m_index = m_child->m_frame->nWinCreated % 7 ; +} + + +// Define the repainting behaviour +void MyCanvas::OnDraw(wxDC& dc) +{ + // vars to use ... + wxString s ; + wxPen wP ; + wxBrush wB ; + wxPoint points[6]; + wxColour wC; + wxFont wF ; + + dc.SetFont(*wxSWISS_FONT); + dc.SetPen(*wxGREEN_PEN); + + + switch (m_index) + { + default: + case 0: + // draw lines to make a cross + dc.DrawLine(0, 0, 200, 200); + dc.DrawLine(200, 0, 0, 200); + // draw point colored line and spline + wP = *wxCYAN_PEN ; + wP.SetWidth(3); + dc.SetPen(wP); + + dc.DrawPoint (25,15) ; + dc.DrawLine(50, 30, 200, 30); + dc.DrawSpline(50, 200, 50, 100, 200, 10); + s = wxT("Green Cross, Cyan Line and spline"); + break ; + + case 1: + // draw standard shapes + dc.SetBrush(*wxCYAN_BRUSH); + dc.SetPen(*wxRED_PEN); + dc.DrawRectangle(10, 10, 100, 70); + wB = wxBrush ("DARK ORCHID", wxTRANSPARENT); + dc.SetBrush (wB); + dc.DrawRoundedRectangle(50, 50, 100, 70, 20); + dc.SetBrush (wxBrush("GOLDENROD", wxSOLID) ); + dc.DrawEllipse(100, 100, 100, 50); + + points[0].x = 100; points[0].y = 200; + points[1].x = 70; points[1].y = 260; + points[2].x = 160; points[2].y = 230; + points[3].x = 40; points[3].y = 230; + points[4].x = 130; points[4].y = 260; + points[5].x = 100; points[5].y = 200; + + dc.DrawPolygon(5, points); + dc.DrawLines (6, points, 160); + s = wxT("Blue rectangle, red edge, clear rounded rectangle, gold ellipse, gold and clear stars"); + break ; + + case 2: + // draw text in Arial or similar font + dc.DrawLine(50,25,50,35); + dc.DrawLine(45,30,55,30); + dc.DrawText(wxT("This is a Swiss-style string"), 50, 30); + wC = dc.GetTextForeground() ; + dc.SetTextForeground ("FIREBRICK"); + + // no effect in msw ?? + dc.SetTextBackground ("WHEAT"); + dc.DrawText(wxT("This is a Red string"), 50, 200); + dc.DrawRotatedText(wxT("This is a 45 deg string"), 50, 200, 45); + dc.DrawRotatedText(wxT("This is a 90 deg string"), 50, 200, 90); + wF = wxFont ( 18, wxROMAN, wxITALIC, wxBOLD, FALSE, wxT("Times New Roman")); + dc.SetFont(wF); + dc.SetTextForeground (wC) ; + dc.DrawText(wxT("This is a Times-style string"), 50, 60); + s = wxT("Swiss, Times text; red text, rotated and colored orange"); + break ; + + case 3 : + // four arcs start and end points, center + dc.SetBrush(*wxGREEN_BRUSH); + dc.DrawArc ( 200,300, 370,230, 300.0,300.0 ); + dc.SetBrush(*wxBLUE_BRUSH); + dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270.0,270.0 ); + dc.SetDeviceOrigin(-10,-10); + dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270.0,270.0 ); + dc.SetDeviceOrigin(0,0); + + wP.SetColour ("CADET BLUE"); + dc.SetPen(wP); + dc.DrawArc ( 75,125, 110, 40, 75.0, 75.0 ); + + wP.SetColour ("SALMON"); + dc.SetPen(wP); + dc.SetBrush(*wxRED_BRUSH); + //top left corner, width and height, start and end angle + // 315 same center and x-radius as last pie-arc, half Y radius + dc.DrawEllipticArc(25,50,100,50,180.0,45.0) ; + + wP = *wxCYAN_PEN ; + wP.SetWidth(3); + dc.SetPen(wP); + //wxTRANSPARENT)); + dc.SetBrush (wxBrush ("SALMON",wxSOLID)) ; + dc.DrawEllipticArc(300, 0,200,100, 0.0,145.0) ; + //same end point + dc.DrawEllipticArc(300, 50,200,100,90.0,145.0) ; + dc.DrawEllipticArc(300,100,200,100,90.0,345.0) ; + + s = wxT("This is an arc test page"); + break ; + + case 4: + dc.DrawCheckMark ( 30,30,25,25); + dc.SetBrush (wxBrush ("SALMON",wxTRANSPARENT)); + dc.DrawCheckMark ( 80,50,75,75); + dc.DrawRectangle ( 80,50,75,75); + s = wxT("Two check marks"); + break ; + + case 5: + wF = wxFont ( 18, wxROMAN, wxITALIC, wxBOLD, FALSE, wxT("Times New Roman")); + dc.SetFont(wF); + dc.DrawLine(0, 0, 200, 200); + dc.DrawLine(200, 0, 0, 200); + dc.DrawText(wxT("This is an 18pt string"), 50, 60); + + // rescale and draw in blue + wP = *wxCYAN_PEN ; + dc.SetPen(wP); + dc.SetUserScale (2.0,0.5); + dc.SetDeviceOrigin(200,0); + dc.DrawLine(0, 0, 200, 200); + dc.DrawLine(200, 0, 0, 200); + dc.DrawText(wxT("This is an 18pt string 2 x 0.5 UserScaled"), 50, 60); + dc.SetUserScale (2.0,2.0); + dc.SetDeviceOrigin(200,200); + dc.DrawText(wxT("This is an 18pt string 2 x 2 UserScaled"), 50, 60); + + wP = *wxRED_PEN ; + dc.SetPen(wP); + dc.SetUserScale (1.0,1.0); + dc.SetDeviceOrigin(0,10); + dc.SetMapMode (wxMM_METRIC) ; //svg ignores this + dc.DrawLine(0, 0, 200, 200); + dc.DrawLine(200, 0, 0, 200); + dc.DrawText(wxT("This is an 18pt string in MapMode"), 50, 60); + s = wxT("Scaling test page"); + break ; + + case 6: + dc.DrawIcon( wxICON(mondrian), 10, 10 ); + dc.DrawBitmap ( wxBITMAP (svgbitmap), 50,15); + s = wxT("Icon and Bitmap "); + break ; + + } + m_child->SetStatusText(s); +} + + + + +// --------------------------------------------------------------------------- +// MyChild +// --------------------------------------------------------------------------- + +MyChild::MyChild(wxMDIParentFrame *parent, const wxString& title, +const wxPoint& pos, const wxSize& size, +const long style) +: wxMDIChildFrame(parent, -1, title, pos, size, style) +{ + + m_frame = (MyFrame *) parent ; + CreateStatusBar(); + SetStatusText(title); + + int w, h ; + GetClientSize ( &w, &h ); + m_canvas = new MyCanvas(this, wxPoint(0, 0), wxSize (w,h) ); + // Give it scrollbars + m_canvas->SetScrollbars(20, 20, 50, 50); + +} + + +MyChild::~MyChild() +{ + m_frame->m_children.DeleteObject(this); +} + + +void MyChild::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(TRUE); +} + + +bool MyChild::OnSave(wxString filename) +{ + wxSVGFileDC svgDC (filename, 600, 650) ; + m_canvas->OnDraw (svgDC); + return svgDC.Ok(); +} + + + +void MyChild::OnActivate(wxActivateEvent& event) +{ + if ( event.GetActive() && m_canvas ) + m_canvas->SetFocus(); +} + + +void MyChild::OnClose(wxCloseEvent& event) +{ + event.Skip(); +} diff --git a/contrib/src/svg/Makefile.in b/contrib/src/svg/Makefile.in new file mode 100644 index 0000000000..9dc158100a --- /dev/null +++ b/contrib/src/svg/Makefile.in @@ -0,0 +1,10 @@ +# $Id$ + +CONTRIB_SAMPLES=canvas fl gizmos mmedia net ogl plot stc svg xrc #applet + +all: + @for d in $(CONTRIB_SAMPLES); do (cd $$d && $(MAKE)); done + +clean: + @for d in $(CONTRIB_SAMPLES); do (cd $$d && $(MAKE) clean); done + diff --git a/contrib/src/svg/dcsvg.cpp b/contrib/src/svg/dcsvg.cpp new file mode 100644 index 0000000000..d59ecb0277 --- /dev/null +++ b/contrib/src/svg/dcsvg.cpp @@ -0,0 +1,856 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: svg.cpp +// Purpose: SVG sample +// Author: Chris Elliott +// Modified by: +// RCS-ID: $Id$ +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +#include "wx/svg/dcsvg.h" + +#include +#include "wx/image.h" + +#define wxSVG_DEBUG FALSE +// or TRUE to see the calls being executed +#define newline wxString(wxT("\n")) +#define space wxString(wxT(" ")) +#define semicolon wxString(wxT(";")) +#define wx_round(a) (int)((a)+.5) + +#ifdef __BORLANDC__ +#pragma warn -rch +#pragma warn -ccc +#endif + +static inline double DegToRad(double deg) { return (deg * 3.14) / 180.0; } ; + +wxString wxColStr ( wxColour c ) +{ + unsigned char r, g, b ; + r = c.Red (); + g = c.Green (); + b = c. Blue (); + + // possible Unicode bug here + wxString s = wxDecToHex(r) + wxDecToHex(g) + wxDecToHex(b) ; + return s ; +} + + +wxString wxBrushString ( wxColour c, int style ) +{ + wxString s = wxT("fill:#") + wxColStr (c) + semicolon + space ; + switch ( style ) + { + case wxSOLID : + s = s + wxT("fill-opacity:1.0; "); + break ; + case wxTRANSPARENT: + s = s + wxT("fill-opacity:0.0; "); + break ; + + default : + wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::Requested Brush Style not available")) ; + + } + s = s + newline ; + return s ; +} + + +void wxSVGFileDC::Init (wxString f, int Width, int Height, float dpi) + +{ + //set up things first wxDCBase does all this? + m_width = Width ; + m_height = Height ; + + m_clipping = FALSE; + m_OK = TRUE; + + m_mm_to_pix_x = dpi/25.4; + m_mm_to_pix_y = dpi/25.4; + + m_signX = m_signY = 1; + + m_userScaleX = m_userScaleY = + m_deviceOriginX = m_deviceOriginY = 0; + + m_OriginX = m_OriginY = 0; + m_logicalOriginX = m_logicalOriginY = 0; + m_logicalScaleX = m_logicalScaleY = 0 ; + m_scaleX = m_scaleY = 1.0 ; + + m_logicalFunction = wxCOPY; + m_backgroundMode = wxTRANSPARENT; + m_mappingMode = wxMM_TEXT; + + m_backgroundBrush = *wxTRANSPARENT_BRUSH; + m_textForegroundColour = *wxBLACK; + m_textBackgroundColour = *wxWHITE; + m_colour = wxColourDisplay(); + + m_pen = *wxBLACK_PEN; + m_font = *wxNORMAL_FONT; + m_brush = *wxWHITE_BRUSH; + + m_graphics_changed = TRUE ; + + ////////////////////code here + + m_outfile = new wxFileOutputStream(f) ; + m_OK = m_outfile->Ok (); + if (m_OK) + { + m_filename = f ; + m_sub_images = 0 ; + wxString s ; + s = wxT("") ; s = s + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + s = wxT("Write (s.c_str(), s.Len() ) ; + s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + s.Printf ( wxT(" \n"), float(Width)/dpi*2.54, float(Height)/dpi*2.54, Width, Height ); + m_outfile->Write (s.c_str(), s.Len() ) ; + s = wxT("SVG Picture created as ") + wxFileNameFromPath(f) + wxT(" ") + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + s = wxString (wxT("Picture generated by wxSVG ")) + wxSVGVersion + wxT(" ")+ newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + s = wxT("") + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + + } + m_OK = m_outfile->Ok (); +} + + +// constructors +wxSVGFileDC::wxSVGFileDC (wxString f) +{ + // quarter 640x480 screen display at 72 dpi + Init (f,320,240,72.0); +}; + +wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height) +{ + Init (f,Width,Height,72.0); +}; + +wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height, float dpi) +{ + Init (f,Width,Height,dpi); +}; + +wxSVGFileDC::~wxSVGFileDC() +{ + wxString s = wxT(" \n \n") ; + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + delete m_outfile ; +} + + +////////////////////////////////////////////////////////////////////////////////////////// + +void wxSVGFileDC::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) +{ + if (m_graphics_changed) NewGraphics (); + wxString s ; + s.Printf ( wxT(" \n"), x1,y1,x2,y2 ); + if (m_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok (); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawLine Call executed")) ; + CalcBoundingBox(x1, y1) ; + CalcBoundingBox(x2, y2) ; + return; +}; + +void wxSVGFileDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset ) +{ + for ( int i = 1; i < n ; i++ ) + { + DoDrawLine ( points [i-1].x + xoffset, points [i-1].y + yoffset, + points [ i ].x + xoffset, points [ i ].y + yoffset ) ; + } +} + + +void wxSVGFileDC::DoDrawPoint (wxCoord x1, wxCoord y1) +{ + wxString s; + if (m_graphics_changed) NewGraphics (); + s = wxT(" ") + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + DrawLine ( x1,y1,x1,y1 ); + s = wxT(""); + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); +} + + +void wxSVGFileDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height) +{ + wxDCBase::DoDrawCheckMark (x1,y1,width,height) ; +} + + +void wxSVGFileDC::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1) +{ + DoDrawRotatedText(text, x1,y1,0.0); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawText Call executed")) ; +} + + +void wxSVGFileDC::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle) +{ + //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW + if (m_graphics_changed) NewGraphics (); + wxString s, sTmp; + + // calculate bounding box + wxCoord w, h, desc ; + DoGetTextExtent(sText, &w, &h, &desc); + + double rad = DegToRad(angle); + + // wxT("upper left") and wxT("upper right") + CalcBoundingBox(x, y); + CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); + + // wxT("bottom left") and wxT("bottom right") + x += (wxCoord)(h*sin(rad)); + y += (wxCoord)(h*cos(rad)); + CalcBoundingBox(x, y); + CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); + + if (m_backgroundMode == wxSOLID) + { + // draw background first + // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ; + sTmp.Printf ( wxT(" "), -angle, x,y ) ; + s = s + sTmp + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + } + //now do the text itself + s.Printf (wxT(" 0) s = s + wxT("style=\"font-family:") + sTmp + wxT("; "); + else s = s + wxT("style=\" ") ; + + wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") }; + s = s + wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + semicolon + space; + + wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") }; + s = s + wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + semicolon + space; + + sTmp.Printf (wxT("font-size:%dpt; fill:#"), m_font.GetPointSize () ); + s = s + sTmp ; + s = s + wxColStr (m_textForegroundColour) + wxT("; stroke:#") + wxColStr (m_textForegroundColour) + wxT("; ") ; + sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle, x,y ) ; + s = s + sTmp + sText + wxT(" ") + newline ; + if (m_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok (); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ; + +} + + +void wxSVGFileDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) +{ + DoDrawRoundedRectangle(x, y, width, height, 0) ; +} + + +void wxSVGFileDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) + +{ + if (m_graphics_changed) NewGraphics (); + wxString s ; + + s.Printf ( wxT(" ") + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ; + CalcBoundingBox(x, y) ; + CalcBoundingBox(x + width, y + height) ; + +} + + +void wxSVGFileDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle) +{ + if (m_graphics_changed) NewGraphics (); + wxString s, sTmp ; + s = wxT(" ") ; + s = s + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ; +} + + +void wxSVGFileDC::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height) + +{ + if (m_graphics_changed) NewGraphics (); + + int rh = height /2 ; + int rw = width /2 ; + + wxString s; + s.Printf ( wxT(" ") + newline ; + + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ; + CalcBoundingBox(x, y) ; + CalcBoundingBox(x + width, y + height) ; +} + + +void wxSVGFileDC::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc) +{ + /* Draws an arc of a circle, centred on (xc, yc), with starting point + (x1, y1) and ending at (x2, y2). The current pen is used for the outline + and the current brush for filling the shape. + + The arc is drawn in an anticlockwise direction from the start point to + the end point. + + Might be better described as Pie drawing */ + + if (m_graphics_changed) NewGraphics (); + wxString s ; + + // we need the radius of the circle which has two estimates + double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) ); + double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) ); + + wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ; + if ( fabs ( r2-r1 ) > 3 ) //pixels + { + s = wxT(" \n") ; + m_outfile->Write (s.c_str(), s.Len() ) ; + } + + double theta1 = atan2(yc-y1,x1-xc); + if ( theta1 < 0 ) theta1 = theta1 + 3.14 * 2; + double theta2 = atan2(yc-y2, x2-xc); + if ( theta2 < 0 ) theta2 = theta2 + 3.14 * 2; + if ( theta2 < theta1 ) theta2 = theta2 + 3.14 *2 ; + + int fArc ; // flag for large or small arc 0 means less than 180 degrees + if ( fabs((theta2 - theta1) > 3.14 )) fArc = 1; else fArc = 0 ; + + int fSweep = 0 ; // flag for sweep always 0 + + s.Printf ( wxT(" ") + newline ; + + + if (m_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed")) ; +} + + +void wxSVGFileDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea) +{ + /* + Draws an arc of an ellipse. The current pen is used for drawing the arc + and the current brush is used for drawing the pie. This function is + currently only available for X window and PostScript device contexts. + + x and y specify the x and y coordinates of the upper-left corner of the + rectangle that contains the ellipse. + + width and height specify the width and height of the rectangle that + contains the ellipse. + + start and end specify the start and end of the arc relative to the + three-o'clock position from the center of the rectangle. Angles are + specified in degrees (360 is a complete circle). Positive values mean + counter-clockwise motion. If start is equal to end, a complete ellipse + will be drawn. */ + + //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW + + if (m_graphics_changed) NewGraphics (); + + wxString s ; + //radius + double rx = w / 2 ; + double ry = h / 2 ; + // center + double xc = x + rx ; + double yc = y + ry ; + + double xs, ys, xe, ye ; + xs = xc + rx * cos (DegToRad(sa)) ; + xe = xc + rx * cos (DegToRad(ea)) ; + ys = yc - ry * sin (DegToRad(sa)) ; + ye = yc - ry * sin (DegToRad(ea)) ; + + ///now same as circle arc... + + double theta1 = atan2(ys-yc, xs-xc); + double theta2 = atan2(ye-yc, xe-xc); + + int fArc ; // flag for large or small arc 0 means less than 180 degrees + if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0 ; + + int fSweep ; + if ( fabs( (theta2 - theta1) > 3.14)) fSweep = 1; else fSweep = 0 ; + + s.Printf ( wxT(" ") + newline ; + + if (m_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ; +} + + +void wxSVGFileDC::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , wxFont *font) const + +{ + wxScreenDC sDC ; + + sDC.SetFont (m_font); + if ( font != NULL ) sDC.SetFont ( *font ); + sDC.GetTextExtent(string, w, h, descent, externalLeading ); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed")) ; +} + + +wxCoord wxSVGFileDC::GetCharHeight() const + +{ + wxScreenDC sDC ; + sDC.SetFont (m_font); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing")) ; + return ( sDC.GetCharHeight() ); + +} + + +wxCoord wxSVGFileDC::GetCharWidth() const +{ + wxScreenDC sDC ; + sDC.SetFont (m_font); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing")) ; + return ( sDC.GetCharWidth() ) ; + +} + + +/// Set Functions ///////////////////////////////////////////////////////////////// +void wxSVGFileDC::SetBackground( const wxBrush &brush ) +{ + + m_backgroundBrush = brush; + return; +} + + +void wxSVGFileDC::SetBackgroundMode( int mode ) +{ + m_backgroundMode = mode; + return; +} + + +void wxSVGFileDC::SetBrush(const wxBrush& brush) + +{ + m_brush = brush ; + + m_graphics_changed = TRUE ; + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed")) ; +} + + +void wxSVGFileDC::SetPen(const wxPen& pen) +{ + // width, color, ends, joins : currently implemented + // dashes, stipple : not implemented + m_pen = pen ; + + m_graphics_changed = TRUE ; + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed")) ; +} + +void wxSVGFileDC::NewGraphics () +{ + + int w = m_pen.GetWidth (); + wxColour c = m_pen.GetColour () ; + + wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn; + + sBrush = wxT("\n \n") ; + } + + sLast.Printf ( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"), + w, m_OriginX, m_OriginY, m_scaleX, m_scaleY ); + + s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn; + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + m_graphics_changed = FALSE ; + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed")) ; +} + + +void wxSVGFileDC::SetFont(const wxFont& font) + +{ + m_font = font ; + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed")) ; +} + + +void wxSVGFileDC::ComputeScaleAndOrigin() +{ + m_scaleX = m_logicalScaleX * m_userScaleX; + m_scaleY = m_logicalScaleY * m_userScaleY; + m_OriginX = m_logicalOriginX * m_logicalScaleX + m_deviceOriginX ; + m_OriginY = m_logicalOriginY * m_logicalScaleY + m_deviceOriginY ; + m_graphics_changed = TRUE; +} + + +int wxSVGFileDC::GetMapMode() +{ + return m_mappingMode ; +} + + +void wxSVGFileDC::SetMapMode( int mode ) +{ + switch (mode) + { + case wxMM_TWIPS: + SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y ); + break; + case wxMM_POINTS: + SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y ); + break; + case wxMM_METRIC: + SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y ); + break; + case wxMM_LOMETRIC: + SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 ); + break; + default: + case wxMM_TEXT: + SetLogicalScale( 1.0, 1.0 ); + break; + } + m_mappingMode = mode; + + /* we don't do this mega optimisation + if (mode != wxMM_TEXT) + { + m_needComputeScaleX = TRUE; + m_needComputeScaleY = TRUE; + } + */ +} + + +void wxSVGFileDC::GetUserScale(double *x, double *y) const +{ + *x = m_userScaleX ; + *y = m_userScaleY ; +} + + +void wxSVGFileDC::SetUserScale( double x, double y ) +{ + // allow negative ? -> no + m_userScaleX = x; + m_userScaleY = y; + ComputeScaleAndOrigin(); +} + + +void wxSVGFileDC::SetLogicalScale( double x, double y ) +{ + // allow negative ? + m_logicalScaleX = x; + m_logicalScaleY = y; + ComputeScaleAndOrigin(); +} + + +void wxSVGFileDC::SetLogicalOrigin( wxCoord x, wxCoord y ) +{ + // is this still correct ? + m_logicalOriginX = x * m_signX; + m_logicalOriginY = y * m_signY; + ComputeScaleAndOrigin(); +} + + +void wxSVGFileDC::SetDeviceOrigin( wxCoord x, wxCoord y ) +{ + // only wxPostScripDC has m_signX = -1, + m_deviceOriginX = x; + m_deviceOriginY = y; + ComputeScaleAndOrigin(); +} + + +void wxSVGFileDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) +{ + // only wxPostScripDC has m_signX = -1, + m_signX = (xLeftRight ? 1 : -1); + m_signY = (yBottomUp ? -1 : 1); + ComputeScaleAndOrigin(); +} + + +// export a bitmap as a raster image in png +bool wxSVGFileDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, + wxDC* source, wxCoord xsrc, wxCoord ysrc, + int logicalFunc /*= wxCOPY*/, bool useMask /*= FALSE*/, + wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/) +{ + + if (logicalFunc != wxCOPY) + { + wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ; + return FALSE ; + } + if (useMask != FALSE) + { + wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ; + return FALSE ; + } + wxBitmap myBitmap (width, height) ; + wxMemoryDC memDC; + memDC.SelectObject( myBitmap ); + memDC.Blit(0, 0, width, height, source, xsrc, ysrc); + memDC.SelectObject( wxNullBitmap ); + DoDrawBitmap(myBitmap, xdest, ydest); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed")) ; + return FALSE ; +} + + +void wxSVGFileDC::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y) +{ + wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() ) ; + wxMemoryDC memDC; + memDC.SelectObject( myBitmap ); + memDC.DrawIcon(myIcon,0,0); + memDC.SelectObject( wxNullBitmap ); + DoDrawBitmap(myBitmap, x, y); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ; + return ; +} + + + +void wxSVGFileDC::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool bTransparent /*=0*/ ) +{ + if (m_graphics_changed) NewGraphics (); + + wxString sTmp, s, sPNG ; + wxImage::AddHandler(new wxPNGHandler); + +// create suitable file name + sTmp.Printf ( wxT("_image%d.png"), m_sub_images); + sPNG = m_filename.BeforeLast(wxT('.')) + sTmp; + while (wxFile::Exists(sPNG) ) + { + m_sub_images ++ ; + sTmp.Printf ( wxT("_image%d.png"), m_sub_images); + sPNG = m_filename.BeforeLast(wxT('.')) + sTmp; + } + +//create copy of bitmap (wxGTK doesn't like saving a constant bitmap) + wxBitmap myBitmap = bmp ; +//save it + bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG); + +// refrence the bitmap from the SVG doc + int w = myBitmap.GetWidth(); + int h = myBitmap.GetHeight(); + sTmp.Printf ( wxT(" \n"), sPNG.c_str() ); + s = s + sTmp + wxT("Image from wxSVG ") + newline; + + if (m_OK && bPNG_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok () && bPNG_OK; + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ; + + return ; +} + + +// --------------------------------------------------------------------------- +// coordinates transformations +// --------------------------------------------------------------------------- + +wxCoord wxSVGFileDC::DeviceToLogicalX(wxCoord x) const +{ + return XDEV2LOG(x); +} + + +wxCoord wxSVGFileDC::DeviceToLogicalY(wxCoord y) const +{ + return YDEV2LOG(y); +} + + +wxCoord wxSVGFileDC::DeviceToLogicalXRel(wxCoord x) const +{ + return XDEV2LOGREL(x); +} + + +wxCoord wxSVGFileDC::DeviceToLogicalYRel(wxCoord y) const +{ + return YDEV2LOGREL(y); +} + + +wxCoord wxSVGFileDC::LogicalToDeviceX(wxCoord x) const +{ + return XLOG2DEV(x); +} + + +wxCoord wxSVGFileDC::LogicalToDeviceY(wxCoord y) const +{ + return YLOG2DEV(y); +} + + +wxCoord wxSVGFileDC::LogicalToDeviceXRel(wxCoord x) const +{ + return XLOG2DEVREL(x); +} + + +wxCoord wxSVGFileDC::LogicalToDeviceYRel(wxCoord y) const +{ + return YLOG2DEVREL(y); +} + + +#ifdef __BORLANDC__ +#pragma warn .rch +#pragma warn .ccc +#endif diff --git a/contrib/src/svg/makefile.b32 b/contrib/src/svg/makefile.b32 new file mode 100644 index 0000000000..7854ed1e3b --- /dev/null +++ b/contrib/src/svg/makefile.b32 @@ -0,0 +1,19 @@ +# +# File: makefile.b32 +# Author: Julian Smart/Chris Elliott +# Created: 1999/2002 +# Updated: +# Copyright: +# +# Makefile : Builds SVG library for 32-bit BC++ + +WXDIR = $(WXWIN) + +EXTRACPPFLAGS=-Icontrib/include + +LIBTARGET=$(WXDIR)\lib\dcsvg.lib + +OBJECTS = dcsvg.obj + +!include $(WXDIR)\src\makelib.b32 + diff --git a/contrib/src/svg/makefile.g95 b/contrib/src/svg/makefile.g95 new file mode 100644 index 0000000000..db540c6e99 --- /dev/null +++ b/contrib/src/svg/makefile.g95 @@ -0,0 +1,16 @@ +# +# File: makefile.g95 +# Author: Julian Smart +# Created: 1999 +# Updated: +# Copyright: (c) Julian Smart, 1999 +# +# Makefile for wxWindows dcsvg library Cygwin/Mingw32). + +WXDIR = ../../.. + +LIBTARGET=$(WXDIR)/lib/libdcsvg.a +OBJECTS = dcsvg.o + +include $(WXDIR)/src/makelib.g95 + diff --git a/contrib/src/svg/makefile.vc b/contrib/src/svg/makefile.vc new file mode 100644 index 0000000000..9ace448800 --- /dev/null +++ b/contrib/src/svg/makefile.vc @@ -0,0 +1,147 @@ + +# File: makefile.vc +# Author: Julian Smart +# Created: 2001 +# Updated: +# Copyright: (c) 2001, Julian Smart +# +# "%W% %G%" +# +# This has not been tested Chris Elliott (biol75@york.ac.uk) and +# the docs don't yet exist +# +# Makefile : Builds dcsvg class library (MS VC++). +# Use FINAL=1 argument to nmake to build final version with no debugging +# info + + +# Set WXDIR for your system +WXDIR = $(WXWIN) +GIZMOSDIR = $(WXDIR)\contrib\src\dcsvg +GIZMOSINC = $(WXDIR)\contrib\include\wx\dcsvg +THISDIR = $(WXDIR)\contrib\src\dcsvg +DOCDIR=$(WXDIR)\contrib\docs +LOCALDOCDIR=$(WXDIR)\contrib\docs\latex\dcsvg + +!include $(WXDIR)\src\makevc.env + +OBJECTS = $(D)\dcsvg.obj + +LIBTARGET=$(WXDIR)\lib\dcsvg$(LIBEXT).lib + +all: $(D) $(LIBTARGET) + +$(D) : + mkdir $(D) + +wx: + cd $(WXDIR)\src\msw + nmake -f makefile.vc FINAL=$(FINAL) + cd $(THISDIR) + +wxclean: + cd $(WXDIR)\src\msw + nmake -f makefile.vc clean + cd $(THISDIR) + +$(LIBTARGET): $(OBJECTS) + -erase $(LIBTARGET) + $(implib) @<< +-out:$(LIBTARGET) +-machine:$(CPU) +$(OBJECTS) +<< + +$(D)\dcsvg.obj: dcsvg.$(SRCSUFF) + cl @<< +$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF) +<< + +clean: + -erase $(D)\*.obj + -erase *.sbr + -erase *.exe + -erase *.res + -erase *.map + -erase *.pdb + -erase $(LIBTARGET) + +DOCSOURCES=$(LOCALDOCDIR)\dcsvg.tex \ + $(LOCALDOCDIR)\bugs.tex $(LOCALDOCDIR)\changes.tex\ + $(LOCALDOCDIR)\classes.tex $(LOCALDOCDIR)\intro.tex\ + $(LOCALDOCDIR)\topics.tex $(LOCALDOCDIR)\sample.tex + +html: $(DOCDIR)\html\dcsvg\dcsvg.htm +htmlhelp: $(DOCDIR)\htmlhelp\dcsvg.chm +htb: $(DOCDIR)\htb\dcsvg.htb +hlp: $(DOCDIR)\winhelp\dcsvg.hlp +pdfrtf: $(DOCDIR)\pdf\dcsvg.rtf +ps: $(DOCDIR)\ps\dcsvg.ps + +touchmanual: + touch $(LOCALDOCDIR)\dcsvg.tex + + +$(DOCDIR)\winhelp\dcsvg.hlp: $(LOCALDOCDIR)\dcsvg.rtf $(LOCALDOCDIR)\dcsvg.hpj + cd $(LOCALDOCDIR) + -erase dcsvg.ph + hc dcsvg + move dcsvg.hlp $(DOCDIR)\winhelp\dcsvg.hlp + move dcsvg.cnt $(DOCDIR)\winhelp\dcsvg.cnt + cd $(THISDIR) + +$(LOCALDOCDIR)\dcsvg.rtf: $(DOCSOURCES) + cd $(LOCALDOCDIR) + -start $(WAITFLAG) tex2rtf $(LOCALDOCDIR)\dcsvg.tex $(LOCALDOCDIR)\dcsvg.rtf -twice -winhelp + cd $(THISDIR) + +$(DOCDIR)\pdf\dcsvg.rtf: $(DOCSOURCES) + cd $(LOCALDOCDIR) + -copy *.bmp $(DOCDIR)\pdf + -start $(WAITFLAG) tex2rtf $(LOCALDOCDIR)\dcsvg.tex $(DOCDIR)\pdf\dcsvg.rtf -twice -rtf + cd $(THISDIR) + +$(DOCDIR)\html\dcsvg\dcsvg.htm: $(DOCSOURCES) + cd $(LOCALDOCDIR) + -mkdir $(DOCDIR)\html\dcsvg + copy *.gif $(DOCDIR)\html\dcsvg + -start $(WAITFLAG) tex2rtf $(LOCALDOCDIR)\dcsvg.tex $(DOCDIR)\html\dcsvg\dcsvg.htm -twice -html + -erase $(DOCDIR)\html\dcsvg\*.con + -erase *.con + -erase $(DOCDIR)\html\dcsvg\*.ref + cd $(THISDIR) + +$(DOCDIR)\htmlhelp\dcsvg.chm: $(DOCDIR)\html\dcsvg\dcsvg.htm $(DOCDIR)\html\dcsvg\dcsvg.hhp + cd $(DOCDIR)\html\dcsvg + -hhc dcsvg.hhp + move dcsvg.chm $(DOCDIR)\htmlhelp\dcsvg.chm + cd $(THISDIR) + +# An htb file is a zip file containing the .htm, .gif, .hhp, .hhc and .hhk +# files, renamed to htb. +# This can then be used with e.g. helpview. +# Optionally, a cached version of the .hhp file can be generated with hhp2cached. +$(DOCDIR)\htb\dcsvg.htb: $(DOCDIR)\html\dcsvg\dcsvg.htm + cd $(DOCDIR)\html\dcsvg + -erase dcsvg.zip dcsvg.htb + zip dcsvg.zip *.htm *.gif *.hhp *.hhc *.hhk + -mkdir $(DOCDIR)\htb + move dcsvg.zip $(DOCDIR)\htb\dcsvg.htb + cd $(THISDIR) + +$(LOCALDOCDIR)\dcsvg.dvi: $(DOCSOURCES) + cd $(LOCALDOCDIR) + -latex dcsvg + -latex dcsvg + -makeindx dcsvg + -bibtex dcsvg + -latex dcsvg + -latex dcsvg + cd $(THISDIR) + +$(WXDIR)\docs\ps\dcsvg.ps: $(LOCALDOCDIR)\dcsvg.dvi + cd $(LOCALDOCDIR) + -dvips32 -o dcsvg.ps dcsvg + move dcsvg.ps $(WXDIR)\docs\ps\dcsvg.ps + cd $(THISDIR) + diff --git a/samples/svg/Makefile.in b/samples/svg/Makefile.in new file mode 100644 index 0000000000..a34d871ea6 --- /dev/null +++ b/samples/svg/Makefile.in @@ -0,0 +1,16 @@ +# Makefile for plot sample. +# $Id$ + +top_srcdir = @top_srcdir@/.. +top_builddir = ../../.. +program_dir = contrib/samples/svg + +PROGRAM=svgtest + +OBJECTS=svgtest.o + +APPEXTRALIBS=$(top_builddir)/lib/libwx_dcsvg.@WX_TARGET_LIBRARY_TYPE@ +APPEXTRADEFS=-I$(top_srcdir)/contrib/include + +include $(top_builddir)/src/makeprog.env + diff --git a/samples/svg/SVGlogo24.bmp b/samples/svg/SVGlogo24.bmp new file mode 100644 index 0000000000..5c6e4a9693 Binary files /dev/null and b/samples/svg/SVGlogo24.bmp differ diff --git a/samples/svg/SVGlogo24.xpm b/samples/svg/SVGlogo24.xpm new file mode 100644 index 0000000000..113067233a --- /dev/null +++ b/samples/svg/SVGlogo24.xpm @@ -0,0 +1,310 @@ +/* XPM */ +static char *svgbitmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"64 48 256 2", +" c #550000", +". c #5c0000", +"X c #5f000a", +"o c #5c033a", +"O c #5a3615", +"+ c #640000", +"@ c #640009", +"# c #680605", +"$ c #680807", +"% c #6d0e0e", +"& c #630015", +"* c #690717", +"= c #6d110e", +"- c #6e1412", +"; c #701513", +": c #721b16", +"> c #741c1a", +", c #650021", +"< c #65022b", +"1 c #65003d", +"2 c #650034", +"3 c #6b1132", +"4 c #711535", +"5 c #76221c", +"6 c #78211e", +"7 c #642939", +"8 c #643929", +"9 c #663336", +"0 c #772220", +"q c #792522", +"w c #7b2a23", +"e c #7d2d29", +"r c #7f312a", +"t c #5d004f", +"y c #560059", +"u c #5b005c", +"i c #5a0054", +"p c #5e0061", +"a c #64004a", +"s c #650046", +"d c #640150", +"f c #64025d", +"g c #660d58", +"h c #671746", +"j c #651352", +"k c #640064", +"l c #640069", +"z c #6d0e6c", +"x c #680767", +"c c #6e0f71", +"v c #6c106b", +"b c #6c1665", +"n c #711a6c", +"m c #731b72", +"M c #682847", +"N c #6d2653", +"B c #75236d", +"V c #7c2d74", +"C c #7d2c7a", +"Z c #782278", +"A c #7e3177", +"S c #565600", +"D c #5c5c00", +"F c #5e6100", +"G c #614416", +"H c #655f06", +"J c #655a0b", +"K c #70463b", +"L c #6e4538", +"P c #646400", +"I c #656a00", +"U c #6c6c0d", +"Y c #676708", +"T c #6d6914", +"R c #6d720f", +"E c #707014", +"W c #78781e", +"Q c #75771a", +"! c #75602d", +"~ c #7a7a23", +"^ c #7b7b2d", +"/ c #812e2a", +"( c #82392d", +") c #81332d", +"_ c #853a34", +"` c #843834", +"' c #833a7b", +"] c #8a443a", +"[ c #884438", +"{ c #8e4a42", +"} c #8d4542", +"| c #8b4055", +" . c #914e48", +".. c #94564a", +"X. c #955250", +"o. c #985b54", +"O. c #995d55", +"+. c #894679", +"@. c #90506f", +"#. c #995c7d", +"$. c #97624d", +"%. c #9e6a5b", +"&. c #9c6756", +"*. c #9e6460", +"=. c #8d6a64", +"-. c #a06a5d", +";. c #a1715d", +":. c #a26a66", +">. c #a97c6c", +",. c #a67568", +"<. c #ac7b74", +"1. c #ab7674", +"2. c #812f81", +"3. c #853a82", +"4. c #823081", +"5. c #8a4284", +"6. c #8d4a84", +"7. c #8f5080", +"8. c #945689", +"9. c #965792", +"0. c #9a6389", +"q. c #9d6397", +"w. c #a2658e", +"e. c #a16a99", +"r. c #a5778f", +"t. c #a77799", +"y. c #ad78aa", +"u. c #a76daa", +"i. c #81812b", +"p. c #878738", +"a. c #888837", +"s. c #8d8d40", +"d. c #919145", +"f. c #919149", +"g. c #979753", +"h. c #9c9c5a", +"j. c #9b9b54", +"k. c #9f8671", +"l. c #9b856c", +"z. c #aa826b", +"x. c #ae8772", +"c. c #b1847a", +"v. c #b08c75", +"b. c #b3897f", +"n. c #b19374", +"m. c #b6997d", +"M. c #a99e77", +"N. c #a1a25b", +"B. c #a4a465", +"V. c #abab73", +"C. c #adad79", +"Z. c #b6a079", +"A. c #b2b278", +"S. c #ab878d", +"D. c #ac8396", +"F. c #b78c86", +"G. c #b69182", +"H. c #b99c83", +"J. c #bc9a8b", +"K. c #bb9592", +"L. c #b183ab", +"P. c #b38ca3", +"I. c #bd98b7", +"U. c #b791a9", +"Y. c #bba385", +"T. c #bca696", +"R. c #bbbb8c", +"E. c #b8b785", +"W. c #bebe94", +"Q. c #bfa5a7", +"!. c #c19c97", +"~. c #c0a88d", +"^. c #c3a896", +"/. c #c3b48f", +"(. c #c7b698", +"). c #c6aba5", +"_. c #c6aab7", +"`. c #ccb7a8", +"'. c #cdb8b5", +"]. c #d0bbab", +"[. c #d1bbb3", +"{. c #c29bc2", +"}. c #caa9c6", +"|. c #d7bfd0", +" X c #d2b8ca", +".X c #c2c28e", +"XX c #c8c294", +"oX c #cbc59c", +"OX c #ccca9b", +"+X c #c4c595", +"@X c #cccaa3", +"#X c #ccc8a7", +"$X c #d0cba5", +"%X c #d3cbab", +"&X c #d1c5aa", +"*X c #d3c3b3", +"=X c #d8c4ba", +"-X c #d8cbbb", +";X c #d5cab7", +":X c #d4d4ab", +">X c #d6dcaa", +",X c #d8dbad", +" % % % ; % % ; % % ; % % ; % % % % % % % ; % % % % % % % % % ; % % % % ; % % % = = % % % % = % % % % % ; % % ; % % ; % % ; % / ", +"% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # ", +"% + + + + + + + + + + + + + + + + + + = % = = % % % @ + + + + + + + + + + + % % % $ = $ % + + + + + + + # + + + + + + # + + + % ", +"% + + + + + + + + + + + + # + + + + % rXUXSXDXcXcXaX6 . + + + + + + + + + 6 oX$X@XoXXXOXZ.# + + + + + + + + + + + + + + + + + % ", +"% + + + + + + + + + + + + + # + + + . F.IXIXIXIXPXPX,.. + + + + + + + + + %.qX3X6X,XX&.+ + + + + + + + + + + + + + + + + + ; ", +"% + + + + + + + # + + + + + + + + + + ` UXPXaX[.aXPX;X@ + + + + + + + + $ (.0X(.m./..wXM.+ + + + + + + + + + + + + # + + + + + ; ", +"; + + + + + + + + + + + + # + + + + + . :.IXSX- . [.IXG.. + + + + + + + v.nXH.. = XX6X] + + + + + + + + + + + + + + + + + + + % ", +"; + + + + + + + + + + + + + + + + + + + > SXIXO. *.PXaX; + + + + + + ; %XjX.. ..6X(.= + + + + # + + + + + + + + + + + + + # % ", +"% + + + + + + + # + + + + # + + + + + + + !.IX[.. ; zXJXO.. + + + + . O.kX#X= + m.9Xz.. + + + + + + + + + + + + + + + # + + + % ", +"% + + + + + + + + + + + + + + + + + + + + } IXGXr J.IX).+ + + + + + ^.bXx. w :X.mX(.+ $ (.9X$.. + + + + + + + + + + + + + + + + + + + + ; ", +"% + + + + + + + + + + + # + + + + + + + + @ q GXPX . ,.KX-X$ + + $ #XbX&. [ 7X$X: + + + + + + + # + + + + + + + + # + + # + % ", +"; + + + + + + + + + + + + + + + + + + + + + + ).IX^.. q vXMX{ . . .kX5X> . n.jXn.+ + + + + + + + + + + + + + + + + + + + + + ; ", +"% + # + + + + + + + + % > ; $ + + + + + + + . o.PXvX> . ^.KXJ.+ + J.BXH.. : %X8X[ . + + + + + . $ / { ._ : + + + + + + + + + % ", +"% + + + + + + + > ,.`.aXpXpX].x.( + + + + + + - sXPX:. ..HXyX; : yXlX] &.jX(.$ + + + + . ; <.-XxXVXVXkX1XH.[ + + + + + + + % ", +"; + + + + + # 1.vXIXKXxXhXpXlXBX0Xm.: + + + + F.IX[.+ % tXHXO.%.MX&X% + /.jX;.. + + + + ..sXIXJXaX].^.%XgXNX8Xn.- + + + + + % ", +"% + + + + % ).IXPX`.O.e ; 6 ] v.1XnXoX( + + + + ` GXFX` c.HX;XyXmX>. r 8X3Xw + + + . 1.PXPX].X.% @ + + e >.1XjX/.: + + + + % ", +"% + + + @ ^.IXcXo.. + # + + 5 m.qX$X( . + + + [.PXb. ` lXxXlXgXe z.nXY.+ + + . :.IXGX,.@ $ w ) ; + w #X8X/.% + + + % ", +"* + + . 1.IXDX` > c.].2X%XH.] . . ;.,X(.5 . + . :.PXaX% + `.MXxX^.+ = %XjX.. + _ PXPXO. ; c.-XlXlXyX~.[ ;.3X7X>.$ + + + % ", +"v 2 + / UXUX} .sXHXMXxXlXBXkXm.) ..OX6Xn.+ + . > vXLXX. &.MXmXO. ..jX#X; + + # [.IX<. r eXPXCXpX-XpXMXgXjX3X..+ + + + * g ", +"c l t w.IXDXe ,.PXFXG.w _ >.1XjX3XqX7X ~.1XZ.;.( - $ + + . { HXvXq . T.J.. w 2XgX_ . + + '.IXX. `.IXJ.# . + + + . ( w . @ < d l l k c ", +"c k k f x }.IXeX3 X J.JX;X: . . = - + . + + + + + + % -XKX,. ` 6 ,.bX(.$ + + > UXdX+ } IX=X$ + + + @ + + . & 1 f l l l k k c ", +"v k k k p z rXIX}.f d _.LX(.- + + + + + + + + + + + . <.KX*X$ . + $ `.bX;. + X.IXK.. !.IXX.. + + + @ , 1 f l l k k l k k k c ", +"c k k k k f m rXPXI.u n [.ZXT.< & @ + + + + + + + + + e vXcX] . . ] kX3X6 + + . 1.IX*.@ sXsX% @ , 2 d f f p p p f p p p f f k c ", +"c k k k k k f ' dXKXP.u n ;XNXP.f f a 1 < , & @ @ + + + (.KXF.. + G.BXH.+ + + . K.IX| 4 KX_.f f l l l l 6.6.6.6.6.+.+.+.+.+.z z ", +"c k k k k k k k 3.vXLXt.y C 2XnXt.p l l l l k k f a a o #.HXuX4 h 2XkX@.o a a t {.IX4.Z PXI.p k k k k z yXjXjX9XqX3X6X>XXN.I E ", +"U P P P F D G M 2.x p p p U.nX&Xm p S.6X(.B p l k k k k k p e.mXlX0.p l k k k k x fXIXC x dXJX9.u p f z '.*X;X3XqXk.O B.>Xa.H R ", +"R P P U p.B.+XkXDXU.N i u f U.nX).b k K.6XT.b p k k k l l f Z hXpXm k k k k k k p y.IXI.y 9.KXFXq.x p p x A ).jX+XY Q +#include + +#include "bitmaps/new.xpm" +#include "bitmaps/save.xpm" +#include "bitmaps/help.xpm" +#include "SVGlogo24.xpm" + +class MyChild; + +// Define a new application +class MyApp : public wxApp +{ + public: + bool OnInit(); +}; + +// Define a new frame +class MyFrame : public wxMDIParentFrame +{ + public: + int nWinCreated; + + wxList m_children; + + MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title, + const wxPoint& pos, const wxSize& size, const long style); + + void InitToolBar(wxToolBar* toolBar); + + void OnSize(wxSizeEvent& event); + void OnAbout(wxCommandEvent& event); + void OnNewWindow(wxCommandEvent& event); + void OnQuit(wxCommandEvent& event); + void OnClose(wxCloseEvent& event); + void FileSavePicture (wxCommandEvent & WXUNUSED(event) ) ; + + DECLARE_EVENT_TABLE() +}; + + +class MyCanvas : public wxScrolledWindow +{ + public: + int m_index ; + + MyChild * m_child ; + MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size); + virtual void OnDraw(wxDC& dc); + + DECLARE_EVENT_TABLE() +}; + +class MyChild: public wxMDIChildFrame +{ + public: + MyCanvas *m_canvas; + MyFrame *m_frame ; + + //////////////////// Methods + + MyChild(wxMDIParentFrame *parent, const wxString& title, const wxPoint& pos, const wxSize& size, const long style); + ~MyChild(); + + void OnActivate(wxActivateEvent& event); + void OnQuit(wxCommandEvent& event); + void OnClose(wxCloseEvent& event); + bool OnSave(wxString filename) ; + + DECLARE_EVENT_TABLE() +}; + +// menu items ids +enum +{ + MDI_QUIT = 100, + MDI_NEW_WINDOW, + MDI_SAVE, + MDI_REFRESH, + MDI_CHILD_QUIT, + MDI_ABOUT +}; + + +IMPLEMENT_APP(MyApp) + +// --------------------------------------------------------------------------- +// global variables +// --------------------------------------------------------------------------- + +MyFrame *frame = (MyFrame *) NULL; + +// --------------------------------------------------------------------------- +// event tables +// --------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame) +EVT_MENU(MDI_ABOUT, MyFrame::OnAbout) +EVT_MENU(MDI_NEW_WINDOW, MyFrame::OnNewWindow) +EVT_MENU(MDI_QUIT, MyFrame::OnQuit) +EVT_MENU (MDI_SAVE, MyFrame::FileSavePicture) +EVT_CLOSE(MyFrame::OnClose) + +EVT_SIZE(MyFrame::OnSize) +END_EVENT_TABLE() + +// =========================================================================== +// implementation +// =========================================================================== + +// --------------------------------------------------------------------------- +// MyApp +// --------------------------------------------------------------------------- + +// Initialise this in OnInit, not statically +bool MyApp::OnInit() +{ + // Create the main frame window + + frame = new MyFrame((wxFrame *)NULL, -1, wxT("SVG Demo"), + wxPoint(-1, -1), wxSize(500, 400), + wxDEFAULT_FRAME_STYLE | wxHSCROLL | wxVSCROLL); + + + // Make a menubar + wxMenu *file_menu = new wxMenu; + + file_menu->Append(MDI_NEW_WINDOW, wxT("&New test\tCtrl+N")); + file_menu->Append(MDI_QUIT, wxT("&Exit\tAlt+X")); + + wxMenu *help_menu = new wxMenu; + help_menu->Append(MDI_ABOUT, wxT("&About")); + + wxMenuBar *menu_bar = new wxMenuBar; + + menu_bar->Append(file_menu, wxT("&File")); + menu_bar->Append(help_menu, wxT("&Help")); + + // Associate the menu bar with the frame + frame->SetMenuBar(menu_bar); + + frame->CreateStatusBar(); + + frame->Show(TRUE); + + SetTopWindow(frame); + + return TRUE; +} + + +// --------------------------------------------------------------------------- +// MyFrame +// --------------------------------------------------------------------------- + +// Define my frame constructor +MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title, + const wxPoint& pos, const wxSize& size, const long style) + : wxMDIParentFrame(parent, id, title, pos, size, style) +{ + nWinCreated = 0 ; + + // Give it an icon + SetIcon(wxICON(mondrian)); + + CreateToolBar(wxNO_BORDER | wxTB_FLAT | wxTB_HORIZONTAL); + InitToolBar(GetToolBar()); + +} + + +void MyFrame::OnClose(wxCloseEvent& event) +{ + if ( !event.CanVeto() ) + { + event.Skip(); + return ; + } + if ( m_children.Number () < 1 ) + { + event.Skip(); + return ; + } + // now try the children + wxNode * pNode = m_children.GetFirst (); + wxNode * pNext ; + MyChild * pChild ; + while ( pNode ) + { + pNext = pNode -> GetNext (); + pChild = (MyChild*) pNode -> Data (); + if (pChild -> Close ()) + { + delete pNode ; + } + else + { + event.Veto(); + return; + } + pNode = pNext ; + } + event.Skip(); +} + + +void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(); +} + + +void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) +{ + (void)wxMessageBox(wxT("wxWindows 2.0 SVG 1.0 Test\n" + "Author: Chris Elliott (c) 2002\n" + "Usage: svg.exe \nClick File | New to show tests\n\n"), wxT("About SVG Test")); +} + + +void MyFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event) ) +{ + // Make another frame, containing a canvas + MyChild *subframe ; + + m_children.Append (new MyChild(frame, wxT("SVG Frame"), + wxPoint(-1, -1), wxSize(-1, -1), + wxDEFAULT_FRAME_STYLE ) ) ; + + subframe = (MyChild *) m_children.GetLast() -> Data (); + wxString title; + title.Printf(wxT("SVG Test Window %d"), nWinCreated ); + // counts number of children previously, even if now closed + nWinCreated ++ ; + + // Give it a title and icon + subframe->SetTitle(title); + subframe->SetIcon(wxICON(mondrian)); + + // Make a menubar + wxMenu *file_menu = new wxMenu; + + file_menu->Append(MDI_NEW_WINDOW, wxT("&Another test\tCtrl+N")); + file_menu->Append(MDI_SAVE, wxT("&Save\tCtrl+S"), wxT("Save in SVG format")); + file_menu->Append(MDI_CHILD_QUIT, wxT("&Close child\tCtrl+F4")); + file_menu->Append(MDI_QUIT, wxT("&Exit\tAlt+X")); + + wxMenu *help_menu = new wxMenu; + help_menu->Append(MDI_ABOUT, wxT("&About")); + + wxMenuBar *menu_bar = new wxMenuBar; + + menu_bar->Append(file_menu, wxT("&File")); + menu_bar->Append(help_menu, wxT("&Help")); + + // Associate the menu bar with the frame + subframe->SetMenuBar(menu_bar); + + subframe->Show(TRUE); +} + + +void MyFrame::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + int w, h; + GetClientSize(&w, &h); + + GetClientWindow()->SetSize(0, 0, w, h); +} + + +void MyFrame::InitToolBar(wxToolBar* toolBar) +{ + const int maxBitmaps = 3 ; + wxBitmap* bitmaps[maxBitmaps]; + + bitmaps[0] = new wxBitmap( new_xpm ); + bitmaps[1] = new wxBitmap( save_xpm ); + bitmaps[2] = new wxBitmap( help_xpm ); + + int width = 16; + int currentX = 5; + + toolBar->AddTool( MDI_NEW_WINDOW, *(bitmaps[0]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, wxT("New SVG test window")); + currentX += width + 5; + toolBar->AddTool( MDI_SAVE, *bitmaps[1], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, wxT("Save test in SVG format")); + currentX += width + 5; + toolBar->AddSeparator(); + toolBar->AddTool(MDI_ABOUT, *bitmaps[2], wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, wxT("Help")); + + toolBar->Realize(); + + int i; + for (i = 0; i < maxBitmaps; i++) + delete bitmaps[i]; +} + + +void MyFrame::FileSavePicture (wxCommandEvent & WXUNUSED(event) ) +{ + MyChild * pChild = (MyChild *)GetActiveChild (); + if (pChild == NULL) + { + return ; + } + + wxFileDialog dialog(this, wxT("Save Picture as"), wxEmptyString, pChild->GetTitle(), + wxT("SVG vector picture files (*.svg)|*.svg"), + wxSAVE|wxOVERWRITE_PROMPT); + + if (dialog.ShowModal() == wxID_OK) + { + if (!pChild -> OnSave ( dialog.GetPath() )) + { + return ; + } + } + return ; +} + + +// Note that MDI_NEW_WINDOW and MDI_ABOUT commands get passed +// to the parent window for processing, so no need to +// duplicate event handlers here. +BEGIN_EVENT_TABLE(MyChild, wxMDIChildFrame) + EVT_MENU(MDI_CHILD_QUIT, MyChild::OnQuit) + EVT_CLOSE(MyChild::OnClose) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) + +END_EVENT_TABLE() + +// --------------------------------------------------------------------------- +// MyCanvas +// --------------------------------------------------------------------------- + +// Define a constructor for my canvas +MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size) +: wxScrolledWindow(parent, -1, pos, size, +wxSUNKEN_BORDER|wxVSCROLL|wxHSCROLL) +{ + m_child = (MyChild *) parent ; + SetBackgroundColour(wxColour("WHITE")); + m_index = m_child->m_frame->nWinCreated % 7 ; +} + + +// Define the repainting behaviour +void MyCanvas::OnDraw(wxDC& dc) +{ + // vars to use ... + wxString s ; + wxPen wP ; + wxBrush wB ; + wxPoint points[6]; + wxColour wC; + wxFont wF ; + + dc.SetFont(*wxSWISS_FONT); + dc.SetPen(*wxGREEN_PEN); + + + switch (m_index) + { + default: + case 0: + // draw lines to make a cross + dc.DrawLine(0, 0, 200, 200); + dc.DrawLine(200, 0, 0, 200); + // draw point colored line and spline + wP = *wxCYAN_PEN ; + wP.SetWidth(3); + dc.SetPen(wP); + + dc.DrawPoint (25,15) ; + dc.DrawLine(50, 30, 200, 30); + dc.DrawSpline(50, 200, 50, 100, 200, 10); + s = wxT("Green Cross, Cyan Line and spline"); + break ; + + case 1: + // draw standard shapes + dc.SetBrush(*wxCYAN_BRUSH); + dc.SetPen(*wxRED_PEN); + dc.DrawRectangle(10, 10, 100, 70); + wB = wxBrush ("DARK ORCHID", wxTRANSPARENT); + dc.SetBrush (wB); + dc.DrawRoundedRectangle(50, 50, 100, 70, 20); + dc.SetBrush (wxBrush("GOLDENROD", wxSOLID) ); + dc.DrawEllipse(100, 100, 100, 50); + + points[0].x = 100; points[0].y = 200; + points[1].x = 70; points[1].y = 260; + points[2].x = 160; points[2].y = 230; + points[3].x = 40; points[3].y = 230; + points[4].x = 130; points[4].y = 260; + points[5].x = 100; points[5].y = 200; + + dc.DrawPolygon(5, points); + dc.DrawLines (6, points, 160); + s = wxT("Blue rectangle, red edge, clear rounded rectangle, gold ellipse, gold and clear stars"); + break ; + + case 2: + // draw text in Arial or similar font + dc.DrawLine(50,25,50,35); + dc.DrawLine(45,30,55,30); + dc.DrawText(wxT("This is a Swiss-style string"), 50, 30); + wC = dc.GetTextForeground() ; + dc.SetTextForeground ("FIREBRICK"); + + // no effect in msw ?? + dc.SetTextBackground ("WHEAT"); + dc.DrawText(wxT("This is a Red string"), 50, 200); + dc.DrawRotatedText(wxT("This is a 45 deg string"), 50, 200, 45); + dc.DrawRotatedText(wxT("This is a 90 deg string"), 50, 200, 90); + wF = wxFont ( 18, wxROMAN, wxITALIC, wxBOLD, FALSE, wxT("Times New Roman")); + dc.SetFont(wF); + dc.SetTextForeground (wC) ; + dc.DrawText(wxT("This is a Times-style string"), 50, 60); + s = wxT("Swiss, Times text; red text, rotated and colored orange"); + break ; + + case 3 : + // four arcs start and end points, center + dc.SetBrush(*wxGREEN_BRUSH); + dc.DrawArc ( 200,300, 370,230, 300.0,300.0 ); + dc.SetBrush(*wxBLUE_BRUSH); + dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270.0,270.0 ); + dc.SetDeviceOrigin(-10,-10); + dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270.0,270.0 ); + dc.SetDeviceOrigin(0,0); + + wP.SetColour ("CADET BLUE"); + dc.SetPen(wP); + dc.DrawArc ( 75,125, 110, 40, 75.0, 75.0 ); + + wP.SetColour ("SALMON"); + dc.SetPen(wP); + dc.SetBrush(*wxRED_BRUSH); + //top left corner, width and height, start and end angle + // 315 same center and x-radius as last pie-arc, half Y radius + dc.DrawEllipticArc(25,50,100,50,180.0,45.0) ; + + wP = *wxCYAN_PEN ; + wP.SetWidth(3); + dc.SetPen(wP); + //wxTRANSPARENT)); + dc.SetBrush (wxBrush ("SALMON",wxSOLID)) ; + dc.DrawEllipticArc(300, 0,200,100, 0.0,145.0) ; + //same end point + dc.DrawEllipticArc(300, 50,200,100,90.0,145.0) ; + dc.DrawEllipticArc(300,100,200,100,90.0,345.0) ; + + s = wxT("This is an arc test page"); + break ; + + case 4: + dc.DrawCheckMark ( 30,30,25,25); + dc.SetBrush (wxBrush ("SALMON",wxTRANSPARENT)); + dc.DrawCheckMark ( 80,50,75,75); + dc.DrawRectangle ( 80,50,75,75); + s = wxT("Two check marks"); + break ; + + case 5: + wF = wxFont ( 18, wxROMAN, wxITALIC, wxBOLD, FALSE, wxT("Times New Roman")); + dc.SetFont(wF); + dc.DrawLine(0, 0, 200, 200); + dc.DrawLine(200, 0, 0, 200); + dc.DrawText(wxT("This is an 18pt string"), 50, 60); + + // rescale and draw in blue + wP = *wxCYAN_PEN ; + dc.SetPen(wP); + dc.SetUserScale (2.0,0.5); + dc.SetDeviceOrigin(200,0); + dc.DrawLine(0, 0, 200, 200); + dc.DrawLine(200, 0, 0, 200); + dc.DrawText(wxT("This is an 18pt string 2 x 0.5 UserScaled"), 50, 60); + dc.SetUserScale (2.0,2.0); + dc.SetDeviceOrigin(200,200); + dc.DrawText(wxT("This is an 18pt string 2 x 2 UserScaled"), 50, 60); + + wP = *wxRED_PEN ; + dc.SetPen(wP); + dc.SetUserScale (1.0,1.0); + dc.SetDeviceOrigin(0,10); + dc.SetMapMode (wxMM_METRIC) ; //svg ignores this + dc.DrawLine(0, 0, 200, 200); + dc.DrawLine(200, 0, 0, 200); + dc.DrawText(wxT("This is an 18pt string in MapMode"), 50, 60); + s = wxT("Scaling test page"); + break ; + + case 6: + dc.DrawIcon( wxICON(mondrian), 10, 10 ); + dc.DrawBitmap ( wxBITMAP (svgbitmap), 50,15); + s = wxT("Icon and Bitmap "); + break ; + + } + m_child->SetStatusText(s); +} + + + + +// --------------------------------------------------------------------------- +// MyChild +// --------------------------------------------------------------------------- + +MyChild::MyChild(wxMDIParentFrame *parent, const wxString& title, +const wxPoint& pos, const wxSize& size, +const long style) +: wxMDIChildFrame(parent, -1, title, pos, size, style) +{ + + m_frame = (MyFrame *) parent ; + CreateStatusBar(); + SetStatusText(title); + + int w, h ; + GetClientSize ( &w, &h ); + m_canvas = new MyCanvas(this, wxPoint(0, 0), wxSize (w,h) ); + // Give it scrollbars + m_canvas->SetScrollbars(20, 20, 50, 50); + +} + + +MyChild::~MyChild() +{ + m_frame->m_children.DeleteObject(this); +} + + +void MyChild::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(TRUE); +} + + +bool MyChild::OnSave(wxString filename) +{ + wxSVGFileDC svgDC (filename, 600, 650) ; + m_canvas->OnDraw (svgDC); + return svgDC.Ok(); +} + + + +void MyChild::OnActivate(wxActivateEvent& event) +{ + if ( event.GetActive() && m_canvas ) + m_canvas->SetFocus(); +} + + +void MyChild::OnClose(wxCloseEvent& event) +{ + event.Skip(); +} diff --git a/src/common/dcsvg.cpp b/src/common/dcsvg.cpp new file mode 100644 index 0000000000..d59ecb0277 --- /dev/null +++ b/src/common/dcsvg.cpp @@ -0,0 +1,856 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: svg.cpp +// Purpose: SVG sample +// Author: Chris Elliott +// Modified by: +// RCS-ID: $Id$ +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +#include "wx/svg/dcsvg.h" + +#include +#include "wx/image.h" + +#define wxSVG_DEBUG FALSE +// or TRUE to see the calls being executed +#define newline wxString(wxT("\n")) +#define space wxString(wxT(" ")) +#define semicolon wxString(wxT(";")) +#define wx_round(a) (int)((a)+.5) + +#ifdef __BORLANDC__ +#pragma warn -rch +#pragma warn -ccc +#endif + +static inline double DegToRad(double deg) { return (deg * 3.14) / 180.0; } ; + +wxString wxColStr ( wxColour c ) +{ + unsigned char r, g, b ; + r = c.Red (); + g = c.Green (); + b = c. Blue (); + + // possible Unicode bug here + wxString s = wxDecToHex(r) + wxDecToHex(g) + wxDecToHex(b) ; + return s ; +} + + +wxString wxBrushString ( wxColour c, int style ) +{ + wxString s = wxT("fill:#") + wxColStr (c) + semicolon + space ; + switch ( style ) + { + case wxSOLID : + s = s + wxT("fill-opacity:1.0; "); + break ; + case wxTRANSPARENT: + s = s + wxT("fill-opacity:0.0; "); + break ; + + default : + wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::Requested Brush Style not available")) ; + + } + s = s + newline ; + return s ; +} + + +void wxSVGFileDC::Init (wxString f, int Width, int Height, float dpi) + +{ + //set up things first wxDCBase does all this? + m_width = Width ; + m_height = Height ; + + m_clipping = FALSE; + m_OK = TRUE; + + m_mm_to_pix_x = dpi/25.4; + m_mm_to_pix_y = dpi/25.4; + + m_signX = m_signY = 1; + + m_userScaleX = m_userScaleY = + m_deviceOriginX = m_deviceOriginY = 0; + + m_OriginX = m_OriginY = 0; + m_logicalOriginX = m_logicalOriginY = 0; + m_logicalScaleX = m_logicalScaleY = 0 ; + m_scaleX = m_scaleY = 1.0 ; + + m_logicalFunction = wxCOPY; + m_backgroundMode = wxTRANSPARENT; + m_mappingMode = wxMM_TEXT; + + m_backgroundBrush = *wxTRANSPARENT_BRUSH; + m_textForegroundColour = *wxBLACK; + m_textBackgroundColour = *wxWHITE; + m_colour = wxColourDisplay(); + + m_pen = *wxBLACK_PEN; + m_font = *wxNORMAL_FONT; + m_brush = *wxWHITE_BRUSH; + + m_graphics_changed = TRUE ; + + ////////////////////code here + + m_outfile = new wxFileOutputStream(f) ; + m_OK = m_outfile->Ok (); + if (m_OK) + { + m_filename = f ; + m_sub_images = 0 ; + wxString s ; + s = wxT("") ; s = s + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + s = wxT("Write (s.c_str(), s.Len() ) ; + s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + s.Printf ( wxT(" \n"), float(Width)/dpi*2.54, float(Height)/dpi*2.54, Width, Height ); + m_outfile->Write (s.c_str(), s.Len() ) ; + s = wxT("SVG Picture created as ") + wxFileNameFromPath(f) + wxT(" ") + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + s = wxString (wxT("Picture generated by wxSVG ")) + wxSVGVersion + wxT(" ")+ newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + s = wxT("") + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + + } + m_OK = m_outfile->Ok (); +} + + +// constructors +wxSVGFileDC::wxSVGFileDC (wxString f) +{ + // quarter 640x480 screen display at 72 dpi + Init (f,320,240,72.0); +}; + +wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height) +{ + Init (f,Width,Height,72.0); +}; + +wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height, float dpi) +{ + Init (f,Width,Height,dpi); +}; + +wxSVGFileDC::~wxSVGFileDC() +{ + wxString s = wxT(" \n \n") ; + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + delete m_outfile ; +} + + +////////////////////////////////////////////////////////////////////////////////////////// + +void wxSVGFileDC::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) +{ + if (m_graphics_changed) NewGraphics (); + wxString s ; + s.Printf ( wxT(" \n"), x1,y1,x2,y2 ); + if (m_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok (); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawLine Call executed")) ; + CalcBoundingBox(x1, y1) ; + CalcBoundingBox(x2, y2) ; + return; +}; + +void wxSVGFileDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset ) +{ + for ( int i = 1; i < n ; i++ ) + { + DoDrawLine ( points [i-1].x + xoffset, points [i-1].y + yoffset, + points [ i ].x + xoffset, points [ i ].y + yoffset ) ; + } +} + + +void wxSVGFileDC::DoDrawPoint (wxCoord x1, wxCoord y1) +{ + wxString s; + if (m_graphics_changed) NewGraphics (); + s = wxT(" ") + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + DrawLine ( x1,y1,x1,y1 ); + s = wxT(""); + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); +} + + +void wxSVGFileDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height) +{ + wxDCBase::DoDrawCheckMark (x1,y1,width,height) ; +} + + +void wxSVGFileDC::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1) +{ + DoDrawRotatedText(text, x1,y1,0.0); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawText Call executed")) ; +} + + +void wxSVGFileDC::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle) +{ + //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW + if (m_graphics_changed) NewGraphics (); + wxString s, sTmp; + + // calculate bounding box + wxCoord w, h, desc ; + DoGetTextExtent(sText, &w, &h, &desc); + + double rad = DegToRad(angle); + + // wxT("upper left") and wxT("upper right") + CalcBoundingBox(x, y); + CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); + + // wxT("bottom left") and wxT("bottom right") + x += (wxCoord)(h*sin(rad)); + y += (wxCoord)(h*cos(rad)); + CalcBoundingBox(x, y); + CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); + + if (m_backgroundMode == wxSOLID) + { + // draw background first + // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ; + sTmp.Printf ( wxT(" "), -angle, x,y ) ; + s = s + sTmp + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + } + //now do the text itself + s.Printf (wxT(" 0) s = s + wxT("style=\"font-family:") + sTmp + wxT("; "); + else s = s + wxT("style=\" ") ; + + wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") }; + s = s + wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + semicolon + space; + + wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") }; + s = s + wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + semicolon + space; + + sTmp.Printf (wxT("font-size:%dpt; fill:#"), m_font.GetPointSize () ); + s = s + sTmp ; + s = s + wxColStr (m_textForegroundColour) + wxT("; stroke:#") + wxColStr (m_textForegroundColour) + wxT("; ") ; + sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle, x,y ) ; + s = s + sTmp + sText + wxT(" ") + newline ; + if (m_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok (); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ; + +} + + +void wxSVGFileDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) +{ + DoDrawRoundedRectangle(x, y, width, height, 0) ; +} + + +void wxSVGFileDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) + +{ + if (m_graphics_changed) NewGraphics (); + wxString s ; + + s.Printf ( wxT(" ") + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ; + CalcBoundingBox(x, y) ; + CalcBoundingBox(x + width, y + height) ; + +} + + +void wxSVGFileDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle) +{ + if (m_graphics_changed) NewGraphics (); + wxString s, sTmp ; + s = wxT(" ") ; + s = s + newline ; + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ; +} + + +void wxSVGFileDC::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height) + +{ + if (m_graphics_changed) NewGraphics (); + + int rh = height /2 ; + int rw = width /2 ; + + wxString s; + s.Printf ( wxT(" ") + newline ; + + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ; + CalcBoundingBox(x, y) ; + CalcBoundingBox(x + width, y + height) ; +} + + +void wxSVGFileDC::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc) +{ + /* Draws an arc of a circle, centred on (xc, yc), with starting point + (x1, y1) and ending at (x2, y2). The current pen is used for the outline + and the current brush for filling the shape. + + The arc is drawn in an anticlockwise direction from the start point to + the end point. + + Might be better described as Pie drawing */ + + if (m_graphics_changed) NewGraphics (); + wxString s ; + + // we need the radius of the circle which has two estimates + double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) ); + double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) ); + + wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ; + if ( fabs ( r2-r1 ) > 3 ) //pixels + { + s = wxT(" \n") ; + m_outfile->Write (s.c_str(), s.Len() ) ; + } + + double theta1 = atan2(yc-y1,x1-xc); + if ( theta1 < 0 ) theta1 = theta1 + 3.14 * 2; + double theta2 = atan2(yc-y2, x2-xc); + if ( theta2 < 0 ) theta2 = theta2 + 3.14 * 2; + if ( theta2 < theta1 ) theta2 = theta2 + 3.14 *2 ; + + int fArc ; // flag for large or small arc 0 means less than 180 degrees + if ( fabs((theta2 - theta1) > 3.14 )) fArc = 1; else fArc = 0 ; + + int fSweep = 0 ; // flag for sweep always 0 + + s.Printf ( wxT(" ") + newline ; + + + if (m_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed")) ; +} + + +void wxSVGFileDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea) +{ + /* + Draws an arc of an ellipse. The current pen is used for drawing the arc + and the current brush is used for drawing the pie. This function is + currently only available for X window and PostScript device contexts. + + x and y specify the x and y coordinates of the upper-left corner of the + rectangle that contains the ellipse. + + width and height specify the width and height of the rectangle that + contains the ellipse. + + start and end specify the start and end of the arc relative to the + three-o'clock position from the center of the rectangle. Angles are + specified in degrees (360 is a complete circle). Positive values mean + counter-clockwise motion. If start is equal to end, a complete ellipse + will be drawn. */ + + //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW + + if (m_graphics_changed) NewGraphics (); + + wxString s ; + //radius + double rx = w / 2 ; + double ry = h / 2 ; + // center + double xc = x + rx ; + double yc = y + ry ; + + double xs, ys, xe, ye ; + xs = xc + rx * cos (DegToRad(sa)) ; + xe = xc + rx * cos (DegToRad(ea)) ; + ys = yc - ry * sin (DegToRad(sa)) ; + ye = yc - ry * sin (DegToRad(ea)) ; + + ///now same as circle arc... + + double theta1 = atan2(ys-yc, xs-xc); + double theta2 = atan2(ye-yc, xe-xc); + + int fArc ; // flag for large or small arc 0 means less than 180 degrees + if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0 ; + + int fSweep ; + if ( fabs( (theta2 - theta1) > 3.14)) fSweep = 1; else fSweep = 0 ; + + s.Printf ( wxT(" ") + newline ; + + if (m_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok (); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ; +} + + +void wxSVGFileDC::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , wxFont *font) const + +{ + wxScreenDC sDC ; + + sDC.SetFont (m_font); + if ( font != NULL ) sDC.SetFont ( *font ); + sDC.GetTextExtent(string, w, h, descent, externalLeading ); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed")) ; +} + + +wxCoord wxSVGFileDC::GetCharHeight() const + +{ + wxScreenDC sDC ; + sDC.SetFont (m_font); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing")) ; + return ( sDC.GetCharHeight() ); + +} + + +wxCoord wxSVGFileDC::GetCharWidth() const +{ + wxScreenDC sDC ; + sDC.SetFont (m_font); + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing")) ; + return ( sDC.GetCharWidth() ) ; + +} + + +/// Set Functions ///////////////////////////////////////////////////////////////// +void wxSVGFileDC::SetBackground( const wxBrush &brush ) +{ + + m_backgroundBrush = brush; + return; +} + + +void wxSVGFileDC::SetBackgroundMode( int mode ) +{ + m_backgroundMode = mode; + return; +} + + +void wxSVGFileDC::SetBrush(const wxBrush& brush) + +{ + m_brush = brush ; + + m_graphics_changed = TRUE ; + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed")) ; +} + + +void wxSVGFileDC::SetPen(const wxPen& pen) +{ + // width, color, ends, joins : currently implemented + // dashes, stipple : not implemented + m_pen = pen ; + + m_graphics_changed = TRUE ; + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed")) ; +} + +void wxSVGFileDC::NewGraphics () +{ + + int w = m_pen.GetWidth (); + wxColour c = m_pen.GetColour () ; + + wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn; + + sBrush = wxT("\n \n") ; + } + + sLast.Printf ( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"), + w, m_OriginX, m_OriginY, m_scaleX, m_scaleY ); + + s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn; + m_outfile->Write (s.c_str(), s.Len() ) ; + m_OK = m_outfile->Ok (); + m_graphics_changed = FALSE ; + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed")) ; +} + + +void wxSVGFileDC::SetFont(const wxFont& font) + +{ + m_font = font ; + + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed")) ; +} + + +void wxSVGFileDC::ComputeScaleAndOrigin() +{ + m_scaleX = m_logicalScaleX * m_userScaleX; + m_scaleY = m_logicalScaleY * m_userScaleY; + m_OriginX = m_logicalOriginX * m_logicalScaleX + m_deviceOriginX ; + m_OriginY = m_logicalOriginY * m_logicalScaleY + m_deviceOriginY ; + m_graphics_changed = TRUE; +} + + +int wxSVGFileDC::GetMapMode() +{ + return m_mappingMode ; +} + + +void wxSVGFileDC::SetMapMode( int mode ) +{ + switch (mode) + { + case wxMM_TWIPS: + SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y ); + break; + case wxMM_POINTS: + SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y ); + break; + case wxMM_METRIC: + SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y ); + break; + case wxMM_LOMETRIC: + SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 ); + break; + default: + case wxMM_TEXT: + SetLogicalScale( 1.0, 1.0 ); + break; + } + m_mappingMode = mode; + + /* we don't do this mega optimisation + if (mode != wxMM_TEXT) + { + m_needComputeScaleX = TRUE; + m_needComputeScaleY = TRUE; + } + */ +} + + +void wxSVGFileDC::GetUserScale(double *x, double *y) const +{ + *x = m_userScaleX ; + *y = m_userScaleY ; +} + + +void wxSVGFileDC::SetUserScale( double x, double y ) +{ + // allow negative ? -> no + m_userScaleX = x; + m_userScaleY = y; + ComputeScaleAndOrigin(); +} + + +void wxSVGFileDC::SetLogicalScale( double x, double y ) +{ + // allow negative ? + m_logicalScaleX = x; + m_logicalScaleY = y; + ComputeScaleAndOrigin(); +} + + +void wxSVGFileDC::SetLogicalOrigin( wxCoord x, wxCoord y ) +{ + // is this still correct ? + m_logicalOriginX = x * m_signX; + m_logicalOriginY = y * m_signY; + ComputeScaleAndOrigin(); +} + + +void wxSVGFileDC::SetDeviceOrigin( wxCoord x, wxCoord y ) +{ + // only wxPostScripDC has m_signX = -1, + m_deviceOriginX = x; + m_deviceOriginY = y; + ComputeScaleAndOrigin(); +} + + +void wxSVGFileDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) +{ + // only wxPostScripDC has m_signX = -1, + m_signX = (xLeftRight ? 1 : -1); + m_signY = (yBottomUp ? -1 : 1); + ComputeScaleAndOrigin(); +} + + +// export a bitmap as a raster image in png +bool wxSVGFileDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, + wxDC* source, wxCoord xsrc, wxCoord ysrc, + int logicalFunc /*= wxCOPY*/, bool useMask /*= FALSE*/, + wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/) +{ + + if (logicalFunc != wxCOPY) + { + wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ; + return FALSE ; + } + if (useMask != FALSE) + { + wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ; + return FALSE ; + } + wxBitmap myBitmap (width, height) ; + wxMemoryDC memDC; + memDC.SelectObject( myBitmap ); + memDC.Blit(0, 0, width, height, source, xsrc, ysrc); + memDC.SelectObject( wxNullBitmap ); + DoDrawBitmap(myBitmap, xdest, ydest); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed")) ; + return FALSE ; +} + + +void wxSVGFileDC::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y) +{ + wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() ) ; + wxMemoryDC memDC; + memDC.SelectObject( myBitmap ); + memDC.DrawIcon(myIcon,0,0); + memDC.SelectObject( wxNullBitmap ); + DoDrawBitmap(myBitmap, x, y); + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ; + return ; +} + + + +void wxSVGFileDC::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool bTransparent /*=0*/ ) +{ + if (m_graphics_changed) NewGraphics (); + + wxString sTmp, s, sPNG ; + wxImage::AddHandler(new wxPNGHandler); + +// create suitable file name + sTmp.Printf ( wxT("_image%d.png"), m_sub_images); + sPNG = m_filename.BeforeLast(wxT('.')) + sTmp; + while (wxFile::Exists(sPNG) ) + { + m_sub_images ++ ; + sTmp.Printf ( wxT("_image%d.png"), m_sub_images); + sPNG = m_filename.BeforeLast(wxT('.')) + sTmp; + } + +//create copy of bitmap (wxGTK doesn't like saving a constant bitmap) + wxBitmap myBitmap = bmp ; +//save it + bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG); + +// refrence the bitmap from the SVG doc + int w = myBitmap.GetWidth(); + int h = myBitmap.GetHeight(); + sTmp.Printf ( wxT(" \n"), sPNG.c_str() ); + s = s + sTmp + wxT("Image from wxSVG ") + newline; + + if (m_OK && bPNG_OK) + { + m_outfile->Write (s.c_str(), s.Len() ) ; + } + m_OK = m_outfile->Ok () && bPNG_OK; + wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ; + + return ; +} + + +// --------------------------------------------------------------------------- +// coordinates transformations +// --------------------------------------------------------------------------- + +wxCoord wxSVGFileDC::DeviceToLogicalX(wxCoord x) const +{ + return XDEV2LOG(x); +} + + +wxCoord wxSVGFileDC::DeviceToLogicalY(wxCoord y) const +{ + return YDEV2LOG(y); +} + + +wxCoord wxSVGFileDC::DeviceToLogicalXRel(wxCoord x) const +{ + return XDEV2LOGREL(x); +} + + +wxCoord wxSVGFileDC::DeviceToLogicalYRel(wxCoord y) const +{ + return YDEV2LOGREL(y); +} + + +wxCoord wxSVGFileDC::LogicalToDeviceX(wxCoord x) const +{ + return XLOG2DEV(x); +} + + +wxCoord wxSVGFileDC::LogicalToDeviceY(wxCoord y) const +{ + return YLOG2DEV(y); +} + + +wxCoord wxSVGFileDC::LogicalToDeviceXRel(wxCoord x) const +{ + return XLOG2DEVREL(x); +} + + +wxCoord wxSVGFileDC::LogicalToDeviceYRel(wxCoord y) const +{ + return YLOG2DEVREL(y); +} + + +#ifdef __BORLANDC__ +#pragma warn .rch +#pragma warn .ccc +#endif