1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        samples/printing.cpp
3 // Purpose:     Printing demo for wxWidgets
4 // Author:      Julian Smart
5 // Modified by: Francesco Montorsi
6 // Created:     1995
7 // Copyright:   (c) Julian Smart
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
13 
14 
15 #ifndef WX_PRECOMP
16     #include "wx/wx.h"
17     #include "wx/log.h"
18 #endif
19 
20 #if !wxUSE_PRINTING_ARCHITECTURE
21     #error "You must set wxUSE_PRINTING_ARCHITECTURE to 1 in setup.h, and recompile the library."
22 #endif
23 
24 #include <ctype.h>
25 #include "wx/metafile.h"
26 #include "wx/print.h"
27 #include "wx/printdlg.h"
28 #include "wx/image.h"
29 #include "wx/accel.h"
30 
31 #if wxUSE_POSTSCRIPT
32     #include "wx/generic/printps.h"
33     #include "wx/generic/prntdlgg.h"
34 #endif
35 
36 #if wxUSE_GRAPHICS_CONTEXT
37     #include "wx/graphics.h"
38     #include "wx/scopedptr.h"
39 #endif
40 
41 #ifdef __WXMAC__
42     #include "wx/osx/printdlg.h"
43 #endif
44 
45 #include "printing.h"
46 
47 #ifndef wxHAS_IMAGES_IN_RESOURCES
48     #include "../sample.xpm"
49 #endif
50 
51 // Global print data, to remember settings during the session
52 wxPrintData *g_printData = NULL;
53 
54 // Global page setup data
55 wxPageSetupDialogData* g_pageSetupData = NULL;
56 
57 
58 
59 // ----------------------------------------------------------------------------
60 // MyApp
61 // ----------------------------------------------------------------------------
62 
63 wxIMPLEMENT_APP(MyApp);
64 
OnInit(void)65 bool MyApp::OnInit(void)
66 {
67     if ( !wxApp::OnInit() )
68         return false;
69 
70     wxInitAllImageHandlers();
71 
72 
73     // init global objects
74     // -------------------
75 
76     g_printData = new wxPrintData;
77 
78     // You could set an initial paper size here
79 #if 0
80     g_printData->SetPaperId(wxPAPER_LETTER); // for Americans
81     g_printData->SetPaperId(wxPAPER_A4);    // for everyone else
82 #endif
83 
84     g_pageSetupData = new wxPageSetupDialogData;
85 
86     // copy over initial paper size from print record
87     (*g_pageSetupData) = *g_printData;
88 
89     // Set some initial page margins in mm.
90     g_pageSetupData->SetMarginTopLeft(wxPoint(15, 15));
91     g_pageSetupData->SetMarginBottomRight(wxPoint(15, 15));
92 
93 
94     // init local GUI objects
95     // ----------------------
96 
97 #if 0
98     wxImage image( "test.jpg" );
99     image.SetAlpha();
100     int i,j;
101     for (i = 0; i < image.GetWidth(); i++)
102        for (j = 0; j < image.GetHeight(); j++)
103           image.SetAlpha( i, j, 50 );
104     m_bitmap = image;
105 #endif
106     m_angle = 30;
107     m_testFont = wxFontInfo(10).Family(wxFONTFAMILY_SWISS);
108 
109 
110     // Create the main frame window
111     // ----------------------------
112 
113     MyFrame* frame = new MyFrame((wxFrame *) NULL, "wxWidgets Printing Demo",
114                                  wxPoint(0, 0), wxSize(400, 400));
115 
116     frame->Centre(wxBOTH);
117     frame->Show();
118 
119     return true;
120 }
121 
OnExit()122 int MyApp::OnExit()
123 {
124     delete g_printData;
125     delete g_pageSetupData;
126 
127     return wxApp::OnExit();
128 }
129 
Draw(wxDC & dc)130 void MyApp::Draw(wxDC&dc)
131 {
132     // This routine just draws a bunch of random stuff on the screen so that we
133     // can check that different types of object are being drawn consistently
134     // between the screen image, the print preview image (at various zoom
135     // levels), and the printed page.
136     dc.SetBackground(*wxWHITE_BRUSH);
137     // dc.Clear();
138     dc.SetFont(m_testFont);
139 
140     // dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
141 
142     dc.SetPen(*wxBLACK_PEN);
143     dc.SetBrush(*wxLIGHT_GREY_BRUSH);
144 
145     dc.DrawRectangle(0, 0, 230, 350);
146     dc.DrawLine(0, 0, 229, 349);
147     dc.DrawLine(229, 0, 0, 349);
148     dc.SetBrush(*wxTRANSPARENT_BRUSH);
149 
150     dc.SetBrush(*wxCYAN_BRUSH);
151     dc.SetPen(*wxRED_PEN);
152 
153     dc.DrawRoundedRectangle(0, 20, 200, 80, 20);
154 
155     dc.DrawText( "Rectangle 200 by 80", 40, 40);
156 
157     dc.SetPen( wxPen(*wxBLACK, 0, wxPENSTYLE_DOT_DASH) );
158     dc.DrawEllipse(50, 140, 100, 50);
159     dc.SetPen(*wxRED_PEN);
160 
161     dc.DrawText( "Test message: this is in 10 point text", 10, 180);
162 
163     dc.DrawRotatedText( "This\nis\na multi-line\ntext", 170, 100, -m_angle/1.5);
164 
165 #if wxUSE_UNICODE
166     const char *test = "Hebrew    שלום -- Japanese (日本語)";
167     wxString tmp = wxConvUTF8.cMB2WC( test );
168     dc.DrawText( tmp, 10, 200 );
169 #endif
170 
171     wxPoint points[5];
172     points[0].x = 0;
173     points[0].y = 0;
174     points[1].x = 20;
175     points[1].y = 0;
176     points[2].x = 20;
177     points[2].y = 20;
178     points[3].x = 10;
179     points[3].y = 20;
180     points[4].x = 10;
181     points[4].y = -20;
182     dc.DrawPolygon( 5, points, 20, 250, wxODDEVEN_RULE );
183     dc.DrawPolygon( 5, points, 50, 250, wxWINDING_RULE );
184 
185     dc.DrawArc( 20, 330, 40, 300, 20, 300 );
186     {
187         wxDCBrushChanger changeBrush(dc, *wxTRANSPARENT_BRUSH);
188         dc.DrawArc( 60, 330, 80, 300, 60, 300 );
189     }
190 
191     dc.DrawEllipticArc( 80, 250, 60, 30, 0.0, 270.0 );
192 
193     points[0].x = 150;
194     points[0].y = 250;
195     points[1].x = 180;
196     points[1].y = 250;
197     points[2].x = 180;
198     points[2].y = 220;
199     points[3].x = 200;
200     points[3].y = 220;
201     dc.DrawSpline( 4, points );
202 
203     wxString str;
204     int i = 0;
205     str.Printf( "---- Text at angle %d ----", i );
206     dc.DrawRotatedText( str, 100, 300, i );
207 
208     i = m_angle;
209     str.Printf( "---- Text at angle %d ----", i );
210     dc.DrawRotatedText( str, 100, 300, i );
211 
212     wxIcon my_icon = wxICON(sample);
213 
214     dc.DrawIcon( my_icon, 100, 100);
215 
216     if (m_bitmap.IsOk())
217         dc.DrawBitmap( m_bitmap, 10, 10 );
218 
219 #if wxUSE_GRAPHICS_CONTEXT
220     wxScopedPtr<wxGraphicsContext> gc(wxGraphicsContext::CreateFromUnknownDC(dc));
221 
222     if (gc)
223     {
224         // make a path that contains a circle and some lines, centered at 100,100
225         gc->SetPen( *wxRED_PEN );
226 
227         wxGraphicsPath path = gc->CreatePath();
228         path.AddCircle( 50.0, 50.0, 50.0 );
229         path.MoveToPoint(0.0, 50.0);
230         path.AddLineToPoint(100.0, 50.0);
231         path.MoveToPoint(50.0, 0.0);
232         path.AddLineToPoint(50.0, 100.0 );
233         path.CloseSubpath();
234         path.AddRectangle(25.0, 25.0, 50.0, 50.0);
235 
236         gc->StrokePath(path);
237 
238         // draw some text
239         wxString text("Text by wxGraphicsContext");
240         gc->SetFont( m_testFont, *wxBLACK );
241         gc->DrawText(text, 25.0, 60.0);
242 
243         // draw rectangle around the text
244         double w, h;
245         gc->GetTextExtent(text, &w, &h);
246         gc->SetPen( *wxBLACK_PEN );
247         gc->DrawRectangle(25.0, 60.0, w, h);
248     }
249 #endif
250 
251 }
252 
253 
254 // ----------------------------------------------------------------------------
255 // MyFrame
256 // ----------------------------------------------------------------------------
257 
wxBEGIN_EVENT_TABLE(MyFrame,wxFrame)258 wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
259     EVT_MENU(wxID_EXIT, MyFrame::OnExit)
260     EVT_MENU(wxID_PRINT, MyFrame::OnPrint)
261     EVT_MENU(wxID_PREVIEW, MyFrame::OnPrintPreview)
262     EVT_MENU(WXPRINT_PAGE_SETUP, MyFrame::OnPageSetup)
263     EVT_MENU(wxID_ABOUT, MyFrame::OnPrintAbout)
264 #if wxUSE_POSTSCRIPT
265     EVT_MENU(WXPRINT_PRINT_PS, MyFrame::OnPrintPS)
266     EVT_MENU(WXPRINT_PREVIEW_PS, MyFrame::OnPrintPreviewPS)
267     EVT_MENU(WXPRINT_PAGE_SETUP_PS, MyFrame::OnPageSetupPS)
268 #endif
269 #ifdef __WXMAC__
270     EVT_MENU(WXPRINT_PAGE_MARGINS, MyFrame::OnPageMargins)
271 #endif
272     EVT_MENU(WXPRINT_ANGLEUP, MyFrame::OnAngleUp)
273     EVT_MENU(WXPRINT_ANGLEDOWN, MyFrame::OnAngleDown)
274 
275     EVT_MENU_RANGE(WXPRINT_FRAME_MODAL_APP,
276                    WXPRINT_FRAME_MODAL_NON,
277                    MyFrame::OnPreviewFrameModalityKind)
278 wxEND_EVENT_TABLE()
279 
280 MyFrame::MyFrame(wxFrame *frame, const wxString&title, const wxPoint&pos, const wxSize&size)
281         : wxFrame(frame, wxID_ANY, title, pos, size)
282 {
283     m_canvas = NULL;
284     m_previewModality = wxPreviewFrame_AppModal;
285 
286 #if wxUSE_STATUSBAR
287     // Give us a status line
288     CreateStatusBar(2);
289     SetStatusText("Printing demo");
290 #endif // wxUSE_STATUSBAR
291 
292     // Load icon and bitmap
293     SetIcon( wxICON( sample) );
294 
295     // Make a menubar
296     wxMenu *file_menu = new wxMenu;
297 
298     file_menu->Append(wxID_PRINT, "&Print...",                 "Print");
299     file_menu->Append(WXPRINT_PAGE_SETUP, "Page Set&up...",    "Page setup");
300 #ifdef __WXMAC__
301     file_menu->Append(WXPRINT_PAGE_MARGINS, "Page Margins...", "Page margins");
302 #endif
303     file_menu->Append(wxID_PREVIEW, "Print Pre&view",          "Preview");
304 
305     wxMenu * const menuModalKind = new wxMenu;
306     menuModalKind->AppendRadioItem(WXPRINT_FRAME_MODAL_APP, "&App modal");
307     menuModalKind->AppendRadioItem(WXPRINT_FRAME_MODAL_WIN, "&Window modal");
308     menuModalKind->AppendRadioItem(WXPRINT_FRAME_MODAL_NON, "&Not modal");
309     file_menu->AppendSubMenu(menuModalKind, "Preview frame &modal kind");
310 #if wxUSE_ACCEL
311     // Accelerators
312     wxAcceleratorEntry entries[1];
313     entries[0].Set(wxACCEL_CTRL, (int) 'V', wxID_PREVIEW);
314     wxAcceleratorTable accel(1, entries);
315     SetAcceleratorTable(accel);
316 #endif
317 
318 #if wxUSE_POSTSCRIPT
319     file_menu->AppendSeparator();
320     file_menu->Append(WXPRINT_PRINT_PS, "Print PostScript...",           "Print (PostScript)");
321     file_menu->Append(WXPRINT_PAGE_SETUP_PS, "Page Setup PostScript...", "Page setup (PostScript)");
322     file_menu->Append(WXPRINT_PREVIEW_PS, "Print Preview PostScript",    "Preview (PostScript)");
323 #endif
324 
325     file_menu->AppendSeparator();
326     file_menu->Append(WXPRINT_ANGLEUP, "Angle up\tAlt-U",                "Raise rotated text angle");
327     file_menu->Append(WXPRINT_ANGLEDOWN, "Angle down\tAlt-D",            "Lower rotated text angle");
328     file_menu->AppendSeparator();
329     file_menu->Append(wxID_EXIT, "E&xit",                                "Exit program");
330 
331     wxMenu *help_menu = new wxMenu;
332     help_menu->Append(wxID_ABOUT, "&About",                              "About this demo");
333 
334     wxMenuBar *menu_bar = new wxMenuBar;
335 
336     menu_bar->Append(file_menu, "&File");
337     menu_bar->Append(help_menu, "&Help");
338 
339     // Associate the menu bar with the frame
340     SetMenuBar(menu_bar);
341 
342 
343     // create the canvas
344     // -----------------
345 
346     m_canvas = new MyCanvas(this, wxPoint(0, 0), wxSize(100, 100),
347                             wxRETAINED|wxHSCROLL|wxVSCROLL);
348 
349     // Give it scrollbars: the virtual canvas is 20 * 50 = 1000 pixels in each direction
350     m_canvas->SetScrollbars(20, 20, 50, 50);
351 }
352 
OnExit(wxCommandEvent & WXUNUSED (event))353 void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
354 {
355     Close(true /*force closing*/);
356 }
357 
OnPrint(wxCommandEvent & WXUNUSED (event))358 void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
359 {
360     wxPrintDialogData printDialogData(* g_printData);
361 
362     wxPrinter printer(&printDialogData);
363     MyPrintout printout(this, "My printout");
364     if (!printer.Print(this, &printout, true /*prompt*/))
365     {
366         if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
367         {
368             wxLogError("There was a problem printing. Perhaps your current printer is not set correctly?");
369         }
370         else
371         {
372             wxLogMessage("You canceled printing");
373         }
374     }
375     else
376     {
377         (*g_printData) = printer.GetPrintDialogData().GetPrintData();
378     }
379 }
380 
OnPrintPreview(wxCommandEvent & WXUNUSED (event))381 void MyFrame::OnPrintPreview(wxCommandEvent& WXUNUSED(event))
382 {
383     // Pass two printout objects: for preview, and possible printing.
384     wxPrintDialogData printDialogData(* g_printData);
385     wxPrintPreview *preview =
386         new wxPrintPreview(new MyPrintout(this), new MyPrintout(this), &printDialogData);
387     if (!preview->IsOk())
388     {
389         delete preview;
390         wxLogError("There was a problem previewing.\nPerhaps your current printer is not set correctly?");
391         return;
392     }
393 
394     wxPreviewFrame *frame =
395         new wxPreviewFrame(preview, this, "Demo Print Preview", wxPoint(100, 100), wxSize(600, 650));
396     frame->Centre(wxBOTH);
397     frame->InitializeWithModality(m_previewModality);
398     frame->Show();
399 }
400 
OnPageSetup(wxCommandEvent & WXUNUSED (event))401 void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
402 {
403     (*g_pageSetupData) = *g_printData;
404 
405     wxPageSetupDialog pageSetupDialog(this, g_pageSetupData);
406     pageSetupDialog.ShowModal();
407 
408     (*g_printData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
409     (*g_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
410 }
411 
412 #if wxUSE_POSTSCRIPT
OnPrintPS(wxCommandEvent & WXUNUSED (event))413 void MyFrame::OnPrintPS(wxCommandEvent& WXUNUSED(event))
414 {
415     wxPrintDialogData printDialogData(* g_printData);
416 
417     wxPostScriptPrinter printer(&printDialogData);
418     MyPrintout printout(this, "My printout");
419     printer.Print(this, &printout, true/*prompt*/);
420 
421     (*g_printData) = printer.GetPrintDialogData().GetPrintData();
422 }
423 
OnPrintPreviewPS(wxCommandEvent & WXUNUSED (event))424 void MyFrame::OnPrintPreviewPS(wxCommandEvent& WXUNUSED(event))
425 {
426     // Pass two printout objects: for preview, and possible printing.
427     wxPrintDialogData printDialogData(* g_printData);
428     wxPrintPreview *preview = new wxPrintPreview(new MyPrintout(this), new MyPrintout(this), &printDialogData);
429     wxPreviewFrame *frame =
430         new wxPreviewFrame(preview, this, "Demo Print Preview", wxPoint(100, 100), wxSize(600, 650));
431     frame->Centre(wxBOTH);
432     frame->Initialize();
433     frame->Show();
434 }
435 
OnPageSetupPS(wxCommandEvent & WXUNUSED (event))436 void MyFrame::OnPageSetupPS(wxCommandEvent& WXUNUSED(event))
437 {
438     (*g_pageSetupData) = * g_printData;
439 
440     wxGenericPageSetupDialog pageSetupDialog(this, g_pageSetupData);
441     pageSetupDialog.ShowModal();
442 
443     (*g_printData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
444     (*g_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
445 }
446 #endif
447 
448 #ifdef __WXMAC__
OnPageMargins(wxCommandEvent & WXUNUSED (event))449 void MyFrame::OnPageMargins(wxCommandEvent& WXUNUSED(event))
450 {
451     (*g_pageSetupData) = *g_printData;
452 
453     wxMacPageMarginsDialog pageMarginsDialog(this, g_pageSetupData);
454     pageMarginsDialog.ShowModal();
455 
456     (*g_printData) = pageMarginsDialog.GetPageSetupDialogData().GetPrintData();
457     (*g_pageSetupData) = pageMarginsDialog.GetPageSetupDialogData();
458 }
459 #endif
460 
OnPrintAbout(wxCommandEvent & WXUNUSED (event))461 void MyFrame::OnPrintAbout(wxCommandEvent& WXUNUSED(event))
462 {
463     (void)wxMessageBox("wxWidgets printing demo\nAuthor: Julian Smart",
464                        "About wxWidgets printing demo", wxOK|wxCENTRE);
465 }
466 
OnAngleUp(wxCommandEvent & WXUNUSED (event))467 void MyFrame::OnAngleUp(wxCommandEvent& WXUNUSED(event))
468 {
469     wxGetApp().IncrementAngle();
470     m_canvas->Refresh();
471 }
472 
OnAngleDown(wxCommandEvent & WXUNUSED (event))473 void MyFrame::OnAngleDown(wxCommandEvent& WXUNUSED(event))
474 {
475     wxGetApp().DecrementAngle();
476     m_canvas->Refresh();
477 }
478 
OnPreviewFrameModalityKind(wxCommandEvent & event)479 void MyFrame::OnPreviewFrameModalityKind(wxCommandEvent& event)
480 {
481     m_previewModality = static_cast<wxPreviewFrameModalityKind>(
482                             wxPreviewFrame_AppModal +
483                                 (event.GetId() - WXPRINT_FRAME_MODAL_APP));
484 }
485 
486 // ----------------------------------------------------------------------------
487 // MyCanvas
488 // ----------------------------------------------------------------------------
489 
wxBEGIN_EVENT_TABLE(MyCanvas,wxScrolledWindow)490 wxBEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
491   //  EVT_PAINT(MyCanvas::OnPaint)
492 wxEND_EVENT_TABLE()
493 
494 MyCanvas::MyCanvas(wxFrame *frame, const wxPoint&pos, const wxSize&size, long style)
495     : wxScrolledWindow(frame, wxID_ANY, pos, size, style)
496 {
497     SetBackgroundColour(*wxWHITE);
498 }
499 
500 //void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(evt))
OnDraw(wxDC & dc)501 void MyCanvas::OnDraw(wxDC& dc)
502 {
503     //wxPaintDC dc(this);
504     wxGetApp().Draw(dc);
505 }
506 
507 
508 // ----------------------------------------------------------------------------
509 // MyPrintout
510 // ----------------------------------------------------------------------------
511 
OnPrintPage(int page)512 bool MyPrintout::OnPrintPage(int page)
513 {
514     wxDC *dc = GetDC();
515     if (dc)
516     {
517         if (page == 1)
518             DrawPageOne();
519         else if (page == 2)
520             DrawPageTwo();
521 
522         // Draw page numbers at top left corner of printable area, sized so that
523         // screen size of text matches paper size.
524         MapScreenSizeToPage();
525 
526         dc->DrawText(wxString::Format("PAGE %d", page), 0, 0);
527 
528         return true;
529     }
530     else
531         return false;
532 }
533 
OnBeginDocument(int startPage,int endPage)534 bool MyPrintout::OnBeginDocument(int startPage, int endPage)
535 {
536     if (!wxPrintout::OnBeginDocument(startPage, endPage))
537         return false;
538 
539     return true;
540 }
541 
GetPageInfo(int * minPage,int * maxPage,int * selPageFrom,int * selPageTo)542 void MyPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
543 {
544     *minPage = 1;
545     *maxPage = 2;
546     *selPageFrom = 1;
547     *selPageTo = 2;
548 }
549 
HasPage(int pageNum)550 bool MyPrintout::HasPage(int pageNum)
551 {
552     return (pageNum == 1 || pageNum == 2);
553 }
554 
DrawPageOne()555 void MyPrintout::DrawPageOne()
556 {
557     // You might use THIS code if you were scaling graphics of known size to fit
558     // on the page. The commented-out code illustrates different ways of scaling
559     // the graphics.
560 
561     // We know the graphic is 230x350. If we didn't know this, we'd need to
562     // calculate it.
563     wxCoord maxX = 230;
564     wxCoord maxY = 350;
565 
566     // This sets the user scale and origin of the DC so that the image fits
567     // within the paper rectangle (but the edges could be cut off by printers
568     // that can't print to the edges of the paper -- which is most of them. Use
569     // this if your image already has its own margins.
570 //    FitThisSizeToPaper(wxSize(maxX, maxY));
571 //    wxRect fitRect = GetLogicalPaperRect();
572 
573     // This sets the user scale and origin of the DC so that the image fits
574     // within the page rectangle, which is the printable area on Mac and MSW
575     // and is the entire page on other platforms.
576 //    FitThisSizeToPage(wxSize(maxX, maxY));
577 //    wxRect fitRect = GetLogicalPageRect();
578 
579     // This sets the user scale and origin of the DC so that the image fits
580     // within the page margins as specified by g_PageSetupData, which you can
581     // change (on some platforms, at least) in the Page Setup dialog. Note that
582     // on Mac, the native Page Setup dialog doesn't let you change the margins
583     // of a wxPageSetupDialogData object, so you'll have to write your own dialog or
584     // use the Mac-only wxMacPageMarginsDialog, as we do in this program.
585     FitThisSizeToPageMargins(wxSize(maxX, maxY), *g_pageSetupData);
586     wxRect fitRect = GetLogicalPageMarginsRect(*g_pageSetupData);
587 
588     // This sets the user scale and origin of the DC so that the image appears
589     // on the paper at the same size that it appears on screen (i.e., 10-point
590     // type on screen is 10-point on the printed page) and is positioned in the
591     // top left corner of the page rectangle (just as the screen image appears
592     // in the top left corner of the window).
593 //    MapScreenSizeToPage();
594 //    wxRect fitRect = GetLogicalPageRect();
595 
596     // You could also map the screen image to the entire paper at the same size
597     // as it appears on screen.
598 //    MapScreenSizeToPaper();
599 //    wxRect fitRect = GetLogicalPaperRect();
600 
601     // You might also wish to do you own scaling in order to draw objects at
602     // full native device resolution. In this case, you should do the following.
603     // Note that you can use the GetLogicalXXXRect() commands to obtain the
604     // appropriate rect to scale to.
605 //    MapScreenSizeToDevice();
606 //    wxRect fitRect = GetLogicalPageRect();
607 
608     // Each of the preceding Fit or Map routines positions the origin so that
609     // the drawn image is positioned at the top left corner of the reference
610     // rectangle. You can easily center or right- or bottom-justify the image as
611     // follows.
612 
613     // This offsets the image so that it is centered within the reference
614     // rectangle defined above.
615     wxCoord xoff = (fitRect.width - maxX) / 2;
616     wxCoord yoff = (fitRect.height - maxY) / 2;
617     OffsetLogicalOrigin(xoff, yoff);
618 
619     // This offsets the image so that it is positioned at the bottom right of
620     // the reference rectangle defined above.
621 //    wxCoord xoff = (fitRect.width - maxX);
622 //    wxCoord yoff = (fitRect.height - maxY);
623 //    OffsetLogicalOrigin(xoff, yoff);
624 
625     wxGetApp().Draw(*GetDC());
626 }
627 
DrawPageTwo()628 void MyPrintout::DrawPageTwo()
629 {
630     // You might use THIS code to set the printer DC to ROUGHLY reflect
631     // the screen text size. This page also draws lines of actual length
632     // 5cm on the page.
633 
634     // Compare this to DrawPageOne(), which uses the really convenient routines
635     // from wxPrintout to fit the screen image onto the printed page. This page
636     // illustrates how to do all the scaling calculations yourself, if you're so
637     // inclined.
638 
639     wxDC *dc = GetDC();
640 
641     // Get the logical pixels per inch of screen and printer
642     int ppiScreenX, ppiScreenY;
643     GetPPIScreen(&ppiScreenX, &ppiScreenY);
644     int ppiPrinterX, ppiPrinterY;
645     GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
646 
647     // This scales the DC so that the printout roughly represents the screen
648     // scaling. The text point size _should_ be the right size but in fact is
649     // too small for some reason. This is a detail that will need to be
650     // addressed at some point but can be fudged for the moment.
651     double scale = double(ppiPrinterX) / ppiScreenX;
652 
653     // Now we have to check in case our real page size is reduced (e.g. because
654     // we're drawing to a print preview memory DC)
655     int pageWidth, pageHeight;
656     int w, h;
657     dc->GetSize(&w, &h);
658     GetPageSizePixels(&pageWidth, &pageHeight);
659 
660     // If printer pageWidth == current DC width, then this doesn't change. But w
661     // might be the preview bitmap width, so scale down.
662     double overallScale = scale * w / pageWidth;
663     dc->SetUserScale(overallScale, overallScale);
664 
665     // Calculate conversion factor for converting millimetres into logical
666     // units. There are approx. 25.4 mm to the inch. There are ppi device units
667     // to the inch. Therefore 1 mm corresponds to ppi/25.4 device units. We also
668     // divide by the screen-to-printer scaling factor, because we need to
669     // unscale to pass logical units to DrawLine.
670 
671     // Draw 50 mm by 50 mm L shape
672     double logUnitsFactor = ppiPrinterX / (scale * 25.4);
673     int logUnits = int(50 * logUnitsFactor);
674     dc->SetPen(* wxBLACK_PEN);
675     dc->DrawLine(50, 250, 50 + logUnits, 250);
676     dc->DrawLine(50, 250, 50, 250 + logUnits);
677 
678     dc->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
679     dc->SetBrush(*wxTRANSPARENT_BRUSH);
680 
681     { // GetTextExtent demo:
682         wxString words[7] = { "This ", "is ", "GetTextExtent ",
683                              "testing ", "string. ", "Enjoy ", "it!" };
684         long x = 200, y= 250;
685 
686         dc->SetFont(wxFontInfo(15).Family(wxFONTFAMILY_SWISS));
687 
688         for (int i = 0; i < 7; i++)
689         {
690             wxCoord wordWidth, wordHeight;
691             wxString word = words[i];
692             word.Remove( word.Len()-1, 1 );
693             dc->GetTextExtent(word, &wordWidth, &wordHeight);
694             dc->DrawRectangle(x, y, wordWidth, wordHeight);
695             dc->GetTextExtent(words[i], &wordWidth, &wordHeight);
696             dc->DrawText(words[i], x, y);
697             x += wordWidth;
698         }
699 
700     }
701 
702     dc->SetFont(wxGetApp().GetTestFont());
703 
704     dc->DrawText("Some test text", 200, 300 );
705 
706     // TESTING
707 
708     int leftMargin = 20;
709     int rightMargin = 20;
710     int topMargin = 20;
711     int bottomMargin = 20;
712 
713     int pageWidthMM, pageHeightMM;
714     GetPageSizeMM(&pageWidthMM, &pageHeightMM);
715 
716     int leftMarginLogical = int(logUnitsFactor * leftMargin);
717     int topMarginLogical = int(logUnitsFactor * topMargin);
718     int bottomMarginLogical = int(logUnitsFactor * (pageHeightMM - bottomMargin));
719     int rightMarginLogical = int(logUnitsFactor * (pageWidthMM - rightMargin));
720 
721     dc->SetPen(* wxRED_PEN);
722     dc->DrawLine(leftMarginLogical, topMarginLogical,
723         rightMarginLogical, topMarginLogical);
724     dc->DrawLine(leftMarginLogical, bottomMarginLogical,
725         rightMarginLogical, bottomMarginLogical);
726 
727     WritePageHeader(this, dc, "A header", logUnitsFactor);
728 }
729 
730 // Writes a header on a page. Margin units are in millimetres.
WritePageHeader(wxPrintout * printout,wxDC * dc,const wxString & text,double mmToLogical)731 bool MyPrintout::WritePageHeader(wxPrintout *printout, wxDC *dc, const wxString&text, double mmToLogical)
732 {
733     int pageWidthMM, pageHeightMM;
734 
735     printout->GetPageSizeMM(&pageWidthMM, &pageHeightMM);
736     wxUnusedVar(pageHeightMM);
737 
738     int leftMargin = 10;
739     int topMargin = 10;
740     int rightMargin = 10;
741 
742     int leftMarginLogical = int(mmToLogical * leftMargin);
743     int topMarginLogical = int(mmToLogical * topMargin);
744     int rightMarginLogical = int(mmToLogical * (pageWidthMM - rightMargin));
745 
746     wxCoord xExtent, yExtent;
747     dc->GetTextExtent(text, &xExtent, &yExtent);
748 
749     int xPos = int(((((pageWidthMM - leftMargin - rightMargin) / 2.0) + leftMargin) * mmToLogical) - (xExtent / 2.0));
750     dc->DrawText(text, xPos, topMarginLogical);
751 
752     dc->SetPen(* wxBLACK_PEN);
753     dc->DrawLine(leftMarginLogical, topMarginLogical + yExtent,
754                  rightMarginLogical, topMarginLogical + yExtent);
755 
756     return true;
757 }
758