home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / contrib / samples / svg / svgtest.cpp < prev   
C/C++ Source or Header  |  2002-06-23  |  18KB  |  606 lines

  1. // biol75@york.ac.uk (Chris Elliott) March 2000
  2.  
  3. #ifdef __BIDE__
  4. #define _NO_VCL
  5. #include "condefs.h"
  6. USERC("svg.rc");
  7. //---------------------------------------------------------------------------
  8. #define WinMain WinMain
  9. #endif
  10. /////////////////////////////////////////////////////////////////////////////
  11. // Name:        svgtest.cpp
  12. // Purpose:     SVG sample
  13. // Author:      Chris Elliott
  14. // Modified by:
  15. // RCS-ID:      $Id: svgtest.cpp,v 1.2 2002/06/21 09:46:32 CE Exp $
  16. // Licence:     wxWindows license
  17. /////////////////////////////////////////////////////////////////////////////
  18.  
  19. // ===========================================================================
  20. // declarations
  21. // ===========================================================================
  22.  
  23. // ---------------------------------------------------------------------------
  24. // headers
  25. // ---------------------------------------------------------------------------
  26.  
  27. // For compilers that support precompilation, includes "wx/wx.h".
  28. #include "wx/wxprec.h"
  29.  
  30. #ifdef __BORLANDC__
  31. #pragma hdrstop
  32. #endif
  33.  
  34. #ifndef WX_PRECOMP
  35. #include "wx/wx.h"
  36. #include "wx/mdi.h"
  37. #endif
  38.  
  39. #include <wx/toolbar.h>
  40. #include <wx/svg/dcsvg.h>
  41.  
  42. #ifndef __WXMSW__
  43. #include "mondrian.xpm"                                         
  44. #endif                                        
  45. #include "bitmaps/new.xpm"
  46. #include "bitmaps/save.xpm"
  47. #include "bitmaps/help.xpm"
  48. #include "SVGlogo24.xpm"
  49.                                          
  50. class MyChild;
  51.  
  52. // Define a new application
  53. class MyApp : public wxApp
  54. {
  55.     public:
  56.         bool OnInit();
  57. };
  58.  
  59. // Define a new frame
  60. class MyFrame : public wxMDIParentFrame
  61. {
  62.     public:
  63.         int nWinCreated;
  64.  
  65.         wxList m_children;
  66.  
  67.         MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
  68.             const wxPoint& pos, const wxSize& size, const long style);
  69.  
  70.         void InitToolBar(wxToolBar* toolBar);
  71.  
  72.         void OnSize(wxSizeEvent& event);
  73.         void OnAbout(wxCommandEvent& event);
  74.         void OnNewWindow(wxCommandEvent& event);
  75.         void OnQuit(wxCommandEvent& event);
  76.         void OnClose(wxCloseEvent& event);
  77.         void FileSavePicture (wxCommandEvent & WXUNUSED(event) ) ;
  78.  
  79.         DECLARE_EVENT_TABLE()
  80. };
  81.  
  82.  
  83. class MyCanvas : public wxScrolledWindow
  84. {
  85.     public:
  86.         int m_index ;
  87.    
  88.         MyChild * m_child ;
  89.         MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size);
  90.         virtual void OnDraw(wxDC& dc);
  91.  
  92.         DECLARE_EVENT_TABLE()
  93. };
  94.  
  95. class MyChild: public wxMDIChildFrame
  96. {
  97.     public:
  98.         MyCanvas *m_canvas;
  99.         MyFrame  *m_frame ;
  100.  
  101.         //////////////////// Methods
  102.  
  103.         MyChild(wxMDIParentFrame *parent, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
  104.         ~MyChild();
  105.  
  106.         void OnActivate(wxActivateEvent& event);
  107.         void OnQuit(wxCommandEvent& event);
  108.         void OnClose(wxCloseEvent& event);
  109.         bool OnSave(wxString filename) ;
  110.  
  111.         DECLARE_EVENT_TABLE()
  112. };
  113.  
  114. // menu items ids
  115. enum
  116. {
  117.     MDI_QUIT = 100,
  118.     MDI_NEW_WINDOW,
  119.     MDI_SAVE,
  120.     MDI_REFRESH,
  121.     MDI_CHILD_QUIT,
  122.     MDI_ABOUT
  123. };
  124.  
  125.  
  126. IMPLEMENT_APP(MyApp)
  127.  
  128. // ---------------------------------------------------------------------------
  129. // global variables
  130. // ---------------------------------------------------------------------------
  131.  
  132. MyFrame *frame = (MyFrame *) NULL;
  133.  
  134. // ---------------------------------------------------------------------------
  135. // event tables
  136. // ---------------------------------------------------------------------------
  137.  
  138. BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame)
  139. EVT_MENU(MDI_ABOUT, MyFrame::OnAbout)
  140. EVT_MENU(MDI_NEW_WINDOW, MyFrame::OnNewWindow)
  141. EVT_MENU(MDI_QUIT, MyFrame::OnQuit)
  142. EVT_MENU (MDI_SAVE, MyFrame::FileSavePicture)
  143. EVT_CLOSE(MyFrame::OnClose)
  144.  
  145. EVT_SIZE(MyFrame::OnSize)
  146. END_EVENT_TABLE()
  147.  
  148. // ===========================================================================
  149. // implementation
  150. // ===========================================================================
  151.  
  152. // ---------------------------------------------------------------------------
  153. // MyApp
  154. // ---------------------------------------------------------------------------
  155.  
  156. // Initialise this in OnInit, not statically
  157. bool MyApp::OnInit()
  158. {
  159.     // Create the main frame window
  160.  
  161.     frame = new MyFrame((wxFrame *)NULL, -1, wxT("SVG Demo"),
  162.         wxPoint(-1, -1), wxSize(500, 400),
  163.         wxDEFAULT_FRAME_STYLE | wxHSCROLL | wxVSCROLL);
  164.         
  165.  
  166.     // Make a menubar
  167.     wxMenu *file_menu = new wxMenu;
  168.  
  169.     file_menu->Append(MDI_NEW_WINDOW, wxT("&New test\tCtrl+N"));
  170.     file_menu->Append(MDI_QUIT, wxT("&Exit\tAlt+X"));
  171.  
  172.     wxMenu *help_menu = new wxMenu;
  173.     help_menu->Append(MDI_ABOUT, wxT("&About"));
  174.  
  175.     wxMenuBar *menu_bar = new wxMenuBar;
  176.  
  177.     menu_bar->Append(file_menu, wxT("&File"));
  178.     menu_bar->Append(help_menu, wxT("&Help"));
  179.  
  180.     // Associate the menu bar with the frame
  181.     frame->SetMenuBar(menu_bar);
  182.  
  183.     frame->CreateStatusBar();
  184.  
  185.     frame->Show(TRUE);
  186.  
  187.     SetTopWindow(frame);
  188.  
  189.     return TRUE;
  190. }
  191.  
  192.  
  193. // ---------------------------------------------------------------------------
  194. // MyFrame
  195. // ---------------------------------------------------------------------------
  196.  
  197. // Define my frame constructor
  198. MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
  199.     const wxPoint& pos, const wxSize& size, const long style)
  200.         : wxMDIParentFrame(parent, id, title, pos, size, style)
  201. {
  202.     nWinCreated = 0 ;
  203.  
  204.     // Give it an icon
  205.     SetIcon(wxICON(mondrian));
  206.  
  207.     CreateToolBar(wxNO_BORDER | wxTB_FLAT | wxTB_HORIZONTAL);
  208.     InitToolBar(GetToolBar());
  209.  
  210. }
  211.  
  212.  
  213. void MyFrame::OnClose(wxCloseEvent& event)
  214. {
  215.     if ( !event.CanVeto() )
  216.     {
  217.         event.Skip();
  218.         return ;
  219.     }
  220.     if ( m_children.Number () < 1 )
  221.     {
  222.         event.Skip();
  223.         return ;
  224.     }
  225.     // now try the children
  226.     wxNode * pNode = m_children.GetFirst ();
  227.     wxNode * pNext ;
  228.     MyChild * pChild ;
  229.     while ( pNode )
  230.     {
  231.         pNext = pNode -> GetNext ();
  232.         pChild = (MyChild*) pNode -> Data ();
  233.         if (pChild -> Close ())
  234.         {
  235.             delete pNode ;
  236.         }
  237.         else
  238.         {
  239.             event.Veto();
  240.             return;
  241.         }
  242.         pNode = pNext ;
  243.     }
  244.     event.Skip();
  245. }
  246.  
  247.  
  248. void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  249. {
  250.     Close();
  251. }
  252.  
  253.  
  254. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
  255. {
  256.     (void)wxMessageBox(wxT("wxWindows 2.0 SVG 1.0 Test\n"
  257.         "Author: Chris Elliott (c) 2002\n"
  258.         "Usage: svg.exe \nClick File | New to show tests\n\n"), wxT("About SVG Test"));
  259. }
  260.  
  261.  
  262. void MyFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event) )
  263. {
  264.     // Make another frame, containing a canvas
  265.     MyChild *subframe ;
  266.  
  267.     m_children.Append (new MyChild(frame, wxT("SVG Frame"),
  268.         wxPoint(-1, -1), wxSize(-1, -1),
  269.         wxDEFAULT_FRAME_STYLE )   ) ;
  270.  
  271.     subframe = (MyChild *) m_children.GetLast() -> Data ();
  272.     wxString title;
  273.     title.Printf(wxT("SVG Test Window %d"), nWinCreated );
  274.     // counts number of children previously, even if now closed
  275.     nWinCreated ++ ;
  276.  
  277.     // Give it a title and icon
  278.     subframe->SetTitle(title);
  279.     subframe->SetIcon(wxICON(mondrian));
  280.  
  281.     // Make a menubar
  282.     wxMenu *file_menu = new wxMenu;
  283.  
  284.     file_menu->Append(MDI_NEW_WINDOW, wxT("&Another test\tCtrl+N"));
  285.     file_menu->Append(MDI_SAVE, wxT("&Save\tCtrl+S"), wxT("Save in SVG format"));
  286.     file_menu->Append(MDI_CHILD_QUIT, wxT("&Close child\tCtrl+F4"));
  287.     file_menu->Append(MDI_QUIT, wxT("&Exit\tAlt+X"));
  288.  
  289.     wxMenu *help_menu = new wxMenu;
  290.     help_menu->Append(MDI_ABOUT, wxT("&About"));
  291.  
  292.     wxMenuBar *menu_bar = new wxMenuBar;
  293.  
  294.     menu_bar->Append(file_menu, wxT("&File"));
  295.     menu_bar->Append(help_menu, wxT("&Help"));
  296.  
  297.     // Associate the menu bar with the frame
  298.     subframe->SetMenuBar(menu_bar);
  299.  
  300.     subframe->Show(TRUE);
  301. }
  302.  
  303.  
  304. void MyFrame::OnSize(wxSizeEvent& WXUNUSED(event))
  305. {
  306.     int w, h;
  307.     GetClientSize(&w, &h);
  308.  
  309.     GetClientWindow()->SetSize(0, 0, w, h);
  310. }
  311.  
  312.  
  313. void MyFrame::InitToolBar(wxToolBar* toolBar)
  314. {
  315.     const int maxBitmaps = 3 ;
  316.     wxBitmap* bitmaps[maxBitmaps];
  317.  
  318.     bitmaps[0] = new wxBitmap( new_xpm );
  319.     bitmaps[1] = new wxBitmap( save_xpm );
  320.     bitmaps[2] = new wxBitmap( help_xpm );
  321.  
  322.     int width = 16;
  323.     int currentX = 5;
  324.  
  325.     toolBar->AddTool( MDI_NEW_WINDOW, *(bitmaps[0]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, wxT("New SVG test window"));
  326.     currentX += width + 5;
  327.     toolBar->AddTool( MDI_SAVE, *bitmaps[1], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, wxT("Save test in SVG format"));
  328.     currentX += width + 5;
  329.     toolBar->AddSeparator();      
  330.     toolBar->AddTool(MDI_ABOUT, *bitmaps[2], wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, wxT("Help"));
  331.  
  332.     toolBar->Realize();
  333.  
  334.     int i;
  335.     for (i = 0; i < maxBitmaps; i++)
  336.         delete bitmaps[i];
  337. }
  338.  
  339.  
  340. void MyFrame::FileSavePicture (wxCommandEvent & WXUNUSED(event) )
  341. {
  342.     MyChild * pChild = (MyChild *)GetActiveChild ();
  343.     if (pChild == NULL) 
  344.     {
  345.         return ;
  346.     }
  347.  
  348.     wxFileDialog dialog(this, wxT("Save Picture as"), wxEmptyString, pChild->GetTitle(),
  349.         wxT("SVG vector picture files (*.svg)|*.svg"),
  350.         wxSAVE|wxOVERWRITE_PROMPT);
  351.  
  352.     if (dialog.ShowModal() == wxID_OK)
  353.     {
  354.         if (!pChild -> OnSave ( dialog.GetPath() ))
  355.         {
  356.             return ;
  357.         }
  358.     }
  359.     return ;
  360. }
  361.  
  362.  
  363. // Note that MDI_NEW_WINDOW and MDI_ABOUT commands get passed
  364. // to the parent window for processing, so no need to
  365. // duplicate event handlers here.
  366. BEGIN_EVENT_TABLE(MyChild, wxMDIChildFrame)
  367.     EVT_MENU(MDI_CHILD_QUIT, MyChild::OnQuit)
  368.     EVT_CLOSE(MyChild::OnClose)
  369. END_EVENT_TABLE()
  370.  
  371. BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
  372.  
  373. END_EVENT_TABLE()
  374.  
  375. // ---------------------------------------------------------------------------
  376. // MyCanvas
  377. // ---------------------------------------------------------------------------
  378.  
  379. // Define a constructor for my canvas
  380. MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size)
  381. : wxScrolledWindow(parent, -1, pos, size,
  382. wxSUNKEN_BORDER|wxVSCROLL|wxHSCROLL)
  383. {
  384.     m_child = (MyChild *) parent ;
  385.     SetBackgroundColour(wxColour("WHITE"));
  386.     m_index = m_child->m_frame->nWinCreated % 7 ;
  387. }
  388.  
  389.  
  390. // Define the repainting behaviour
  391. void MyCanvas::OnDraw(wxDC& dc)
  392. {
  393.     // vars to use ...
  394.     wxString s ;
  395.     wxPen wP ;
  396.     wxBrush wB ;
  397.     wxPoint points[6];
  398.     wxColour wC;
  399.     wxFont wF ;
  400.  
  401.     dc.SetFont(*wxSWISS_FONT);
  402.     dc.SetPen(*wxGREEN_PEN);
  403.  
  404.     
  405.     switch (m_index)
  406.     {
  407.         default:
  408.         case 0:
  409.             // draw lines to make a cross
  410.             dc.DrawLine(0, 0, 200, 200);
  411.             dc.DrawLine(200, 0, 0, 200);
  412.             // draw point colored line and spline
  413.             wP = *wxCYAN_PEN ;
  414.             wP.SetWidth(3);
  415.             dc.SetPen(wP);
  416.  
  417.             dc.DrawPoint (25,15) ;
  418.             dc.DrawLine(50, 30, 200, 30);
  419.             dc.DrawSpline(50, 200, 50, 100, 200, 10);
  420.             s = wxT("Green Cross, Cyan Line and spline");
  421.             break ;
  422.  
  423.         case 1:
  424.             // draw standard shapes
  425.             dc.SetBrush(*wxCYAN_BRUSH);
  426.             dc.SetPen(*wxRED_PEN);
  427.             dc.DrawRectangle(10, 10, 100, 70);
  428.             wB = wxBrush ("DARK ORCHID", wxTRANSPARENT);
  429.             dc.SetBrush (wB);
  430.             dc.DrawRoundedRectangle(50, 50, 100, 70, 20);
  431.             dc.SetBrush (wxBrush("GOLDENROD", wxSOLID) );
  432.             dc.DrawEllipse(100, 100, 100, 50);
  433.  
  434.             points[0].x = 100; points[0].y = 200;
  435.             points[1].x = 70; points[1].y = 260;
  436.             points[2].x = 160; points[2].y = 230;
  437.             points[3].x = 40; points[3].y = 230;
  438.             points[4].x = 130; points[4].y = 260;
  439.             points[5].x = 100; points[5].y = 200;
  440.  
  441.             dc.DrawPolygon(5, points);
  442.             dc.DrawLines (6, points, 160);
  443.             s = wxT("Blue rectangle, red edge, clear rounded rectangle, gold ellipse, gold and clear stars");
  444.             break ;
  445.  
  446.         case 2:
  447.             // draw text in Arial or similar font
  448.             dc.DrawLine(50,25,50,35);
  449.             dc.DrawLine(45,30,55,30);
  450.             dc.DrawText(wxT("This is a Swiss-style string"), 50, 30);
  451.             wC = dc.GetTextForeground() ;
  452.             dc.SetTextForeground ("FIREBRICK");
  453.                                  
  454.             // no effect in msw ??
  455.             dc.SetTextBackground ("WHEAT");
  456.             dc.DrawText(wxT("This is a Red string"), 50, 200);
  457.             dc.DrawRotatedText(wxT("This is a 45 deg string"), 50, 200, 45);
  458.             dc.DrawRotatedText(wxT("This is a 90 deg string"), 50, 200, 90);
  459.             wF = wxFont ( 18, wxROMAN, wxITALIC, wxBOLD, FALSE, wxT("Times New Roman"));
  460.             dc.SetFont(wF);
  461.             dc.SetTextForeground (wC) ;
  462.             dc.DrawText(wxT("This is a Times-style string"), 50, 60);
  463.             s = wxT("Swiss, Times text; red text, rotated and colored orange");
  464.             break ;
  465.  
  466.         case 3 :
  467.             // four arcs start and end points, center
  468.             dc.SetBrush(*wxGREEN_BRUSH);
  469.             dc.DrawArc ( 200,300, 370,230, 300.0,300.0 );
  470.             dc.SetBrush(*wxBLUE_BRUSH);
  471.             dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270.0,270.0 );
  472.             dc.SetDeviceOrigin(-10,-10);
  473.             dc.DrawArc ( 270-50, 270-86, 270-86, 270-50, 270.0,270.0 );
  474.             dc.SetDeviceOrigin(0,0);
  475.  
  476.             wP.SetColour ("CADET BLUE");
  477.             dc.SetPen(wP);
  478.             dc.DrawArc ( 75,125, 110, 40, 75.0, 75.0 );
  479.  
  480.             wP.SetColour ("SALMON");
  481.             dc.SetPen(wP);
  482.             dc.SetBrush(*wxRED_BRUSH);
  483.             //top left corner, width and height, start and end angle
  484.                                  // 315 same center and x-radius as last pie-arc, half Y radius
  485.             dc.DrawEllipticArc(25,50,100,50,180.0,45.0) ;
  486.  
  487.             wP = *wxCYAN_PEN ;
  488.             wP.SetWidth(3);
  489.             dc.SetPen(wP);
  490.                                  //wxTRANSPARENT));
  491.             dc.SetBrush (wxBrush ("SALMON",wxSOLID)) ;
  492.             dc.DrawEllipticArc(300,  0,200,100, 0.0,145.0) ;
  493.                                  //same end point
  494.             dc.DrawEllipticArc(300, 50,200,100,90.0,145.0) ;
  495.             dc.DrawEllipticArc(300,100,200,100,90.0,345.0) ;
  496.  
  497.             s = wxT("This is an arc test page");
  498.             break ;
  499.  
  500.         case 4:
  501.             dc.DrawCheckMark ( 30,30,25,25);
  502.             dc.SetBrush (wxBrush ("SALMON",wxTRANSPARENT));
  503.             dc.DrawCheckMark ( 80,50,75,75);
  504.             dc.DrawRectangle ( 80,50,75,75);
  505.             s = wxT("Two check marks");
  506.             break ;
  507.  
  508.         case 5:
  509.             wF = wxFont ( 18, wxROMAN, wxITALIC, wxBOLD, FALSE, wxT("Times New Roman"));
  510.             dc.SetFont(wF);
  511.             dc.DrawLine(0, 0, 200, 200);
  512.             dc.DrawLine(200, 0, 0, 200);
  513.             dc.DrawText(wxT("This is an 18pt string"), 50, 60);
  514.  
  515.             // rescale and draw in blue
  516.             wP = *wxCYAN_PEN ;
  517.             dc.SetPen(wP);
  518.             dc.SetUserScale (2.0,0.5);
  519.             dc.SetDeviceOrigin(200,0);
  520.             dc.DrawLine(0, 0, 200, 200);
  521.             dc.DrawLine(200, 0, 0, 200);
  522.             dc.DrawText(wxT("This is an 18pt string 2 x 0.5 UserScaled"), 50, 60);
  523.             dc.SetUserScale (2.0,2.0);
  524.             dc.SetDeviceOrigin(200,200);
  525.             dc.DrawText(wxT("This is an 18pt string 2 x 2 UserScaled"), 50, 60);
  526.  
  527.             wP = *wxRED_PEN ;
  528.             dc.SetPen(wP);
  529.             dc.SetUserScale (1.0,1.0);
  530.             dc.SetDeviceOrigin(0,10);
  531.             dc.SetMapMode (wxMM_METRIC) ; //svg ignores this
  532.             dc.DrawLine(0, 0, 200, 200);
  533.             dc.DrawLine(200, 0, 0, 200);
  534.             dc.DrawText(wxT("This is an 18pt string in MapMode"), 50, 60); 
  535.             s = wxT("Scaling test page");
  536.             break ;
  537.  
  538.         case 6:
  539.             dc.DrawIcon( wxICON(mondrian), 10, 10 );
  540.             dc.DrawBitmap ( wxBITMAP (svgbitmap), 50,15);
  541.             s = wxT("Icon and Bitmap ");
  542.             break ;
  543.  
  544.     }
  545.     m_child->SetStatusText(s);
  546. }
  547.  
  548.  
  549.  
  550.  
  551. // ---------------------------------------------------------------------------
  552. // MyChild
  553. // ---------------------------------------------------------------------------
  554.  
  555. MyChild::MyChild(wxMDIParentFrame *parent, const wxString& title,
  556. const wxPoint& pos, const wxSize& size,
  557. const long style)
  558. : wxMDIChildFrame(parent, -1, title, pos, size, style)
  559. {
  560.  
  561.     m_frame = (MyFrame *) parent ;
  562.     CreateStatusBar();
  563.     SetStatusText(title);    
  564.  
  565.     int w, h ;
  566.     GetClientSize ( &w, &h );
  567.     m_canvas = new MyCanvas(this, wxPoint(0, 0),  wxSize (w,h)  );
  568.     // Give it scrollbars
  569.     m_canvas->SetScrollbars(20, 20, 50, 50);
  570.  
  571. }
  572.  
  573.  
  574. MyChild::~MyChild()
  575. {
  576.     m_frame->m_children.DeleteObject(this);
  577. }
  578.  
  579.  
  580. void MyChild::OnQuit(wxCommandEvent& WXUNUSED(event))
  581. {
  582.     Close(TRUE);
  583. }
  584.  
  585.  
  586. bool MyChild::OnSave(wxString filename)
  587. {
  588.     wxSVGFileDC svgDC (filename, 600, 650) ;
  589.     m_canvas->OnDraw (svgDC);
  590.     return svgDC.Ok();
  591. }
  592.  
  593.  
  594.  
  595. void MyChild::OnActivate(wxActivateEvent& event)
  596. {
  597.     if ( event.GetActive() && m_canvas )
  598.         m_canvas->SetFocus();
  599. }
  600.  
  601.  
  602. void MyChild::OnClose(wxCloseEvent& event)
  603. {
  604.     event.Skip();
  605. }
  606.