1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: html printing classes
4 // Author: Vaclav Slavik
7 // Copyright: (c) Vaclav Slavik, 1999
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "htmprint.h"
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
31 #if wxUSE_HTML && wxUSE_PRINTING_ARCHITECTURE && wxUSE_STREAMS
35 #include "wx/printdlg.h"
36 #include "wx/html/htmprint.h"
37 #include "wx/wxhtml.h"
38 #include "wx/wfstream.h"
39 #include "wx/module.h"
40 #include "wx/settings.h"
43 //--------------------------------------------------------------------------------
45 //--------------------------------------------------------------------------------
48 wxHtmlDCRenderer::wxHtmlDCRenderer() : wxObject()
51 m_Width
= m_Height
= 0;
53 m_Parser
= new wxHtmlWinParser(NULL
);
54 m_FS
= new wxFileSystem();
55 m_Parser
->SetFS(m_FS
);
60 wxHtmlDCRenderer::~wxHtmlDCRenderer()
62 if (m_Cells
) delete m_Cells
;
63 if (m_Parser
) delete m_Parser
;
64 if (m_FS
) delete m_FS
;
69 void wxHtmlDCRenderer::SetDC(wxDC
*dc
, double pixel_scale
)
72 m_Parser
->SetDC(m_DC
, pixel_scale
);
77 void wxHtmlDCRenderer::SetSize(int width
, int height
)
84 void wxHtmlDCRenderer::SetHtmlText(const wxString
& html
, const wxString
& basepath
, bool isdir
)
86 if (m_DC
== NULL
) return;
88 if (m_Cells
!= NULL
) delete m_Cells
;
90 m_FS
->ChangePathTo(basepath
, isdir
);
91 m_Cells
= (wxHtmlContainerCell
*) m_Parser
->Parse(html
);
92 m_Cells
->SetIndent(0, wxHTML_INDENT_ALL
, wxHTML_UNITS_PIXELS
);
93 m_Cells
->Layout(m_Width
);
97 void wxHtmlDCRenderer::SetFonts(wxString normal_face
, wxString fixed_face
,
100 m_Parser
->SetFonts(normal_face
, fixed_face
, sizes
);
101 if (m_DC
== NULL
&& m_Cells
!= NULL
) m_Cells
->Layout(m_Width
);
105 void wxHtmlDCRenderer::NormalizeFontSizes(int size
)
109 size
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
).GetPointSize();
111 f_sizes
[0] = int(size
* 0.6);
112 f_sizes
[1] = int(size
* 0.8);
114 f_sizes
[3] = int(size
* 1.2);
115 f_sizes
[4] = int(size
* 1.4);
116 f_sizes
[5] = int(size
* 1.6);
117 f_sizes
[6] = int(size
* 1.8);
119 SetFonts(wxEmptyString
, wxEmptyString
, f_sizes
);
123 int wxHtmlDCRenderer::Render(int x
, int y
, int from
, int dont_render
, int to
, int *known_pagebreaks
, int number_of_pages
)
127 if (m_Cells
== NULL
|| m_DC
== NULL
) return 0;
129 pbreak
= (int)(from
+ m_Height
);
130 while (m_Cells
->AdjustPagebreak(&pbreak
, known_pagebreaks
, number_of_pages
)) {}
131 hght
= pbreak
- from
;
137 wxHtmlRenderingInfo rinfo
;
138 wxDefaultHtmlRenderingStyle rstyle
;
139 rinfo
.SetStyle(&rstyle
);
140 m_DC
->SetBrush(*wxWHITE_BRUSH
);
141 m_DC
->SetClippingRegion(x
, y
, m_Width
, hght
);
144 y
, pbreak
+ (y
/*- from*/),
146 m_DC
->DestroyClippingRegion();
149 if (pbreak
< m_Cells
->GetHeight()) return pbreak
;
150 else return GetTotalHeight();
155 int wxHtmlDCRenderer::GetTotalHeight()
157 if (m_Cells
) return m_Cells
->GetHeight();
162 //--------------------------------------------------------------------------------
164 //--------------------------------------------------------------------------------
167 wxList
wxHtmlPrintout::m_Filters
;
169 wxHtmlPrintout::wxHtmlPrintout(const wxString
& title
) : wxPrintout(title
)
171 m_Renderer
= new wxHtmlDCRenderer
;
172 m_RendererHdr
= new wxHtmlDCRenderer
;
173 m_NumPages
= wxHTML_PRINT_MAX_PAGES
;
174 m_Document
= m_BasePath
= wxEmptyString
; m_BasePathIsDir
= TRUE
;
175 m_Headers
[0] = m_Headers
[1] = wxEmptyString
;
176 m_Footers
[0] = m_Footers
[1] = wxEmptyString
;
177 m_HeaderHeight
= m_FooterHeight
= 0;
178 SetMargins(); // to default values
183 wxHtmlPrintout::~wxHtmlPrintout()
186 delete m_RendererHdr
;
189 void wxHtmlPrintout::CleanUpStatics()
191 WX_CLEAR_LIST(wxList
, m_Filters
);
195 void wxHtmlPrintout::AddFilter(wxHtmlFilter
*filter
)
197 m_Filters
.Append(filter
);
200 void wxHtmlPrintout::OnPreparePrinting()
202 int pageWidth
, pageHeight
, mm_w
, mm_h
, scr_w
, scr_h
, dc_w
, dc_h
;
203 float ppmm_h
, ppmm_v
;
205 GetPageSizePixels(&pageWidth
, &pageHeight
);
206 GetPageSizeMM(&mm_w
, &mm_h
);
207 ppmm_h
= (float)pageWidth
/ mm_w
;
208 ppmm_v
= (float)pageHeight
/ mm_h
;
210 int ppiPrinterX
, ppiPrinterY
;
211 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
212 int ppiScreenX
, ppiScreenY
;
213 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
215 wxDisplaySize(&scr_w
, &scr_h
);
216 GetDC()->GetSize(&dc_w
, &dc_h
);
218 GetDC()->SetUserScale((double)dc_w
/ (double)pageWidth
, (double)dc_w
/ (double)pageWidth
);
220 /* prepare headers/footers renderer: */
222 m_RendererHdr
->SetDC(GetDC(), (double)ppiPrinterY
/ (double)ppiScreenY
);
223 m_RendererHdr
->SetSize((int) (ppmm_h
* (mm_w
- m_MarginLeft
- m_MarginRight
)),
224 (int) (ppmm_v
* (mm_h
- m_MarginTop
- m_MarginBottom
)));
225 if (m_Headers
[0] != wxEmptyString
)
227 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Headers
[0], 1));
228 m_HeaderHeight
= m_RendererHdr
->GetTotalHeight();
230 else if (m_Headers
[1] != wxEmptyString
)
232 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Headers
[1], 1));
233 m_HeaderHeight
= m_RendererHdr
->GetTotalHeight();
235 if (m_Footers
[0] != wxEmptyString
)
237 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Footers
[0], 1));
238 m_FooterHeight
= m_RendererHdr
->GetTotalHeight();
240 else if (m_Footers
[1] != wxEmptyString
)
242 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Footers
[1], 1));
243 m_FooterHeight
= m_RendererHdr
->GetTotalHeight();
246 /* prepare main renderer: */
247 m_Renderer
->SetDC(GetDC(), (double)ppiPrinterY
/ (double)ppiScreenY
);
248 m_Renderer
->SetSize((int) (ppmm_h
* (mm_w
- m_MarginLeft
- m_MarginRight
)),
249 (int) (ppmm_v
* (mm_h
- m_MarginTop
- m_MarginBottom
) -
250 m_FooterHeight
- m_HeaderHeight
-
251 ((m_HeaderHeight
== 0) ? 0 : m_MarginSpace
* ppmm_v
) -
252 ((m_FooterHeight
== 0) ? 0 : m_MarginSpace
* ppmm_v
)
254 m_Renderer
->SetHtmlText(m_Document
, m_BasePath
, m_BasePathIsDir
);
258 bool wxHtmlPrintout::OnBeginDocument(int startPage
, int endPage
)
260 if (!wxPrintout::OnBeginDocument(startPage
, endPage
)) return FALSE
;
266 bool wxHtmlPrintout::OnPrintPage(int page
)
272 RenderPage(dc
, page
);
279 void wxHtmlPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
)
282 *maxPage
= m_NumPages
;
284 *selPageTo
= m_NumPages
;
289 bool wxHtmlPrintout::HasPage(int pageNum
)
291 return (pageNum
>= 1 && pageNum
<= m_NumPages
);
296 void wxHtmlPrintout::SetHtmlText(const wxString
& html
, const wxString
&basepath
, bool isdir
)
299 m_BasePath
= basepath
;
300 m_BasePathIsDir
= isdir
;
303 void wxHtmlPrintout::SetHtmlFile(const wxString
& htmlfile
)
306 wxFSFile
*ff
= fs
.OpenFile(htmlfile
);
310 wxLogError(htmlfile
+ _(": file does not exist!"));
315 wxHtmlFilterHTML defaultFilter
;
318 wxList::compatibility_iterator node
= m_Filters
.GetFirst();
321 wxHtmlFilter
*h
= (wxHtmlFilter
*) node
->GetData();
324 doc
= h
->ReadFile(*ff
);
328 node
= node
->GetNext();
332 doc
= defaultFilter
.ReadFile(*ff
);
334 SetHtmlText(doc
, htmlfile
, FALSE
);
340 void wxHtmlPrintout::SetHeader(const wxString
& header
, int pg
)
342 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_EVEN
)
343 m_Headers
[0] = header
;
344 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_ODD
)
345 m_Headers
[1] = header
;
350 void wxHtmlPrintout::SetFooter(const wxString
& footer
, int pg
)
352 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_EVEN
)
353 m_Footers
[0] = footer
;
354 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_ODD
)
355 m_Footers
[1] = footer
;
360 void wxHtmlPrintout::CountPages()
363 int pageWidth
, pageHeight
, mm_w
, mm_h
;
364 float ppmm_h
, ppmm_v
;
366 GetPageSizePixels(&pageWidth
, &pageHeight
);
367 GetPageSizeMM(&mm_w
, &mm_h
);
368 ppmm_h
= (float)pageWidth
/ mm_w
;
369 ppmm_v
= (float)pageHeight
/ mm_h
;
378 pos
= m_Renderer
->Render((int)( ppmm_h
* m_MarginLeft
),
379 (int) (ppmm_v
* (m_MarginTop
+ (m_HeaderHeight
== 0 ? 0 : m_MarginSpace
)) + m_HeaderHeight
),
380 pos
, TRUE
, INT_MAX
, m_PageBreaks
, m_NumPages
);
381 m_PageBreaks
[++m_NumPages
] = pos
;
382 } while (pos
< m_Renderer
->GetTotalHeight());
387 void wxHtmlPrintout::RenderPage(wxDC
*dc
, int page
)
391 int pageWidth
, pageHeight
, mm_w
, mm_h
, scr_w
, scr_h
, dc_w
, dc_h
;
392 float ppmm_h
, ppmm_v
;
394 GetPageSizePixels(&pageWidth
, &pageHeight
);
395 GetPageSizeMM(&mm_w
, &mm_h
);
396 ppmm_h
= (float)pageWidth
/ mm_w
;
397 ppmm_v
= (float)pageHeight
/ mm_h
;
398 wxDisplaySize(&scr_w
, &scr_h
);
399 dc
->GetSize(&dc_w
, &dc_h
);
401 int ppiPrinterX
, ppiPrinterY
;
402 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
403 wxUnusedVar(ppiPrinterX
);
404 int ppiScreenX
, ppiScreenY
;
405 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
406 wxUnusedVar(ppiScreenX
);
408 dc
->SetUserScale((double)dc_w
/ (double)pageWidth
, (double)dc_w
/ (double)pageWidth
);
410 m_Renderer
->SetDC(dc
, (double)ppiPrinterY
/ (double)ppiScreenY
);
412 dc
->SetBackgroundMode(wxTRANSPARENT
);
414 m_Renderer
->Render((int) (ppmm_h
* m_MarginLeft
),
415 (int) (ppmm_v
* (m_MarginTop
+ (m_HeaderHeight
== 0 ? 0 : m_MarginSpace
)) + m_HeaderHeight
),
416 m_PageBreaks
[page
-1], FALSE
, m_PageBreaks
[page
]-m_PageBreaks
[page
-1]);
418 m_RendererHdr
->SetDC(dc
, (double)ppiPrinterY
/ (double)ppiScreenY
);
419 if (m_Headers
[page
% 2] != wxEmptyString
)
421 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Headers
[page
% 2], page
));
422 m_RendererHdr
->Render((int) (ppmm_h
* m_MarginLeft
), (int) (ppmm_v
* m_MarginTop
));
424 if (m_Footers
[page
% 2] != wxEmptyString
)
426 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Footers
[page
% 2], page
));
427 m_RendererHdr
->Render((int) (ppmm_h
* m_MarginLeft
), (int) (pageHeight
- ppmm_v
* m_MarginBottom
- m_FooterHeight
));
433 wxString
wxHtmlPrintout::TranslateHeader(const wxString
& instr
, int page
)
438 num
.Printf(wxT("%i"), page
);
439 r
.Replace(wxT("@PAGENUM@"), num
);
441 num
.Printf(wxT("%i"), m_NumPages
);
442 r
.Replace(wxT("@PAGESCNT@"), num
);
449 void wxHtmlPrintout::SetMargins(float top
, float bottom
, float left
, float right
, float spaces
)
452 m_MarginBottom
= bottom
;
454 m_MarginRight
= right
;
455 m_MarginSpace
= spaces
;
461 void wxHtmlPrintout::SetFonts(wxString normal_face
, wxString fixed_face
,
464 m_Renderer
->SetFonts(normal_face
, fixed_face
, sizes
);
465 m_RendererHdr
->SetFonts(normal_face
, fixed_face
, sizes
);
469 void wxHtmlPrintout::NormalizeFontSizes(int size
)
473 size
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
).GetPointSize();
475 f_sizes
[0] = int(size
* 0.6);
476 f_sizes
[1] = int(size
* 0.8);
478 f_sizes
[3] = int(size
* 1.2);
479 f_sizes
[4] = int(size
* 1.4);
480 f_sizes
[5] = int(size
* 1.6);
481 f_sizes
[6] = int(size
* 1.8);
483 SetFonts(wxEmptyString
, wxEmptyString
, f_sizes
);
488 //----------------------------------------------------------------------------
489 // wxHtmlEasyPrinting
490 //----------------------------------------------------------------------------
493 wxHtmlEasyPrinting::wxHtmlEasyPrinting(const wxString
& name
, wxWindow
*parentWindow
)
495 m_ParentWindow
= parentWindow
;
498 m_PageSetupData
= new wxPageSetupDialogData
;
499 m_Headers
[0] = m_Headers
[1] = m_Footers
[0] = m_Footers
[1] = wxEmptyString
;
501 m_PageSetupData
->EnableMargins(TRUE
);
502 m_PageSetupData
->SetMarginTopLeft(wxPoint(25, 25));
503 m_PageSetupData
->SetMarginBottomRight(wxPoint(25, 25));
505 SetFonts(wxEmptyString
, wxEmptyString
, NULL
);
510 wxHtmlEasyPrinting::~wxHtmlEasyPrinting()
513 delete m_PageSetupData
;
517 wxPrintData
*wxHtmlEasyPrinting::GetPrintData()
519 if (m_PrintData
== NULL
)
520 m_PrintData
= new wxPrintData();
525 bool wxHtmlEasyPrinting::PreviewFile(const wxString
&htmlfile
)
527 wxHtmlPrintout
*p1
= CreatePrintout();
528 p1
->SetHtmlFile(htmlfile
);
529 wxHtmlPrintout
*p2
= CreatePrintout();
530 p2
->SetHtmlFile(htmlfile
);
531 return DoPreview(p1
, p2
);
536 bool wxHtmlEasyPrinting::PreviewText(const wxString
&htmltext
, const wxString
&basepath
)
538 wxHtmlPrintout
*p1
= CreatePrintout();
539 p1
->SetHtmlText(htmltext
, basepath
, TRUE
);
540 wxHtmlPrintout
*p2
= CreatePrintout();
541 p2
->SetHtmlText(htmltext
, basepath
, TRUE
);
542 return DoPreview(p1
, p2
);
547 bool wxHtmlEasyPrinting::PrintFile(const wxString
&htmlfile
)
549 wxHtmlPrintout
*p
= CreatePrintout();
550 p
->SetHtmlFile(htmlfile
);
551 bool ret
= DoPrint(p
);
558 bool wxHtmlEasyPrinting::PrintText(const wxString
&htmltext
, const wxString
&basepath
)
560 wxHtmlPrintout
*p
= CreatePrintout();
561 p
->SetHtmlText(htmltext
, basepath
, TRUE
);
562 bool ret
= DoPrint(p
);
569 bool wxHtmlEasyPrinting::DoPreview(wxHtmlPrintout
*printout1
, wxHtmlPrintout
*printout2
)
571 // Pass two printout objects: for preview, and possible printing.
572 wxPrintDialogData
printDialogData(*GetPrintData());
573 wxPrintPreview
*preview
= new wxPrintPreview(printout1
, printout2
, &printDialogData
);
580 wxPreviewFrame
*frame
= new wxPreviewFrame(preview
, m_ParentWindow
,
581 m_Name
+ _(" Preview"),
582 wxPoint(100, 100), wxSize(650, 500));
583 frame
->Centre(wxBOTH
);
591 bool wxHtmlEasyPrinting::DoPrint(wxHtmlPrintout
*printout
)
593 wxPrintDialogData
printDialogData(*GetPrintData());
594 wxPrinter
printer(&printDialogData
);
596 if (!printer
.Print(m_ParentWindow
, printout
, TRUE
))
601 (*GetPrintData()) = printer
.GetPrintDialogData().GetPrintData();
607 void wxHtmlEasyPrinting::PrinterSetup()
609 wxPrintDialogData
printDialogData(*GetPrintData());
610 wxPrintDialog
printerDialog(m_ParentWindow
, &printDialogData
);
612 printerDialog
.GetPrintDialogData().SetSetupDialog(TRUE
);
614 if (printerDialog
.ShowModal() == wxID_OK
)
615 (*GetPrintData()) = printerDialog
.GetPrintDialogData().GetPrintData();
620 void wxHtmlEasyPrinting::PageSetup()
622 if (!GetPrintData()->Ok())
624 wxLogError(_("There was a problem during page setup: you may need to set a default printer."));
628 m_PageSetupData
->SetPrintData(*GetPrintData());
629 wxPageSetupDialog
pageSetupDialog(m_ParentWindow
, m_PageSetupData
);
631 if (pageSetupDialog
.ShowModal() == wxID_OK
)
633 (*GetPrintData()) = pageSetupDialog
.GetPageSetupData().GetPrintData();
634 (*m_PageSetupData
) = pageSetupDialog
.GetPageSetupData();
640 void wxHtmlEasyPrinting::SetHeader(const wxString
& header
, int pg
)
642 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_EVEN
)
643 m_Headers
[0] = header
;
644 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_ODD
)
645 m_Headers
[1] = header
;
650 void wxHtmlEasyPrinting::SetFooter(const wxString
& footer
, int pg
)
652 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_EVEN
)
653 m_Footers
[0] = footer
;
654 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_ODD
)
655 m_Footers
[1] = footer
;
659 void wxHtmlEasyPrinting::SetFonts(wxString normal_face
, wxString fixed_face
,
662 m_FontFaceNormal
= normal_face
;
663 m_FontFaceFixed
= fixed_face
;
667 m_FontsSizes
= m_FontsSizesArr
;
668 for (int i
= 0; i
< 7; i
++) m_FontsSizes
[i
] = sizes
[i
];
674 void wxHtmlEasyPrinting::NormalizeFontSizes(int size
)
678 size
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
).GetPointSize();
680 f_sizes
[0] = int(size
* 0.6);
681 f_sizes
[1] = int(size
* 0.8);
683 f_sizes
[3] = int(size
* 1.2);
684 f_sizes
[4] = int(size
* 1.4);
685 f_sizes
[5] = int(size
* 1.6);
686 f_sizes
[6] = int(size
* 1.8);
688 SetFonts(wxEmptyString
, wxEmptyString
, f_sizes
);
692 wxHtmlPrintout
*wxHtmlEasyPrinting::CreatePrintout()
694 wxHtmlPrintout
*p
= new wxHtmlPrintout(m_Name
);
696 p
->SetFonts(m_FontFaceNormal
, m_FontFaceFixed
, m_FontsSizes
);
698 p
->SetHeader(m_Headers
[0], wxPAGE_EVEN
);
699 p
->SetHeader(m_Headers
[1], wxPAGE_ODD
);
700 p
->SetFooter(m_Footers
[0], wxPAGE_EVEN
);
701 p
->SetFooter(m_Footers
[1], wxPAGE_ODD
);
703 p
->SetMargins(m_PageSetupData
->GetMarginTopLeft().y
,
704 m_PageSetupData
->GetMarginBottomRight().y
,
705 m_PageSetupData
->GetMarginTopLeft().x
,
706 m_PageSetupData
->GetMarginBottomRight().x
);
711 // A module to allow initialization/cleanup
712 // without calling these functions from app.cpp or from
713 // the user's application.
715 class wxHtmlPrintingModule
: public wxModule
717 DECLARE_DYNAMIC_CLASS(wxHtmlPrintingModule
)
719 wxHtmlPrintingModule() : wxModule() {}
720 bool OnInit() { return TRUE
; }
721 void OnExit() { wxHtmlPrintout::CleanUpStatics(); }
724 IMPLEMENT_DYNAMIC_CLASS(wxHtmlPrintingModule
, wxModule
)
727 // This hack forces the linker to always link in m_* files
728 // (wxHTML doesn't work without handlers from these files)
729 #include "wx/html/forcelnk.h"
730 FORCE_WXHTML_MODULES()
732 #endif // wxUSE_HTML & wxUSE_PRINTING_ARCHITECTURE