1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: html printing classes
4 // Author: Vaclav Slavik
7 // Copyright: (c) Vaclav Slavik, 1999
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
26 #if wxUSE_HTML && wxUSE_PRINTING_ARCHITECTURE && wxUSE_STREAMS
30 #include "wx/printdlg.h"
31 #include "wx/html/htmprint.h"
32 #include "wx/wxhtml.h"
33 #include "wx/wfstream.h"
34 #include "wx/module.h"
35 #include "wx/settings.h"
38 //--------------------------------------------------------------------------------
40 //--------------------------------------------------------------------------------
43 wxHtmlDCRenderer::wxHtmlDCRenderer() : wxObject()
46 m_Width
= m_Height
= 0;
48 m_Parser
= new wxHtmlWinParser();
49 m_FS
= new wxFileSystem();
50 m_Parser
->SetFS(m_FS
);
55 wxHtmlDCRenderer::~wxHtmlDCRenderer()
57 if (m_Cells
) delete m_Cells
;
58 if (m_Parser
) delete m_Parser
;
59 if (m_FS
) delete m_FS
;
64 void wxHtmlDCRenderer::SetDC(wxDC
*dc
, double pixel_scale
)
67 m_Parser
->SetDC(m_DC
, pixel_scale
);
72 void wxHtmlDCRenderer::SetSize(int width
, int height
)
79 void wxHtmlDCRenderer::SetHtmlText(const wxString
& html
, const wxString
& basepath
, bool isdir
)
81 if (m_DC
== NULL
) return;
83 if (m_Cells
!= NULL
) delete m_Cells
;
85 m_FS
->ChangePathTo(basepath
, isdir
);
86 m_Cells
= (wxHtmlContainerCell
*) m_Parser
->Parse(html
);
87 m_Cells
->SetIndent(0, wxHTML_INDENT_ALL
, wxHTML_UNITS_PIXELS
);
88 m_Cells
->Layout(m_Width
);
92 void wxHtmlDCRenderer::SetFonts(const wxString
& normal_face
, const wxString
& fixed_face
,
95 m_Parser
->SetFonts(normal_face
, fixed_face
, sizes
);
96 if (m_DC
== NULL
&& m_Cells
!= NULL
)
97 m_Cells
->Layout(m_Width
);
100 void wxHtmlDCRenderer::SetStandardFonts(int size
,
101 const wxString
& normal_face
,
102 const wxString
& fixed_face
)
104 m_Parser
->SetStandardFonts(size
, normal_face
, fixed_face
);
105 if (m_DC
== NULL
&& m_Cells
!= NULL
)
106 m_Cells
->Layout(m_Width
);
110 int wxHtmlDCRenderer::Render(int x
, int y
, int from
, int dont_render
,
112 int *known_pagebreaks
, int number_of_pages
)
116 if (m_Cells
== NULL
|| m_DC
== NULL
) return 0;
118 pbreak
= (int)(from
+ m_Height
);
119 while (m_Cells
->AdjustPagebreak(&pbreak
, known_pagebreaks
, number_of_pages
)) {}
120 hght
= pbreak
- from
;
121 if (maxHeight
< hght
)
126 wxHtmlRenderingInfo rinfo
;
127 wxDefaultHtmlRenderingStyle rstyle
;
128 rinfo
.SetStyle(&rstyle
);
129 m_DC
->SetBrush(*wxWHITE_BRUSH
);
130 m_DC
->SetClippingRegion(x
, y
, m_Width
, hght
);
133 y
, pbreak
+ (y
/*- from*/),
135 m_DC
->DestroyClippingRegion();
138 if (pbreak
< m_Cells
->GetHeight()) return pbreak
;
139 else return GetTotalHeight();
144 int wxHtmlDCRenderer::GetTotalHeight()
146 if (m_Cells
) return m_Cells
->GetHeight();
151 //--------------------------------------------------------------------------------
153 //--------------------------------------------------------------------------------
156 wxList
wxHtmlPrintout::m_Filters
;
158 wxHtmlPrintout::wxHtmlPrintout(const wxString
& title
) : wxPrintout(title
)
160 m_Renderer
= new wxHtmlDCRenderer
;
161 m_RendererHdr
= new wxHtmlDCRenderer
;
162 m_NumPages
= wxHTML_PRINT_MAX_PAGES
;
163 m_Document
= m_BasePath
= wxEmptyString
; m_BasePathIsDir
= true;
164 m_Headers
[0] = m_Headers
[1] = wxEmptyString
;
165 m_Footers
[0] = m_Footers
[1] = wxEmptyString
;
166 m_HeaderHeight
= m_FooterHeight
= 0;
167 SetMargins(); // to default values
172 wxHtmlPrintout::~wxHtmlPrintout()
175 delete m_RendererHdr
;
178 void wxHtmlPrintout::CleanUpStatics()
180 WX_CLEAR_LIST(wxList
, m_Filters
);
184 void wxHtmlPrintout::AddFilter(wxHtmlFilter
*filter
)
186 m_Filters
.Append(filter
);
189 void wxHtmlPrintout::OnPreparePrinting()
191 int pageWidth
, pageHeight
, mm_w
, mm_h
, scr_w
, scr_h
, dc_w
, dc_h
;
192 float ppmm_h
, ppmm_v
;
194 GetPageSizePixels(&pageWidth
, &pageHeight
);
195 GetPageSizeMM(&mm_w
, &mm_h
);
196 ppmm_h
= (float)pageWidth
/ mm_w
;
197 ppmm_v
= (float)pageHeight
/ mm_h
;
199 int ppiPrinterX
, ppiPrinterY
;
200 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
201 int ppiScreenX
, ppiScreenY
;
202 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
204 wxDisplaySize(&scr_w
, &scr_h
);
205 GetDC()->GetSize(&dc_w
, &dc_h
);
207 GetDC()->SetUserScale((double)dc_w
/ (double)pageWidth
, (double)dc_w
/ (double)pageWidth
);
209 /* prepare headers/footers renderer: */
211 m_RendererHdr
->SetDC(GetDC(), (double)ppiPrinterY
/ (double)ppiScreenY
);
212 m_RendererHdr
->SetSize((int) (ppmm_h
* (mm_w
- m_MarginLeft
- m_MarginRight
)),
213 (int) (ppmm_v
* (mm_h
- m_MarginTop
- m_MarginBottom
)));
214 if (m_Headers
[0] != wxEmptyString
)
216 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Headers
[0], 1));
217 m_HeaderHeight
= m_RendererHdr
->GetTotalHeight();
219 else if (m_Headers
[1] != wxEmptyString
)
221 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Headers
[1], 1));
222 m_HeaderHeight
= m_RendererHdr
->GetTotalHeight();
224 if (m_Footers
[0] != wxEmptyString
)
226 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Footers
[0], 1));
227 m_FooterHeight
= m_RendererHdr
->GetTotalHeight();
229 else if (m_Footers
[1] != wxEmptyString
)
231 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Footers
[1], 1));
232 m_FooterHeight
= m_RendererHdr
->GetTotalHeight();
235 /* prepare main renderer: */
236 m_Renderer
->SetDC(GetDC(), (double)ppiPrinterY
/ (double)ppiScreenY
);
237 m_Renderer
->SetSize((int) (ppmm_h
* (mm_w
- m_MarginLeft
- m_MarginRight
)),
238 (int) (ppmm_v
* (mm_h
- m_MarginTop
- m_MarginBottom
) -
239 m_FooterHeight
- m_HeaderHeight
-
240 ((m_HeaderHeight
== 0) ? 0 : m_MarginSpace
* ppmm_v
) -
241 ((m_FooterHeight
== 0) ? 0 : m_MarginSpace
* ppmm_v
)
243 m_Renderer
->SetHtmlText(m_Document
, m_BasePath
, m_BasePathIsDir
);
247 bool wxHtmlPrintout::OnBeginDocument(int startPage
, int endPage
)
249 if (!wxPrintout::OnBeginDocument(startPage
, endPage
)) return false;
255 bool wxHtmlPrintout::OnPrintPage(int page
)
261 RenderPage(dc
, page
);
268 void wxHtmlPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
)
271 *maxPage
= m_NumPages
;
273 *selPageTo
= m_NumPages
;
278 bool wxHtmlPrintout::HasPage(int pageNum
)
280 return (pageNum
>= 1 && pageNum
<= m_NumPages
);
285 void wxHtmlPrintout::SetHtmlText(const wxString
& html
, const wxString
&basepath
, bool isdir
)
288 m_BasePath
= basepath
;
289 m_BasePathIsDir
= isdir
;
292 void wxHtmlPrintout::SetHtmlFile(const wxString
& htmlfile
)
297 if (wxFileExists(htmlfile
))
298 ff
= fs
.OpenFile(wxFileSystem::FileNameToURL(htmlfile
));
300 ff
= fs
.OpenFile(htmlfile
);
304 wxLogError(htmlfile
+ _(": file does not exist!"));
309 wxHtmlFilterHTML defaultFilter
;
312 wxList::compatibility_iterator node
= m_Filters
.GetFirst();
315 wxHtmlFilter
*h
= (wxHtmlFilter
*) node
->GetData();
318 doc
= h
->ReadFile(*ff
);
322 node
= node
->GetNext();
326 doc
= defaultFilter
.ReadFile(*ff
);
328 SetHtmlText(doc
, htmlfile
, false);
334 void wxHtmlPrintout::SetHeader(const wxString
& header
, int pg
)
336 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_EVEN
)
337 m_Headers
[0] = header
;
338 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_ODD
)
339 m_Headers
[1] = header
;
344 void wxHtmlPrintout::SetFooter(const wxString
& footer
, int pg
)
346 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_EVEN
)
347 m_Footers
[0] = footer
;
348 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_ODD
)
349 m_Footers
[1] = footer
;
354 void wxHtmlPrintout::CountPages()
357 int pageWidth
, pageHeight
, mm_w
, mm_h
;
358 float ppmm_h
, ppmm_v
;
360 GetPageSizePixels(&pageWidth
, &pageHeight
);
361 GetPageSizeMM(&mm_w
, &mm_h
);
362 ppmm_h
= (float)pageWidth
/ mm_w
;
363 ppmm_v
= (float)pageHeight
/ mm_h
;
372 pos
= m_Renderer
->Render((int)( ppmm_h
* m_MarginLeft
),
373 (int) (ppmm_v
* (m_MarginTop
+ (m_HeaderHeight
== 0 ? 0 : m_MarginSpace
)) + m_HeaderHeight
),
374 pos
, true, INT_MAX
, m_PageBreaks
, m_NumPages
);
375 m_PageBreaks
[++m_NumPages
] = pos
;
376 } while (pos
< m_Renderer
->GetTotalHeight());
381 void wxHtmlPrintout::RenderPage(wxDC
*dc
, int page
)
385 int pageWidth
, pageHeight
, mm_w
, mm_h
, scr_w
, scr_h
, dc_w
, dc_h
;
386 float ppmm_h
, ppmm_v
;
388 GetPageSizePixels(&pageWidth
, &pageHeight
);
389 GetPageSizeMM(&mm_w
, &mm_h
);
390 ppmm_h
= (float)pageWidth
/ mm_w
;
391 ppmm_v
= (float)pageHeight
/ mm_h
;
392 wxDisplaySize(&scr_w
, &scr_h
);
393 dc
->GetSize(&dc_w
, &dc_h
);
395 int ppiPrinterX
, ppiPrinterY
;
396 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
397 wxUnusedVar(ppiPrinterX
);
398 int ppiScreenX
, ppiScreenY
;
399 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
400 wxUnusedVar(ppiScreenX
);
402 dc
->SetUserScale((double)dc_w
/ (double)pageWidth
, (double)dc_w
/ (double)pageWidth
);
404 m_Renderer
->SetDC(dc
, (double)ppiPrinterY
/ (double)ppiScreenY
);
406 dc
->SetBackgroundMode(wxTRANSPARENT
);
408 m_Renderer
->Render((int) (ppmm_h
* m_MarginLeft
),
409 (int) (ppmm_v
* (m_MarginTop
+ (m_HeaderHeight
== 0 ? 0 : m_MarginSpace
)) + m_HeaderHeight
),
410 m_PageBreaks
[page
-1], false, m_PageBreaks
[page
]-m_PageBreaks
[page
-1]);
412 m_RendererHdr
->SetDC(dc
, (double)ppiPrinterY
/ (double)ppiScreenY
);
413 if (m_Headers
[page
% 2] != wxEmptyString
)
415 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Headers
[page
% 2], page
));
416 m_RendererHdr
->Render((int) (ppmm_h
* m_MarginLeft
), (int) (ppmm_v
* m_MarginTop
));
418 if (m_Footers
[page
% 2] != wxEmptyString
)
420 m_RendererHdr
->SetHtmlText(TranslateHeader(m_Footers
[page
% 2], page
));
421 m_RendererHdr
->Render((int) (ppmm_h
* m_MarginLeft
), (int) (pageHeight
- ppmm_v
* m_MarginBottom
- m_FooterHeight
));
427 wxString
wxHtmlPrintout::TranslateHeader(const wxString
& instr
, int page
)
432 num
.Printf(wxT("%i"), page
);
433 r
.Replace(wxT("@PAGENUM@"), num
);
435 num
.Printf(wxT("%i"), m_NumPages
);
436 r
.Replace(wxT("@PAGESCNT@"), num
);
443 void wxHtmlPrintout::SetMargins(float top
, float bottom
, float left
, float right
, float spaces
)
446 m_MarginBottom
= bottom
;
448 m_MarginRight
= right
;
449 m_MarginSpace
= spaces
;
455 void wxHtmlPrintout::SetFonts(const wxString
& normal_face
, const wxString
& fixed_face
,
458 m_Renderer
->SetFonts(normal_face
, fixed_face
, sizes
);
459 m_RendererHdr
->SetFonts(normal_face
, fixed_face
, sizes
);
462 void wxHtmlPrintout::SetStandardFonts(int size
,
463 const wxString
& normal_face
,
464 const wxString
& fixed_face
)
466 m_Renderer
->SetStandardFonts(size
, normal_face
, fixed_face
);
467 m_RendererHdr
->SetStandardFonts(size
, normal_face
, fixed_face
);
472 //----------------------------------------------------------------------------
473 // wxHtmlEasyPrinting
474 //----------------------------------------------------------------------------
477 wxHtmlEasyPrinting::wxHtmlEasyPrinting(const wxString
& name
, wxWindow
*parentWindow
)
479 m_ParentWindow
= parentWindow
;
482 m_PageSetupData
= new wxPageSetupDialogData
;
483 m_Headers
[0] = m_Headers
[1] = m_Footers
[0] = m_Footers
[1] = wxEmptyString
;
485 m_PageSetupData
->EnableMargins(true);
486 m_PageSetupData
->SetMarginTopLeft(wxPoint(25, 25));
487 m_PageSetupData
->SetMarginBottomRight(wxPoint(25, 25));
489 SetFonts(wxEmptyString
, wxEmptyString
, NULL
);
494 wxHtmlEasyPrinting::~wxHtmlEasyPrinting()
497 delete m_PageSetupData
;
501 wxPrintData
*wxHtmlEasyPrinting::GetPrintData()
503 if (m_PrintData
== NULL
)
504 m_PrintData
= new wxPrintData();
509 bool wxHtmlEasyPrinting::PreviewFile(const wxString
&htmlfile
)
511 wxHtmlPrintout
*p1
= CreatePrintout();
512 p1
->SetHtmlFile(htmlfile
);
513 wxHtmlPrintout
*p2
= CreatePrintout();
514 p2
->SetHtmlFile(htmlfile
);
515 return DoPreview(p1
, p2
);
520 bool wxHtmlEasyPrinting::PreviewText(const wxString
&htmltext
, const wxString
&basepath
)
522 wxHtmlPrintout
*p1
= CreatePrintout();
523 p1
->SetHtmlText(htmltext
, basepath
, true);
524 wxHtmlPrintout
*p2
= CreatePrintout();
525 p2
->SetHtmlText(htmltext
, basepath
, true);
526 return DoPreview(p1
, p2
);
531 bool wxHtmlEasyPrinting::PrintFile(const wxString
&htmlfile
)
533 wxHtmlPrintout
*p
= CreatePrintout();
534 p
->SetHtmlFile(htmlfile
);
535 bool ret
= DoPrint(p
);
542 bool wxHtmlEasyPrinting::PrintText(const wxString
&htmltext
, const wxString
&basepath
)
544 wxHtmlPrintout
*p
= CreatePrintout();
545 p
->SetHtmlText(htmltext
, basepath
, true);
546 bool ret
= DoPrint(p
);
553 bool wxHtmlEasyPrinting::DoPreview(wxHtmlPrintout
*printout1
, wxHtmlPrintout
*printout2
)
555 // Pass two printout objects: for preview, and possible printing.
556 wxPrintDialogData
printDialogData(*GetPrintData());
557 wxPrintPreview
*preview
= new wxPrintPreview(printout1
, printout2
, &printDialogData
);
564 wxPreviewFrame
*frame
= new wxPreviewFrame(preview
, m_ParentWindow
,
565 m_Name
+ _(" Preview"),
566 wxPoint(100, 100), wxSize(650, 500));
567 frame
->Centre(wxBOTH
);
575 bool wxHtmlEasyPrinting::DoPrint(wxHtmlPrintout
*printout
)
577 wxPrintDialogData
printDialogData(*GetPrintData());
578 wxPrinter
printer(&printDialogData
);
580 if (!printer
.Print(m_ParentWindow
, printout
, true))
585 (*GetPrintData()) = printer
.GetPrintDialogData().GetPrintData();
592 void wxHtmlEasyPrinting::PageSetup()
594 if (!GetPrintData()->Ok())
596 wxLogError(_("There was a problem during page setup: you may need to set a default printer."));
600 m_PageSetupData
->SetPrintData(*GetPrintData());
601 wxPageSetupDialog
pageSetupDialog(m_ParentWindow
, m_PageSetupData
);
603 if (pageSetupDialog
.ShowModal() == wxID_OK
)
605 (*GetPrintData()) = pageSetupDialog
.GetPageSetupData().GetPrintData();
606 (*m_PageSetupData
) = pageSetupDialog
.GetPageSetupData();
612 void wxHtmlEasyPrinting::SetHeader(const wxString
& header
, int pg
)
614 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_EVEN
)
615 m_Headers
[0] = header
;
616 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_ODD
)
617 m_Headers
[1] = header
;
622 void wxHtmlEasyPrinting::SetFooter(const wxString
& footer
, int pg
)
624 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_EVEN
)
625 m_Footers
[0] = footer
;
626 if (pg
== wxPAGE_ALL
|| pg
== wxPAGE_ODD
)
627 m_Footers
[1] = footer
;
631 void wxHtmlEasyPrinting::SetFonts(const wxString
& normal_face
, const wxString
& fixed_face
,
634 m_fontMode
= FontMode_Explicit
;
635 m_FontFaceNormal
= normal_face
;
636 m_FontFaceFixed
= fixed_face
;
640 m_FontsSizes
= m_FontsSizesArr
;
641 for (int i
= 0; i
< 7; i
++) m_FontsSizes
[i
] = sizes
[i
];
647 void wxHtmlEasyPrinting::SetStandardFonts(int size
,
648 const wxString
& normal_face
,
649 const wxString
& fixed_face
)
651 m_fontMode
= FontMode_Standard
;
652 m_FontFaceNormal
= normal_face
;
653 m_FontFaceFixed
= fixed_face
;
654 m_FontsSizesArr
[0] = size
;
658 wxHtmlPrintout
*wxHtmlEasyPrinting::CreatePrintout()
660 wxHtmlPrintout
*p
= new wxHtmlPrintout(m_Name
);
662 if (m_fontMode
== FontMode_Explicit
)
664 p
->SetFonts(m_FontFaceNormal
, m_FontFaceFixed
, m_FontsSizes
);
666 else // FontMode_Standard
668 p
->SetStandardFonts(m_FontsSizesArr
[0],
669 m_FontFaceNormal
, m_FontFaceFixed
);
672 p
->SetHeader(m_Headers
[0], wxPAGE_EVEN
);
673 p
->SetHeader(m_Headers
[1], wxPAGE_ODD
);
674 p
->SetFooter(m_Footers
[0], wxPAGE_EVEN
);
675 p
->SetFooter(m_Footers
[1], wxPAGE_ODD
);
677 p
->SetMargins(m_PageSetupData
->GetMarginTopLeft().y
,
678 m_PageSetupData
->GetMarginBottomRight().y
,
679 m_PageSetupData
->GetMarginTopLeft().x
,
680 m_PageSetupData
->GetMarginBottomRight().x
);
685 // A module to allow initialization/cleanup
686 // without calling these functions from app.cpp or from
687 // the user's application.
689 class wxHtmlPrintingModule
: public wxModule
691 DECLARE_DYNAMIC_CLASS(wxHtmlPrintingModule
)
693 wxHtmlPrintingModule() : wxModule() {}
694 bool OnInit() { return true; }
695 void OnExit() { wxHtmlPrintout::CleanUpStatics(); }
698 IMPLEMENT_DYNAMIC_CLASS(wxHtmlPrintingModule
, wxModule
)
701 // This hack forces the linker to always link in m_* files
702 // (wxHTML doesn't work without handlers from these files)
703 #include "wx/html/forcelnk.h"
704 FORCE_WXHTML_MODULES()
706 #endif // wxUSE_HTML & wxUSE_PRINTING_ARCHITECTURE