From f1ea4afdbe1b5d02ef3dd0a7e9dc8806a4225e10 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 21 May 2018 16:39:02 +0200 Subject: [PATCH 01/21] Make wxHtmlPrintout::m_Renderer{,Hdr} objects instead of pointers There is no need to allocate these objects on the heap and delete them later when we can just make them members of wxHtmlPrintout object itself. No real changes. --- include/wx/html/htmprint.h | 3 +- src/html/htmprint.cpp | 64 +++++++++++++++++--------------------- 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/include/wx/html/htmprint.h b/include/wx/html/htmprint.h index 6098b9bd94..71ef634f88 100644 --- a/include/wx/html/htmprint.h +++ b/include/wx/html/htmprint.h @@ -121,7 +121,6 @@ class WXDLLIMPEXP_HTML wxHtmlPrintout : public wxPrintout { public: wxHtmlPrintout(const wxString& title = wxT("Printout")); - virtual ~wxHtmlPrintout(); void SetHtmlText(const wxString& html, const wxString &basepath = wxEmptyString, bool isdir = true); // prepares the class for printing this html document. @@ -207,7 +206,7 @@ private: wxString m_Headers[2], m_Footers[2]; int m_HeaderHeight, m_FooterHeight; - wxHtmlDCRenderer *m_Renderer, *m_RendererHdr; + wxHtmlDCRenderer m_Renderer, m_RendererHdr; float m_MarginTop, m_MarginBottom, m_MarginLeft, m_MarginRight, m_MarginSpace; // list of HTML filters diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index 5709a798e1..9f5c8d39d1 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -193,8 +193,6 @@ wxList wxHtmlPrintout::m_Filters; wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title) { - m_Renderer = new wxHtmlDCRenderer; - m_RendererHdr = new wxHtmlDCRenderer; m_NumPages = INT_MAX; m_Document = m_BasePath = wxEmptyString; m_BasePathIsDir = true; m_Headers[0] = m_Headers[1] = wxEmptyString; @@ -206,12 +204,6 @@ wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title) -wxHtmlPrintout::~wxHtmlPrintout() -{ - delete m_Renderer; - delete m_RendererHdr; -} - void wxHtmlPrintout::CleanUpStatics() { WX_CLEAR_LIST(wxList, m_Filters); @@ -315,34 +307,34 @@ void wxHtmlPrintout::OnPreparePrinting() /* prepare headers/footers renderer: */ - m_RendererHdr->SetDC(GetDC(), + m_RendererHdr.SetDC(GetDC(), (double)ppiPrinterY / TYPICAL_SCREEN_DPI, (double)ppiPrinterY / (double)ppiScreenY); - m_RendererHdr->SetSize((int) (ppmm_h * (mm_w - m_MarginLeft - m_MarginRight)), + m_RendererHdr.SetSize((int) (ppmm_h * (mm_w - m_MarginLeft - m_MarginRight)), (int) (ppmm_v * (mm_h - m_MarginTop - m_MarginBottom))); if (!m_Headers[0].empty()) { - m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[0], 1)); - m_HeaderHeight = m_RendererHdr->GetTotalHeight(); + m_RendererHdr.SetHtmlText(TranslateHeader(m_Headers[0], 1)); + m_HeaderHeight = m_RendererHdr.GetTotalHeight(); } else if (!m_Headers[1].empty()) { - m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[1], 1)); - m_HeaderHeight = m_RendererHdr->GetTotalHeight(); + m_RendererHdr.SetHtmlText(TranslateHeader(m_Headers[1], 1)); + m_HeaderHeight = m_RendererHdr.GetTotalHeight(); } if (!m_Footers[0].empty()) { - m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[0], 1)); - m_FooterHeight = m_RendererHdr->GetTotalHeight(); + m_RendererHdr.SetHtmlText(TranslateHeader(m_Footers[0], 1)); + m_FooterHeight = m_RendererHdr.GetTotalHeight(); } else if (!m_Footers[1].empty()) { - m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[1], 1)); - m_FooterHeight = m_RendererHdr->GetTotalHeight(); + m_RendererHdr.SetHtmlText(TranslateHeader(m_Footers[1], 1)); + m_FooterHeight = m_RendererHdr.GetTotalHeight(); } /* prepare main renderer: */ - m_Renderer->SetDC(GetDC(), + m_Renderer.SetDC(GetDC(), (double)ppiPrinterY / TYPICAL_SCREEN_DPI, (double)ppiPrinterY / (double)ppiScreenY); @@ -353,12 +345,12 @@ void wxHtmlPrintout::OnPreparePrinting() if ( m_FooterHeight ) printAreaH -= int(m_FooterHeight + m_MarginSpace * ppmm_v); - m_Renderer->SetSize(printAreaW, printAreaH); - m_Renderer->SetHtmlText(m_Document, m_BasePath, m_BasePathIsDir); + m_Renderer.SetSize(printAreaW, printAreaH); + m_Renderer.SetHtmlText(m_Document, m_BasePath, m_BasePathIsDir); if ( CheckFit(wxSize(printAreaW, printAreaH), - wxSize(m_Renderer->GetTotalWidth(), - m_Renderer->GetTotalHeight())) || IsPreview() ) + wxSize(m_Renderer.GetTotalWidth(), + m_Renderer.GetTotalHeight())) || IsPreview() ) { // do paginate the document CountPages(); @@ -496,12 +488,12 @@ void wxHtmlPrintout::CountPages() m_PageBreaks.Add( 0); do { - pos = m_Renderer->Render((int)( ppmm_h * m_MarginLeft), + pos = m_Renderer.Render((int)( ppmm_h * m_MarginLeft), (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), m_PageBreaks, pos, true, INT_MAX); m_PageBreaks.Add( pos); - } while (pos < m_Renderer->GetTotalHeight()); + } while (pos < m_Renderer.GetTotalHeight()); } @@ -529,29 +521,29 @@ void wxHtmlPrintout::RenderPage(wxDC *dc, int page) dc->SetUserScale((double)dc_w / (double)pageWidth, (double)dc_h / (double)pageHeight); - m_Renderer->SetDC(dc, + m_Renderer.SetDC(dc, (double)ppiPrinterY / TYPICAL_SCREEN_DPI, (double)ppiPrinterY / (double)ppiScreenY); dc->SetBackgroundMode(wxTRANSPARENT); - m_Renderer->Render((int) (ppmm_h * m_MarginLeft), + m_Renderer.Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), m_PageBreaks, m_PageBreaks[page-1], false, m_PageBreaks[page]-m_PageBreaks[page-1]); - m_RendererHdr->SetDC(dc, + m_RendererHdr.SetDC(dc, (double)ppiPrinterY / TYPICAL_SCREEN_DPI, (double)ppiPrinterY / (double)ppiScreenY); if (!m_Headers[page % 2].empty()) { - m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[page % 2], page)); - m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop), m_PageBreaks); + m_RendererHdr.SetHtmlText(TranslateHeader(m_Headers[page % 2], page)); + m_RendererHdr.Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop), m_PageBreaks); } if (!m_Footers[page % 2].empty()) { - m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[page % 2], page)); - m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight), m_PageBreaks); + m_RendererHdr.SetHtmlText(TranslateHeader(m_Footers[page % 2], page)); + m_RendererHdr.Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight), m_PageBreaks); } } @@ -604,16 +596,16 @@ void wxHtmlPrintout::SetMargins(const wxPageSetupDialogData& pageSetupData) void wxHtmlPrintout::SetFonts(const wxString& normal_face, const wxString& fixed_face, const int *sizes) { - m_Renderer->SetFonts(normal_face, fixed_face, sizes); - m_RendererHdr->SetFonts(normal_face, fixed_face, sizes); + m_Renderer.SetFonts(normal_face, fixed_face, sizes); + m_RendererHdr.SetFonts(normal_face, fixed_face, sizes); } void wxHtmlPrintout::SetStandardFonts(int size, const wxString& normal_face, const wxString& fixed_face) { - m_Renderer->SetStandardFonts(size, normal_face, fixed_face); - m_RendererHdr->SetStandardFonts(size, normal_face, fixed_face); + m_Renderer.SetStandardFonts(size, normal_face, fixed_face); + m_RendererHdr.SetStandardFonts(size, normal_face, fixed_face); } From 9544d102ddee1369f6e56558db7c892000581861 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 21 May 2018 16:43:49 +0200 Subject: [PATCH 02/21] Remove unnecessary wxHtmlPrintout members initialization Don't initialize strings to their default (empty) value, this is just useless. --- src/html/htmprint.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index 9f5c8d39d1..1403019851 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -194,9 +194,7 @@ wxList wxHtmlPrintout::m_Filters; wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title) { m_NumPages = INT_MAX; - m_Document = m_BasePath = wxEmptyString; m_BasePathIsDir = true; - m_Headers[0] = m_Headers[1] = wxEmptyString; - m_Footers[0] = m_Footers[1] = wxEmptyString; + m_BasePathIsDir = true; m_HeaderHeight = m_FooterHeight = 0; SetMargins(); // to default values SetStandardFonts(DEFAULT_PRINT_FONT_SIZE); From a56b993c55b239b0183305c2a61e84a476ab9d15 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 21 May 2018 17:14:29 +0200 Subject: [PATCH 03/21] Use "for" loop in wxHtmlContainerCell::AdjustPagebreak() Use a simpler form for iterating over all children. No real changes. --- src/html/htmlcell.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/html/htmlcell.cpp b/src/html/htmlcell.cpp index bf16620db8..0f14760198 100644 --- a/src/html/htmlcell.cpp +++ b/src/html/htmlcell.cpp @@ -704,15 +704,13 @@ wxHtmlContainerCell::AdjustPagebreak(int *pagebreak, if (!m_CanLiveOnPagebreak) return wxHtmlCell::AdjustPagebreak(pagebreak, known_pagebreaks, pageHeight); - wxHtmlCell *c = GetFirstChild(); bool rt = false; int pbrk = *pagebreak - m_PosY; - while (c) + for ( wxHtmlCell *c = GetFirstChild(); c; c = c->GetNext() ) { if (c->AdjustPagebreak(&pbrk, known_pagebreaks, pageHeight)) rt = true; - c = c->GetNext(); } if (rt) *pagebreak = pbrk + m_PosY; From 9fa9880f979ee9abefcf18e4685e1ef56ff7592b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 21 May 2018 19:06:21 +0200 Subject: [PATCH 04/21] Pass known page breaks as const ref to wxHtmlDCRenderer::Render() This method doesn't modify the known page breaks, it only uses them to find the next one, so make it more clear by using const reference in the function signature. --- include/wx/html/htmprint.h | 2 +- src/html/htmprint.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/wx/html/htmprint.h b/include/wx/html/htmprint.h index 71ef634f88..5e4584aec1 100644 --- a/include/wx/html/htmprint.h +++ b/include/wx/html/htmprint.h @@ -78,7 +78,7 @@ public: // set the same pagebreak twice. // // CAUTION! Render() changes DC's user scale and does NOT restore it! - int Render(int x, int y, wxArrayInt& known_pagebreaks, int from = 0, + int Render(int x, int y, const wxArrayInt& known_pagebreaks, int from = 0, int dont_render = false, int to = INT_MAX); // returns total width of the html document diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index 1403019851..c2195cc266 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -141,7 +141,7 @@ void wxHtmlDCRenderer::SetStandardFonts(int size, } int wxHtmlDCRenderer::Render(int x, int y, - wxArrayInt& known_pagebreaks, + const wxArrayInt& known_pagebreaks, int from, int dont_render, int to) { wxCHECK_MSG( m_Cells, 0, "SetHtmlText() must be called before Render()" ); From b6f0693a4103060f121b229d567127ca88dac752 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 23 May 2018 17:22:54 +0200 Subject: [PATCH 05/21] Use wxDCClipper in wxHtmlDCRenderer code Use wxDCClipper instead of manually calling DestroyClippingRegion(). This is simpler and safer and also potentially more correct as wxDCClipper restores the previous clipping region, if any, unlike the old code -- even though this probably doesn't matter here as the printing DC seems unlikely to be clipped. --- src/html/htmprint.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index c2195cc266..84f77b7df4 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -161,12 +161,11 @@ int wxHtmlDCRenderer::Render(int x, int y, wxDefaultHtmlRenderingStyle rstyle; rinfo.SetStyle(&rstyle); m_DC->SetBrush(*wxWHITE_BRUSH); - m_DC->SetClippingRegion(x, y, m_Width, hght); + wxDCClipper clip(*m_DC, x, y, m_Width, hght); m_Cells->Draw(*m_DC, x, (y - from), y, y + hght, rinfo); - m_DC->DestroyClippingRegion(); } if (pbreak < m_Cells->GetHeight()) return pbreak; From 048b7f44ec44a428f9b115121be299ea329276b2 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 23 May 2018 17:52:31 +0200 Subject: [PATCH 06/21] Add wxPrintout::SetUp() to reuse the same code in all ports MSW, GTK, OSX and Postscript implementations all did almost exactly the same thing to initialize wxPrintout, so extract this common code into a new wxPrintout method and just call it instead. There should be no changes in behaviour. --- include/wx/prntbase.h | 4 ++++ src/common/prntbase.cpp | 27 +++++++++++++++++++++++++++ src/generic/printps.cpp | 18 +----------------- src/gtk/print.cpp | 13 +------------ src/msw/printwin.cpp | 28 +++------------------------- src/osx/core/printmac.cpp | 12 +----------- 6 files changed, 37 insertions(+), 65 deletions(-) diff --git a/include/wx/prntbase.h b/include/wx/prntbase.h index 18987fffb3..1056e27d0e 100644 --- a/include/wx/prntbase.h +++ b/include/wx/prntbase.h @@ -281,6 +281,10 @@ public: virtual wxString GetTitle() const { return m_printoutTitle; } + // Port-specific code should call this function to initialize this object + // with everything it needs, instead of using individual accessors below. + bool SetUp(wxDC& dc); + wxDC *GetDC() const { return m_printoutDC; } void SetDC(wxDC *dc) { m_printoutDC = dc; } diff --git a/src/common/prntbase.cpp b/src/common/prntbase.cpp index eb2d92ecdb..cfecbd6158 100644 --- a/src/common/prntbase.cpp +++ b/src/common/prntbase.cpp @@ -638,6 +638,33 @@ void wxPrintout::GetPageInfo(int *minPage, int *maxPage, int *fromPage, int *toP *toPage = 1; } +bool wxPrintout::SetUp(wxDC& dc) +{ + SetPPIScreen(wxGetDisplayPPI()); + + // We need to know printer PPI. In most ports, this can be retrieved from + // the printer DC, but in others it is computed (probably for legacy + // reasons) outside of wxDC code, so don't override it if it had been + // already set. + if ( !m_PPIPrinterX || !m_PPIPrinterY ) + { + SetPPIPrinter(dc.GetPPI()); + if ( !m_PPIPrinterX || !m_PPIPrinterY ) + { + // But if we couldn't get it in any way, we can't continue. + return false; + } + } + + SetDC(&dc); + + dc.GetSize(&m_pageWidthPixels, &m_pageHeightPixels); + m_paperRectPixels = wxRect(0, 0, m_pageWidthPixels, m_pageHeightPixels); + dc.GetSizeMM(&m_pageWidthMM, &m_pageHeightMM); + + return true; +} + void wxPrintout::FitThisSizeToPaper(const wxSize& imageSize) { // Set the DC scale and origin so that the given image size fits within the diff --git a/src/generic/printps.cpp b/src/generic/printps.cpp index cedf7278f7..efcdb879b6 100644 --- a/src/generic/printps.cpp +++ b/src/generic/printps.cpp @@ -105,24 +105,8 @@ bool wxPostScriptPrinter::Print(wxWindow *parent, wxPrintout *printout, bool pro return false; } - wxSize ScreenPixels = wxGetDisplaySize(); - wxSize ScreenMM = wxGetDisplaySizeMM(); - - printout->SetPPIScreen( (int) ((ScreenPixels.GetWidth() * 25.4) / ScreenMM.GetWidth()), - (int) ((ScreenPixels.GetHeight() * 25.4) / ScreenMM.GetHeight()) ); - printout->SetPPIPrinter( dc->GetResolution(), - dc->GetResolution() ); - // Set printout parameters - printout->SetDC(dc); - - int w, h; - dc->GetSize(&w, &h); - printout->SetPageSizePixels((int)w, (int)h); - printout->SetPaperRectPixels(wxRect(0, 0, w, h)); - int mw, mh; - dc->GetSizeMM(&mw, &mh); - printout->SetPageSizeMM((int)mw, (int)mh); + printout->SetUp(*dc); // Create an abort window wxBeginBusyCursor(); diff --git a/src/gtk/print.cpp b/src/gtk/print.cpp index 62578a44e5..9089e57f52 100644 --- a/src/gtk/print.cpp +++ b/src/gtk/print.cpp @@ -1024,19 +1024,8 @@ void wxGtkPrinter::BeginPrint(wxPrintout *printout, GtkPrintOperation *operation return; } - printout->SetPPIScreen(wxGetDisplayPPI()); - printout->SetPPIPrinter( printDC->GetResolution(), - printDC->GetResolution() ); + printout->SetUp(*m_dc); - printout->SetDC(m_dc); - - int w, h; - m_dc->GetSize(&w, &h); - printout->SetPageSizePixels((int)w, (int)h); - printout->SetPaperRectPixels(wxRect(0, 0, w, h)); - int mw, mh; - m_dc->GetSizeMM(&mw, &mh); - printout->SetPageSizeMM((int)mw, (int)mh); printout->OnPreparePrinting(); // Get some parameters from the printout, if defined. diff --git a/src/msw/printwin.cpp b/src/msw/printwin.cpp index 6d1e9c40c7..48e61003c1 100644 --- a/src/msw/printwin.cpp +++ b/src/msw/printwin.cpp @@ -115,36 +115,14 @@ bool wxWindowsPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt return false; } - wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl(); - - HDC hdc = ::GetDC(NULL); - int logPPIScreenX = ::GetDeviceCaps(hdc, LOGPIXELSX); - int logPPIScreenY = ::GetDeviceCaps(hdc, LOGPIXELSY); - ::ReleaseDC(NULL, hdc); - - int logPPIPrinterX = ::GetDeviceCaps((HDC) impl->GetHDC(), LOGPIXELSX); - int logPPIPrinterY = ::GetDeviceCaps((HDC) impl->GetHDC(), LOGPIXELSY); - if (logPPIPrinterX == 0 || logPPIPrinterY == 0) + // Set printout parameters + if (!printout->SetUp(*dc)) { delete dc; sm_lastError = wxPRINTER_ERROR; return false; } - printout->SetPPIScreen(logPPIScreenX, logPPIScreenY); - printout->SetPPIPrinter(logPPIPrinterX, logPPIPrinterY); - - // Set printout parameters - printout->SetDC(dc); - - int w, h; - dc->GetSize(&w, &h); - printout->SetPageSizePixels((int)w, (int)h); - printout->SetPaperRectPixels(dc->GetPaperRect()); - - dc->GetSizeMM(&w, &h); - printout->SetPageSizeMM((int)w, (int)h); - // Create an abort window wxBusyCursor busyCursor; @@ -169,7 +147,7 @@ bool wxWindowsPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt wxPrintAbortDialog *win = CreateAbortWindow(parent, printout); wxYield(); - ::SetAbortProc(GetHdcOf(*impl), wxAbortProc); + ::SetAbortProc(GetHdcOf(*dc), wxAbortProc); if (!win) { diff --git a/src/osx/core/printmac.cpp b/src/osx/core/printmac.cpp index 9bc7f7fccf..c14c376226 100644 --- a/src/osx/core/printmac.cpp +++ b/src/osx/core/printmac.cpp @@ -585,8 +585,6 @@ bool wxMacPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt) return false; } - printout->SetPPIScreen(wxGetDisplayPPI()); - PMResolution res; PMPrinter printer; wxOSXPrintData* nativeData = (wxOSXPrintData*) @@ -607,15 +605,7 @@ bool wxMacPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt) printout->SetPPIPrinter(int(res.hRes), int(res.vRes)); // Set printout parameters - printout->SetDC(dc); - - int w, h; - dc->GetSize(&w, &h); - printout->SetPageSizePixels((int)w, (int)h); - printout->SetPaperRectPixels(dc->GetPaperRect()); - wxCoord mw, mh; - dc->GetSizeMM(&mw, &mh); - printout->SetPageSizeMM((int)mw, (int)mh); + printout->SetUp(*dc); // Create an abort window wxBeginBusyCursor(); From dd92a269c3cdee5f35c078b7821eb92f688978b1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 23 May 2018 18:12:26 +0200 Subject: [PATCH 07/21] Add a simple unit test for wxHtmlPrintout pagination logic Verify that the number of pages to be printed is as expected. --- tests/Makefile.in | 4 ++ tests/html/htmprint.cpp | 82 ++++++++++++++++++++++++++++++++++ tests/makefile.bcc | 4 ++ tests/makefile.gcc | 4 ++ tests/makefile.vc | 4 ++ tests/test.bkl | 1 + tests/test_gui.vcxproj | 3 +- tests/test_gui.vcxproj.filters | 5 ++- tests/test_vc7_test_gui.vcproj | 3 ++ tests/test_vc8_test_gui.vcproj | 4 ++ tests/test_vc9_test_gui.vcproj | 4 ++ 11 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 tests/html/htmprint.cpp diff --git a/tests/Makefile.in b/tests/Makefile.in index d20559e8fe..bc37e442f9 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -243,6 +243,7 @@ TEST_GUI_OBJECTS = \ test_gui_rawbmp.o \ test_gui_htmlparser.o \ test_gui_htmlwindow.o \ + test_gui_htmprint.o \ test_gui_accelentry.o \ test_gui_menu.o \ test_gui_guifuncs.o \ @@ -997,6 +998,9 @@ test_gui_htmlparser.o: $(srcdir)/html/htmlparser.cpp $(TEST_GUI_ODEP) test_gui_htmlwindow.o: $(srcdir)/html/htmlwindow.cpp $(TEST_GUI_ODEP) $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/html/htmlwindow.cpp +test_gui_htmprint.o: $(srcdir)/html/htmprint.cpp $(TEST_GUI_ODEP) + $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/html/htmprint.cpp + test_gui_accelentry.o: $(srcdir)/menu/accelentry.cpp $(TEST_GUI_ODEP) $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/menu/accelentry.cpp diff --git a/tests/html/htmprint.cpp b/tests/html/htmprint.cpp new file mode 100644 index 0000000000..0466182845 --- /dev/null +++ b/tests/html/htmprint.cpp @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: tests/html/htmprint.cpp +// Purpose: wxHtmlPrintout tests +// Author: Vadim Zeitlin +// Created: 2018-05-22 +// Copyright: (c) 2018 Vadim Zeitlin +/////////////////////////////////////////////////////////////////////////////// + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#include "testprec.h" + +#if wxUSE_HTML + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/dcmemory.h" +#endif // WX_PRECOMP + +#include "wx/html/htmprint.h" + +namespace +{ + +// Return the number of pages in the printout. +int CountPages(wxHtmlPrintout& pr) +{ + REQUIRE_NOTHROW( pr.OnPreparePrinting() ); + + int pageMin = -1, + pageMax = -1, + selFrom = -1, + selTo = -1; + REQUIRE_NOTHROW( pr.GetPageInfo(&pageMin, &pageMax, &selFrom, &selTo) ); + + // This should be always the case. + CHECK( pageMin == 1 ); + + // Return the really interesting value to the caller. + return pageMax; +} + +} // anonymous namespace + +TEST_CASE("wxHtmlPrintout::Pagination", "[html][print]") +{ + wxHtmlPrintout pr; + + wxBitmap bmp(1000, 1000); + wxMemoryDC dc(bmp); + pr.SetUp(dc); + + // Empty or short HTML documents should be printed on a single page only. + CHECK( CountPages(pr) == 1 ); + + pr.SetHtmlText("

Hello world!

"); + CHECK( CountPages(pr) == 1 ); + + // This one should be too big to fit on a single page. + pr.SetHtmlText + ( + "" + "
" + "" + ); + CHECK( CountPages(pr) == 2 ); + + // Special case: normally images are not split, but if the image height is + // greater than the page height, it should be. + pr.SetHtmlText + ( + "" + ); + CHECK( CountPages(pr) == 3 ); +} + +#endif //wxUSE_HTML diff --git a/tests/makefile.bcc b/tests/makefile.bcc index 30897885eb..69ff216d07 100644 --- a/tests/makefile.bcc +++ b/tests/makefile.bcc @@ -229,6 +229,7 @@ TEST_GUI_OBJECTS = \ $(OBJS)\test_gui_rawbmp.obj \ $(OBJS)\test_gui_htmlparser.obj \ $(OBJS)\test_gui_htmlwindow.obj \ + $(OBJS)\test_gui_htmprint.obj \ $(OBJS)\test_gui_accelentry.obj \ $(OBJS)\test_gui_menu.obj \ $(OBJS)\test_gui_guifuncs.obj \ @@ -1050,6 +1051,9 @@ $(OBJS)\test_gui_htmlparser.obj: .\html\htmlparser.cpp $(OBJS)\test_gui_htmlwindow.obj: .\html\htmlwindow.cpp $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\html\htmlwindow.cpp +$(OBJS)\test_gui_htmprint.obj: .\html\htmprint.cpp + $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\html\htmprint.cpp + $(OBJS)\test_gui_accelentry.obj: .\menu\accelentry.cpp $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\menu\accelentry.cpp diff --git a/tests/makefile.gcc b/tests/makefile.gcc index b9a05edb64..9855000899 100644 --- a/tests/makefile.gcc +++ b/tests/makefile.gcc @@ -224,6 +224,7 @@ TEST_GUI_OBJECTS = \ $(OBJS)\test_gui_rawbmp.o \ $(OBJS)\test_gui_htmlparser.o \ $(OBJS)\test_gui_htmlwindow.o \ + $(OBJS)\test_gui_htmprint.o \ $(OBJS)\test_gui_accelentry.o \ $(OBJS)\test_gui_menu.o \ $(OBJS)\test_gui_guifuncs.o \ @@ -1027,6 +1028,9 @@ $(OBJS)\test_gui_htmlparser.o: ./html/htmlparser.cpp $(OBJS)\test_gui_htmlwindow.o: ./html/htmlwindow.cpp $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\test_gui_htmprint.o: ./html/htmprint.cpp + $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\test_gui_accelentry.o: ./menu/accelentry.cpp $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $< diff --git a/tests/makefile.vc b/tests/makefile.vc index 8ae6c6c439..60ecf9ff0c 100644 --- a/tests/makefile.vc +++ b/tests/makefile.vc @@ -235,6 +235,7 @@ TEST_GUI_OBJECTS = \ $(OBJS)\test_gui_rawbmp.obj \ $(OBJS)\test_gui_htmlparser.obj \ $(OBJS)\test_gui_htmlwindow.obj \ + $(OBJS)\test_gui_htmprint.obj \ $(OBJS)\test_gui_accelentry.obj \ $(OBJS)\test_gui_menu.obj \ $(OBJS)\test_gui_guifuncs.obj \ @@ -1229,6 +1230,9 @@ $(OBJS)\test_gui_htmlparser.obj: .\html\htmlparser.cpp $(OBJS)\test_gui_htmlwindow.obj: .\html\htmlwindow.cpp $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\html\htmlwindow.cpp +$(OBJS)\test_gui_htmprint.obj: .\html\htmprint.cpp + $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\html\htmprint.cpp + $(OBJS)\test_gui_accelentry.obj: .\menu\accelentry.cpp $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\menu\accelentry.cpp diff --git a/tests/test.bkl b/tests/test.bkl index 47016bcf33..4db76b86cb 100644 --- a/tests/test.bkl +++ b/tests/test.bkl @@ -249,6 +249,7 @@ image/rawbmp.cpp html/htmlparser.cpp html/htmlwindow.cpp + html/htmprint.cpp menu/accelentry.cpp menu/menu.cpp misc/guifuncs.cpp diff --git a/tests/test_gui.vcxproj b/tests/test_gui.vcxproj index af4d68b517..d7710c370f 100644 --- a/tests/test_gui.vcxproj +++ b/tests/test_gui.vcxproj @@ -535,6 +535,7 @@ + @@ -564,4 +565,4 @@ - + \ No newline at end of file diff --git a/tests/test_gui.vcxproj.filters b/tests/test_gui.vcxproj.filters index 40ab41a51d..bd3fbfdc4d 100644 --- a/tests/test_gui.vcxproj.filters +++ b/tests/test_gui.vcxproj.filters @@ -293,10 +293,13 @@ Source Files + + Source Files + Resource Files - + \ No newline at end of file diff --git a/tests/test_vc7_test_gui.vcproj b/tests/test_vc7_test_gui.vcproj index 484c4776ac..eade1cba94 100644 --- a/tests/test_vc7_test_gui.vcproj +++ b/tests/test_vc7_test_gui.vcproj @@ -439,6 +439,9 @@ + + diff --git a/tests/test_vc8_test_gui.vcproj b/tests/test_vc8_test_gui.vcproj index 15fda65a98..8ab1a7002d 100644 --- a/tests/test_vc8_test_gui.vcproj +++ b/tests/test_vc8_test_gui.vcproj @@ -1054,6 +1054,10 @@ RelativePath=".\html\htmlwindow.cpp" > + + diff --git a/tests/test_vc9_test_gui.vcproj b/tests/test_vc9_test_gui.vcproj index 6e99dc8de7..6852c292ab 100644 --- a/tests/test_vc9_test_gui.vcproj +++ b/tests/test_vc9_test_gui.vcproj @@ -1026,6 +1026,10 @@ RelativePath=".\html\htmlwindow.cpp" > + + From b0ae6681bedc2c5868c3a6784a9ccfe0a146acfa Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 24 May 2018 00:30:38 +0200 Subject: [PATCH 08/21] Add a test of explicit page breaks in wxHtmlPrintout too Check that using the style forcing a page break does work. --- tests/html/htmprint.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/html/htmprint.cpp b/tests/html/htmprint.cpp index 0466182845..905a70d34e 100644 --- a/tests/html/htmprint.cpp +++ b/tests/html/htmprint.cpp @@ -77,6 +77,15 @@ TEST_CASE("wxHtmlPrintout::Pagination", "[html][print]") "" ); CHECK( CountPages(pr) == 3 ); + + // Test explicit page breaks too. + pr.SetHtmlText + ( + "First page" + "
" + "Second page" + ); + CHECK( CountPages(pr) == 2 ); } #endif //wxUSE_HTML From 0ada873c4521b9691b445972531617bbd4071384 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 23 May 2018 19:43:23 +0200 Subject: [PATCH 09/21] Slightly simplify wxHtmlDCRenderer::Render() Use "totalHeight" variable to make it more clear that m_Cells->GetHeight() and GetTotalHeight() are the same value. --- src/html/htmprint.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index 84f77b7df4..a11eeae995 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -168,8 +168,8 @@ int wxHtmlDCRenderer::Render(int x, int y, rinfo); } - if (pbreak < m_Cells->GetHeight()) return pbreak; - else return GetTotalHeight(); + const int totalHeight = GetTotalHeight(); + return pbreak < totalHeight ? pbreak : totalHeight; } int wxHtmlDCRenderer::GetTotalWidth() const From e01892c6697480654715d0698557bea9b3573621 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 24 May 2018 00:13:35 +0200 Subject: [PATCH 10/21] Split and simplify wxHtmlDCRenderer::Render() This function was difficult to understand as it did two quite different things depending on the value of its "dont_render" argument and using it also made CountPages() logic more complicated than necessary. Simplify the code by splitting Render() into FindNextPageBreak(), which is used by CountPages(), and Render() itself, which doesn't need to deal with pagination at all as it's either already provided the page start and end positions or can just assume that everything fits on a single page (the latter is the case for the headers and footers renderer). This is a notionally backwards-incompatible change, but no code using wxHtmlDCRenderer could be found in the wild and the new API is so much simpler that it seems to be worth switching to it. --- docs/changes.txt | 3 ++ include/wx/html/htmprint.h | 21 +++------- interface/wx/html/htmprint.h | 24 +++-------- src/html/htmprint.cpp | 78 ++++++++++++++++-------------------- 4 files changed, 48 insertions(+), 78 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index daa8c0c192..9275e58a29 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -66,6 +66,9 @@ Changes in behaviour which may result in build errors - wx/treebook.h doesn't include wx/treectrl.h (and, via it, wx/textctrl.h) any more, include these headers explicitly from your code if necessary. +- wxHtmlDCRenderer::Render() arguments have changed, simply omit the ones not + existing in the function signature any more to update the code using it. + 3.1.2: (released 2018-??-??) ---------------------------- diff --git a/include/wx/html/htmprint.h b/include/wx/html/htmprint.h index 5e4584aec1..8bd6d67e91 100644 --- a/include/wx/html/htmprint.h +++ b/include/wx/html/htmprint.h @@ -62,30 +62,19 @@ public: const wxString& normal_face = wxEmptyString, const wxString& fixed_face = wxEmptyString); + // Finds the next page break after the specified (vertical) position. + // Returns wxNOT_FOUND if passed in position is the last page break. + int FindNextPageBreak(const wxArrayInt& known_pagebreaks, int pos); + // [x,y] is position of upper-left corner of printing rectangle (see SetSize) // from is y-coordinate of the very first visible cell // to is y-coordinate of the next following page break, if any - // Returned value is y coordinate of first cell than didn't fit onto page. - // Use this value as 'from' in next call to Render in order to print multiple pages - // document - // If dont_render is TRUE then nothing is rendered into DC and it only counts - // pixels and return y coord of the next page - // - // known_pagebreaks and number_of_pages are used only when counting pages; - // otherwise, their default values should be used. Their purpose is to - // support pagebreaks using a subset of CSS2's
. The
handler - // needs to know what pagebreaks have already been set so that it doesn't - // set the same pagebreak twice. - // - // CAUTION! Render() changes DC's user scale and does NOT restore it! - int Render(int x, int y, const wxArrayInt& known_pagebreaks, int from = 0, - int dont_render = false, int to = INT_MAX); + void Render(int x, int y, int from = 0, int to = INT_MAX); // returns total width of the html document int GetTotalWidth() const; // returns total height of the html document - // (compare Render's return value with this) int GetTotalHeight() const; private: diff --git a/interface/wx/html/htmprint.h b/interface/wx/html/htmprint.h index 7d0ceaf15e..9036a6f1ff 100644 --- a/interface/wx/html/htmprint.h +++ b/interface/wx/html/htmprint.h @@ -38,10 +38,9 @@ public: /** Returns the height of the HTML text in pixels. - This is important if area height (see wxHtmlDCRenderer::SetSize) is - smaller that total height and thus the page cannot fit into it. In that - case you're supposed to call Render() as long as its return value is - smaller than GetTotalHeight()'s. + If the height of the area used with this renderer (see + wxHtmlDCRenderer::SetSize) is smaller that total height, the renderer + will produce more than one page of output. @see GetTotalWidth() */ @@ -52,19 +51,11 @@ public: @param x,y position of upper-left corner of printing rectangle (see SetSize()). - @param known_pagebreaks - @todo docme @param from y-coordinate of the very first visible cell. - @param dont_render - if @true then this method only returns y coordinate of the next page - and does not output anything. @param to - y-coordinate of the last visible cell. - - Returned value is y coordinate of first cell than didn't fit onto page. - Use this value as from in next call to Render() in order to print - multipages document. + y-coordinate of the last visible cell or @c INT_MAX to use the full + page height. @note The following three methods @b must always be called before any call to @@ -72,11 +63,8 @@ public: - SetDC() - SetSize() - SetHtmlText() - - @note Render() changes the DC's user scale and does NOT restore it. */ - int Render(int x, int y, wxArrayInt& known_pagebreaks, int from = 0, - int dont_render = false, int to = INT_MAX); + void Render(int x, int y, int from = 0, int to = INT_MAX); /** Assign DC instance to the renderer. diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index a11eeae995..a65ccb524b 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -140,36 +140,37 @@ void wxHtmlDCRenderer::SetStandardFonts(int size, // else: SetHtmlText() not yet called, no need for relayout } -int wxHtmlDCRenderer::Render(int x, int y, - const wxArrayInt& known_pagebreaks, - int from, int dont_render, int to) +int wxHtmlDCRenderer::FindNextPageBreak(const wxArrayInt& known_pagebreaks, + int pos) { - wxCHECK_MSG( m_Cells, 0, "SetHtmlText() must be called before Render()" ); - wxCHECK_MSG( m_DC, 0, "SetDC() must be called before Render()" ); + // Stop looking for page breaks if the previous one was already at the end + // of the last page. + // + // For an empty HTML document total height is 0, but we still must have at + // least a single page in it, so handle the case of pos == 0 specially. + if ( pos != 0 && pos >= GetTotalHeight() ) + return wxNOT_FOUND; - int pbreak, hght; + pos += m_Height; + while (m_Cells->AdjustPagebreak(&pos, known_pagebreaks, m_Height)) {} + return pos; +} - pbreak = (int)(from + m_Height); - while (m_Cells->AdjustPagebreak(&pbreak, known_pagebreaks, m_Height)) {} - hght = pbreak - from; - if(to < hght) - hght = to; +void wxHtmlDCRenderer::Render(int x, int y, int from, int to) +{ + wxCHECK_RET( m_DC, "SetDC() must be called before Render()" ); - if (!dont_render) - { - wxHtmlRenderingInfo rinfo; - wxDefaultHtmlRenderingStyle rstyle; - rinfo.SetStyle(&rstyle); - m_DC->SetBrush(*wxWHITE_BRUSH); - wxDCClipper clip(*m_DC, x, y, m_Width, hght); - m_Cells->Draw(*m_DC, - x, (y - from), - y, y + hght, - rinfo); - } + const int hght = to == INT_MAX ? m_Height : to - from; - const int totalHeight = GetTotalHeight(); - return pbreak < totalHeight ? pbreak : totalHeight; + wxHtmlRenderingInfo rinfo; + wxDefaultHtmlRenderingStyle rstyle; + rinfo.SetStyle(&rstyle); + m_DC->SetBrush(*wxWHITE_BRUSH); + wxDCClipper clip(*m_DC, x, y, m_Width, hght); + m_Cells->Draw(*m_DC, + x, (y - from), + y, y + hght, + rinfo); } int wxHtmlDCRenderer::GetTotalWidth() const @@ -470,27 +471,16 @@ void wxHtmlPrintout::SetFooter(const wxString& footer, int pg) void wxHtmlPrintout::CountPages() { wxBusyCursor wait; - int pageWidth, pageHeight, mm_w, mm_h; - float ppmm_h, ppmm_v; - GetPageSizePixels(&pageWidth, &pageHeight); - GetPageSizeMM(&mm_w, &mm_h); - ppmm_h = (float)pageWidth / mm_w; - ppmm_v = (float)pageHeight / mm_h; - - int pos = 0; m_NumPages = 0; m_PageBreaks.Clear(); - m_PageBreaks.Add( 0); - do + + for ( int pos = 0; pos != wxNOT_FOUND; ) { - pos = m_Renderer.Render((int)( ppmm_h * m_MarginLeft), - (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), - m_PageBreaks, - pos, true, INT_MAX); m_PageBreaks.Add( pos); - } while (pos < m_Renderer.GetTotalHeight()); + pos = m_Renderer.FindNextPageBreak(m_PageBreaks, pos); + } } @@ -525,8 +515,8 @@ void wxHtmlPrintout::RenderPage(wxDC *dc, int page) dc->SetBackgroundMode(wxTRANSPARENT); m_Renderer.Render((int) (ppmm_h * m_MarginLeft), - (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), m_PageBreaks, - m_PageBreaks[page-1], false, m_PageBreaks[page]-m_PageBreaks[page-1]); + (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), + m_PageBreaks[page-1], m_PageBreaks[page]); m_RendererHdr.SetDC(dc, @@ -535,12 +525,12 @@ void wxHtmlPrintout::RenderPage(wxDC *dc, int page) if (!m_Headers[page % 2].empty()) { m_RendererHdr.SetHtmlText(TranslateHeader(m_Headers[page % 2], page)); - m_RendererHdr.Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop), m_PageBreaks); + m_RendererHdr.Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop)); } if (!m_Footers[page % 2].empty()) { m_RendererHdr.SetHtmlText(TranslateHeader(m_Footers[page % 2], page)); - m_RendererHdr.Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight), m_PageBreaks); + m_RendererHdr.Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight)); } } From 63add2cd1931b01b928b73d574397c792791d6a1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 24 May 2018 15:47:08 +0200 Subject: [PATCH 11/21] Don't call AdjustPagebreak() in a loop, this seems useless There doesn't seem to be any reason to call this function more than once on the same cell as the existing implementations are idempotent and it's difficult to see why this should ever not be the case. --- include/wx/html/htmlcell.h | 1 - interface/wx/html/htmlcell.h | 10 ++-------- src/html/htmprint.cpp | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/include/wx/html/htmlcell.h b/include/wx/html/htmlcell.h index 6f726b2795..80535d39f3 100644 --- a/include/wx/html/htmlcell.h +++ b/include/wx/html/htmlcell.h @@ -286,7 +286,6 @@ public: // few pixels up. // // Returned value : true if pagebreak was modified, false otherwise - // Usage : while (container->AdjustPagebreak(&p)) {} virtual bool AdjustPagebreak(int *pagebreak, const wxArrayInt& known_pagebreaks, int pageHeight) const; diff --git a/interface/wx/html/htmlcell.h b/interface/wx/html/htmlcell.h index 665de5f5b4..1ad5aa7382 100644 --- a/interface/wx/html/htmlcell.h +++ b/interface/wx/html/htmlcell.h @@ -198,19 +198,13 @@ public: Returns @true if pagebreak was modified, @false otherwise. @param pagebreak - position in pixel of the pagebreak. + position in pixels of the pagebreak. @param known_pagebreaks the list of the previous pagebreaks @param pageHeight - the height in pixel of the page drawable area - - Usage: - @code - while (container->AdjustPagebreak(&p, kp, ph)) {} - @endcode - + the height in pixels of the page drawable area */ virtual bool AdjustPagebreak(int* pagebreak, const wxArrayInt& known_pagebreaks, diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index a65ccb524b..5a1e4d0c87 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -152,7 +152,7 @@ int wxHtmlDCRenderer::FindNextPageBreak(const wxArrayInt& known_pagebreaks, return wxNOT_FOUND; pos += m_Height; - while (m_Cells->AdjustPagebreak(&pos, known_pagebreaks, m_Height)) {} + m_Cells->AdjustPagebreak(&pos, known_pagebreaks, m_Height); return pos; } From 71948018f48ed428f63b34b29c909dea9d744d10 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 24 May 2018 17:51:40 +0200 Subject: [PATCH 12/21] Add a sanity check for AdjustPagebreak() implementation Verify that this function never adjusts page break so far back that it comes before the previous one (or even at the same position). This avoids infinite loops in CountPages() even if a custom cell class implements its overridden AdjustPagebreak() incorrectly. --- src/html/htmprint.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index 5a1e4d0c87..f42b008fff 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -151,9 +151,16 @@ int wxHtmlDCRenderer::FindNextPageBreak(const wxArrayInt& known_pagebreaks, if ( pos != 0 && pos >= GetTotalHeight() ) return wxNOT_FOUND; - pos += m_Height; - m_Cells->AdjustPagebreak(&pos, known_pagebreaks, m_Height); - return pos; + int posNext = pos + m_Height; + if ( m_Cells->AdjustPagebreak(&posNext, known_pagebreaks, m_Height) ) + { + // Check that AdjustPagebreak() returns the page break at a strictly + // greater position than that of the previous page, otherwise + // CountPages() would enter into an infinite loop. + wxCHECK_MSG( posNext > pos, wxNOT_FOUND, "Bug in AdjustPagebreak()" ); + } + + return posNext; } void wxHtmlDCRenderer::Render(int x, int y, int from, int to) From c58d81d32d7faa6dd53a124f27675b3d50b5567b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 24 May 2018 17:46:14 +0200 Subject: [PATCH 13/21] Simplify wxHtmlPageBreakCell::AdjustPagebreak() There is no need to look in the known page breaks array for a page break at the position of this cell, all we care about is whether this cell is on the current page or not: we must insert a page break if, and only if, it is. No real changes in behaviour, but the code is now much simpler to understand and this change paves way for removing "known_pagebreaks" entirely, as it was only added for the use in this function (see f2034f1b6e04a39f6d882cf6cdd53c11bf39f5d7 from 15 years ago), which doesn't even actually need it. It should also make pagination code somewhat faster. --- src/html/m_layout.cpp | 44 ++++++++----------------------------------- 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/src/html/m_layout.cpp b/src/html/m_layout.cpp index 619ec2bb08..4dba82e6d1 100644 --- a/src/html/m_layout.cpp +++ b/src/html/m_layout.cpp @@ -80,47 +80,19 @@ private: bool wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak, - const wxArrayInt& known_pagebreaks, - int WXUNUSED(pageHeight)) const + const wxArrayInt& WXUNUSED(known_pagebreaks), + int pageHeight) const { - // When we are counting pages, 'known_pagebreaks' is non-NULL. - // That's the only time we change 'pagebreak'. Otherwise, pages - // were already counted, 'known_pagebreaks' is NULL, and we don't - // do anything except return false. - // - // We also simply return false if the 'pagebreak' argument is - // less than (vertically above) or the same as the current - // vertical position. Otherwise we'd be setting a pagebreak above - // the current cell, which is incorrect, or duplicating a - // pagebreak that has already been set. - if( known_pagebreaks.GetCount() == 0 || *pagebreak <= m_PosY) - { - return false; - } - - // m_PosY is only the vertical offset from the parent. The pagebreak - // required here is the total page offset, so m_PosY must be added - // to the parent's offset and height. - int total_height = m_PosY; - for ( wxHtmlCell *parent = GetParent(); parent; parent = parent->GetParent() ) - { - total_height += parent->GetPosY(); - } - - - // Search the array of pagebreaks to see whether we've already set - // a pagebreak here. - int where = known_pagebreaks.Index( total_height); - // Add a pagebreak only if there isn't one already set here. - if( wxNOT_FOUND != where) - { - return false; - } - else + // Request a page break at the position of this cell if it's on the current + // page. Note that it's important not to do it unconditionally or we could + // end up in an infinite number of page breaks at this cell position. + if ( m_PosY < *pagebreak && m_PosY > *pagebreak - pageHeight ) { *pagebreak = m_PosY; return true; } + + return false; } From b9b6ccb80461fb694130e046e9f23d3919ff3ecb Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 24 May 2018 18:05:58 +0200 Subject: [PATCH 14/21] Remove "known_pagebreaks" from wxHtmlCell::AdjustPagebreak() This parameter is not actually needed for any reasonable page breaking algorithm, as it shouldn't care about any previous page breaks except for the last one, which is already known as "*pagebreak - pageHeight" in this function. Removing it will allow to stop using wxArrayInt in the code using this method and switch to an std::vector instead. This is not a backwards compatible change, but it seems that there is very little code actually overriding this function (none could be found in any open source repositories) and updating it should be as simple as removing the now unneeded argument. --- docs/changes.txt | 3 +++ include/wx/html/htmlcell.h | 24 +++++++++++++----------- include/wx/html/htmprint.h | 2 +- interface/wx/html/htmlcell.h | 33 ++++++++++++++++++--------------- src/html/htmlcell.cpp | 12 ++++-------- src/html/htmprint.cpp | 7 +++---- src/html/m_layout.cpp | 8 ++------ 7 files changed, 44 insertions(+), 45 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 9275e58a29..f59a0fd64e 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -69,6 +69,9 @@ Changes in behaviour which may result in build errors - wxHtmlDCRenderer::Render() arguments have changed, simply omit the ones not existing in the function signature any more to update the code using it. +- wxHtmlCell::AdjustPagebreak() has lost its "known_pagebreaks" argument, + update your code if you override this method (you shouldn't be calling it). + 3.1.2: (released 2018-??-??) ---------------------------- diff --git a/include/wx/html/htmlcell.h b/include/wx/html/htmlcell.h index 80535d39f3..282b7cd964 100644 --- a/include/wx/html/htmlcell.h +++ b/include/wx/html/htmlcell.h @@ -279,16 +279,20 @@ public: const wxPoint& pos, const wxMouseEvent& event); - // This method used to adjust pagebreak position. The parameter is variable - // that contains y-coordinate of page break (= horizontal line that should - // not be crossed by words, images etc.). If this cell cannot be divided - // into two pieces (each one on another page) then it moves the pagebreak - // few pixels up. + // This method is called when paginating HTML, e.g. when printing. + // + // On input, pagebreak contains y-coordinate of page break (i.e. the + // horizontal line that should not be crossed by words, images etc.) + // relative to the parent cell on entry and may be modified to request a + // page break at a position before it if this cell cannot be divided into + // two pieces (each one on its own page). + // + // Note that page break must still happen on the current page, i.e. the + // returned value must be strictly greater than "*pagebreak - pageHeight" + // and less or equal to "*pagebreak" for the value of pagebreak on input. // // Returned value : true if pagebreak was modified, false otherwise - virtual bool AdjustPagebreak(int *pagebreak, - const wxArrayInt& known_pagebreaks, - int pageHeight) const; + virtual bool AdjustPagebreak(int *pagebreak, int pageHeight) const; // Sets cell's behaviour on pagebreaks (see AdjustPagebreak). Default // is true - the cell can be split on two pages @@ -450,9 +454,7 @@ public: virtual void DrawInvisible(wxDC& dc, int x, int y, wxHtmlRenderingInfo& info) wxOVERRIDE; - virtual bool AdjustPagebreak(int *pagebreak, - const wxArrayInt& known_pagebreaks, - int pageHeight) const wxOVERRIDE; + virtual bool AdjustPagebreak(int *pagebreak, int pageHeight) const wxOVERRIDE; // insert cell at the end of m_Cells list void InsertCell(wxHtmlCell *cell); diff --git a/include/wx/html/htmprint.h b/include/wx/html/htmprint.h index 8bd6d67e91..7edfa808db 100644 --- a/include/wx/html/htmprint.h +++ b/include/wx/html/htmprint.h @@ -64,7 +64,7 @@ public: // Finds the next page break after the specified (vertical) position. // Returns wxNOT_FOUND if passed in position is the last page break. - int FindNextPageBreak(const wxArrayInt& known_pagebreaks, int pos); + int FindNextPageBreak(int pos); // [x,y] is position of upper-left corner of printing rectangle (see SetSize) // from is y-coordinate of the very first visible cell diff --git a/interface/wx/html/htmlcell.h b/interface/wx/html/htmlcell.h index 1ad5aa7382..18b05a8a00 100644 --- a/interface/wx/html/htmlcell.h +++ b/interface/wx/html/htmlcell.h @@ -187,28 +187,31 @@ public: wxHtmlCell(); /** - This method is used to adjust pagebreak position. - The first parameter is a variable that contains the y-coordinate of the page break - (= horizontal line that should not be crossed by words, images etc.). - If this cell cannot be divided into two pieces (each one on another page) - then it either moves the pagebreak a few pixels up, if possible, or, if - the cell cannot fit on the page at all, then the cell is forced to - split unconditionally. + This method is called when paginating HTML, e.g.\ when printing. - Returns @true if pagebreak was modified, @false otherwise. + User code should never call this function, but may need to override it + in custom HTML cell classes with any specific page breaking + requirements. + + On input, @a pagebreak contains y-coordinate of page break (i.e. the + horizontal line that should not be crossed by words, images etc.) + relative to the parent cell on entry and may be modified to request a + page break at a position before it if this cell cannot be divided into + two pieces (each one on its own page). + + Note that page break must still happen on the current page, i.e. the + returned value must be strictly greater than @code *pagebreak - + pageHeight @endcode and less or equal to @c *pagebreak for the value of + @a pagebreak on input. @param pagebreak position in pixels of the pagebreak. - - @param known_pagebreaks - the list of the previous pagebreaks - @param pageHeight the height in pixels of the page drawable area + + @return @true if pagebreak was modified, @false otherwise. */ - virtual bool AdjustPagebreak(int* pagebreak, - const wxArrayInt& known_pagebreaks, - int pageHeight) const; + virtual bool AdjustPagebreak(int* pagebreak, int pageHeight) const; /** Renders the cell. diff --git a/src/html/htmlcell.cpp b/src/html/htmlcell.cpp index 0f14760198..176c5e79c4 100644 --- a/src/html/htmlcell.cpp +++ b/src/html/htmlcell.cpp @@ -157,9 +157,7 @@ wxHtmlCell::GetMouseCursorAt(wxHtmlWindowInterface *window, bool -wxHtmlCell::AdjustPagebreak(int *pagebreak, - const wxArrayInt& WXUNUSED(known_pagebreaks), - int pageHeight) const +wxHtmlCell::AdjustPagebreak(int *pagebreak, int pageHeight) const { // Notice that we always break the cells bigger than the page height here // as otherwise we wouldn't be able to break them at all. @@ -697,19 +695,17 @@ int wxHtmlContainerCell::GetIndentUnits(int ind) const bool -wxHtmlContainerCell::AdjustPagebreak(int *pagebreak, - const wxArrayInt& known_pagebreaks, - int pageHeight) const +wxHtmlContainerCell::AdjustPagebreak(int *pagebreak, int pageHeight) const { if (!m_CanLiveOnPagebreak) - return wxHtmlCell::AdjustPagebreak(pagebreak, known_pagebreaks, pageHeight); + return wxHtmlCell::AdjustPagebreak(pagebreak, pageHeight); bool rt = false; int pbrk = *pagebreak - m_PosY; for ( wxHtmlCell *c = GetFirstChild(); c; c = c->GetNext() ) { - if (c->AdjustPagebreak(&pbrk, known_pagebreaks, pageHeight)) + if (c->AdjustPagebreak(&pbrk, pageHeight)) rt = true; } if (rt) diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index f42b008fff..199f89b835 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -140,8 +140,7 @@ void wxHtmlDCRenderer::SetStandardFonts(int size, // else: SetHtmlText() not yet called, no need for relayout } -int wxHtmlDCRenderer::FindNextPageBreak(const wxArrayInt& known_pagebreaks, - int pos) +int wxHtmlDCRenderer::FindNextPageBreak(int pos) { // Stop looking for page breaks if the previous one was already at the end // of the last page. @@ -152,7 +151,7 @@ int wxHtmlDCRenderer::FindNextPageBreak(const wxArrayInt& known_pagebreaks, return wxNOT_FOUND; int posNext = pos + m_Height; - if ( m_Cells->AdjustPagebreak(&posNext, known_pagebreaks, m_Height) ) + if ( m_Cells->AdjustPagebreak(&posNext, m_Height) ) { // Check that AdjustPagebreak() returns the page break at a strictly // greater position than that of the previous page, otherwise @@ -486,7 +485,7 @@ void wxHtmlPrintout::CountPages() for ( int pos = 0; pos != wxNOT_FOUND; ) { m_PageBreaks.Add( pos); - pos = m_Renderer.FindNextPageBreak(m_PageBreaks, pos); + pos = m_Renderer.FindNextPageBreak(pos); } } diff --git a/src/html/m_layout.cpp b/src/html/m_layout.cpp index 4dba82e6d1..95b0afbab2 100644 --- a/src/html/m_layout.cpp +++ b/src/html/m_layout.cpp @@ -65,9 +65,7 @@ class wxHtmlPageBreakCell : public wxHtmlCell public: wxHtmlPageBreakCell() {} - bool AdjustPagebreak(int* pagebreak, - const wxArrayInt& known_pagebreaks, - int pageHeight) const wxOVERRIDE; + bool AdjustPagebreak(int* pagebreak, int pageHeight) const wxOVERRIDE; void Draw(wxDC& WXUNUSED(dc), int WXUNUSED(x), int WXUNUSED(y), @@ -79,9 +77,7 @@ private: }; bool -wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak, - const wxArrayInt& WXUNUSED(known_pagebreaks), - int pageHeight) const +wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak, int pageHeight) const { // Request a page break at the position of this cell if it's on the current // page. Note that it's important not to do it unconditionally or we could From edeca4d9d66ce4ef51eae3f18dc165c21be612ee Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 24 May 2018 18:11:45 +0200 Subject: [PATCH 15/21] Use wxVector instead of wxArrayInt in wxHtmlDCRenderer No real changes, just prefer standard-like template class to the legacy wx one. --- include/wx/html/htmprint.h | 3 ++- src/html/htmprint.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/wx/html/htmprint.h b/include/wx/html/htmprint.h index 7edfa808db..e2462ceaf5 100644 --- a/include/wx/html/htmprint.h +++ b/include/wx/html/htmprint.h @@ -20,6 +20,7 @@ #include "wx/print.h" #include "wx/printdlg.h" +#include "wx/vector.h" #include // INT_MAX @@ -188,7 +189,7 @@ private: private: int m_NumPages; - wxArrayInt m_PageBreaks; + wxVector m_PageBreaks; wxString m_Document, m_BasePath; bool m_BasePathIsDir; diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index 199f89b835..703fe6387a 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -388,19 +388,19 @@ bool wxHtmlPrintout::OnPrintPage(int page) void wxHtmlPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) { *minPage = 1; - if ( m_NumPages >= (signed)m_PageBreaks.GetCount()-1) + if ( m_NumPages >= (signed)m_PageBreaks.size()-1) *maxPage = m_NumPages; else - *maxPage = (signed)m_PageBreaks.GetCount()-1; + *maxPage = (signed)m_PageBreaks.size()-1; *selPageFrom = 1; - *selPageTo = (signed)m_PageBreaks.GetCount()-1; + *selPageTo = (signed)m_PageBreaks.size()-1; } bool wxHtmlPrintout::HasPage(int pageNum) { - return pageNum > 0 && (unsigned)pageNum < m_PageBreaks.GetCount(); + return pageNum > 0 && (unsigned)pageNum < m_PageBreaks.size(); } @@ -480,11 +480,11 @@ void wxHtmlPrintout::CountPages() m_NumPages = 0; - m_PageBreaks.Clear(); + m_PageBreaks.clear(); for ( int pos = 0; pos != wxNOT_FOUND; ) { - m_PageBreaks.Add( pos); + m_PageBreaks.push_back(pos); pos = m_Renderer.FindNextPageBreak(pos); } } @@ -550,7 +550,7 @@ wxString wxHtmlPrintout::TranslateHeader(const wxString& instr, int page) num.Printf(wxT("%i"), page); r.Replace(wxT("@PAGENUM@"), num); - num.Printf(wxT("%lu"), (unsigned long)(m_PageBreaks.GetCount() - 1)); + num.Printf(wxT("%lu"), (unsigned long)(m_PageBreaks.size() - 1)); r.Replace(wxT("@PAGESCNT@"), num); #if wxUSE_DATETIME From c5bb583cdffb91d12947d3d586a30141faab22e2 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 25 May 2018 01:22:29 +0200 Subject: [PATCH 16/21] Replace wxList used in wxHtmlPrintout with wxVector<> too Prefer the use of the standard-like template class to macro-based list. It also makes more sense to use a vector rather than a linked list here, as the elements are never removed from or inserted into m_Filters, so there is no reason to prefer the list structure. --- include/wx/html/htmprint.h | 2 +- src/html/htmprint.cpp | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/wx/html/htmprint.h b/include/wx/html/htmprint.h index e2462ceaf5..2efafaf29f 100644 --- a/include/wx/html/htmprint.h +++ b/include/wx/html/htmprint.h @@ -200,7 +200,7 @@ private: float m_MarginTop, m_MarginBottom, m_MarginLeft, m_MarginRight, m_MarginSpace; // list of HTML filters - static wxList m_Filters; + static wxVector m_Filters; wxDECLARE_NO_COPY_CLASS(wxHtmlPrintout); }; diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index 703fe6387a..d7d3e7059a 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -195,7 +195,7 @@ int wxHtmlDCRenderer::GetTotalHeight() const //-------------------------------------------------------------------------------- -wxList wxHtmlPrintout::m_Filters; +wxVector wxHtmlPrintout::m_Filters; wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title) { @@ -210,13 +210,16 @@ wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title) void wxHtmlPrintout::CleanUpStatics() { - WX_CLEAR_LIST(wxList, m_Filters); + for ( size_t n = 0; n < m_Filters.size(); ++n ) + delete m_Filters[n]; + + m_Filters.clear(); } // Adds input filter void wxHtmlPrintout::AddFilter(wxHtmlFilter *filter) { - m_Filters.Append(filter); + m_Filters.push_back(filter); } bool @@ -432,17 +435,15 @@ void wxHtmlPrintout::SetHtmlFile(const wxString& htmlfile) wxHtmlFilterHTML defaultFilter; wxString doc; - wxList::compatibility_iterator node = m_Filters.GetFirst(); - while (node) + for ( size_t n = 0; n < m_Filters.size(); ++n ) { - wxHtmlFilter *h = (wxHtmlFilter*) node->GetData(); + wxHtmlFilter* const h = m_Filters[n]; if (h->CanRead(*ff)) { doc = h->ReadFile(*ff); done = true; break; } - node = node->GetNext(); } if (!done) From 8d7601295ba7ed8ac44f866fd60f75ef205c88e1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 25 May 2018 01:31:54 +0200 Subject: [PATCH 17/21] Make wxHtmlDCRenderer::FindNextPageBreak() const It doesn't modify the renderer. --- include/wx/html/htmprint.h | 2 +- src/html/htmprint.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/wx/html/htmprint.h b/include/wx/html/htmprint.h index 2efafaf29f..a455dec747 100644 --- a/include/wx/html/htmprint.h +++ b/include/wx/html/htmprint.h @@ -65,7 +65,7 @@ public: // Finds the next page break after the specified (vertical) position. // Returns wxNOT_FOUND if passed in position is the last page break. - int FindNextPageBreak(int pos); + int FindNextPageBreak(int pos) const; // [x,y] is position of upper-left corner of printing rectangle (see SetSize) // from is y-coordinate of the very first visible cell diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index d7d3e7059a..3b03b2e67c 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -140,7 +140,7 @@ void wxHtmlDCRenderer::SetStandardFonts(int size, // else: SetHtmlText() not yet called, no need for relayout } -int wxHtmlDCRenderer::FindNextPageBreak(int pos) +int wxHtmlDCRenderer::FindNextPageBreak(int pos) const { // Stop looking for page breaks if the previous one was already at the end // of the last page. From bf9712978aa7344416e1b35ff0c9808f7132c1f6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 25 May 2018 01:32:31 +0200 Subject: [PATCH 18/21] Document wxHtmlDCRenderer::FindNextPageBreak() This is a useful (even if mostly trivial) function, so document it and mention it in Render() documentation too. --- interface/wx/html/htmprint.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/interface/wx/html/htmprint.h b/interface/wx/html/htmprint.h index 9036a6f1ff..6e6a0908dc 100644 --- a/interface/wx/html/htmprint.h +++ b/interface/wx/html/htmprint.h @@ -46,9 +46,39 @@ public: */ int GetTotalHeight() const; + /** + Finds the next page break after the specified (vertical) position. + + An example of using this method: + + @code + std::vector pages; + for ( int pos = 0; pos != wxNOT_FOUND; pos = renderer.FindNextPageBreak(pos) ) + { + pages.push_back(pos); + } + + // "pages" vector now contains all page break positions and, in + // particular, its size() returns the number of pages + @endcode + + @param pos Absolute position of the last page break. For the initial + call of this function, it should be 0 and for the subsequent ones + it should be the previous return value. + @return Position of the next page break or @c wxNOT_FOUND if there are + no more of them. + + @since 3.1.2 + */ + int FindNextPageBreak(int pos) const; + /** Renders HTML text to the DC. + When using multi-page documents, FindNextPageBreak() can be used to + find the values for @a from and @a to, which should be the consecutive + page breaks returned by that function. + @param x,y position of upper-left corner of printing rectangle (see SetSize()). @param from From adfde70054f6911faeffc9cf6f9cde29baf275a7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 25 May 2018 01:35:34 +0200 Subject: [PATCH 19/21] Remove redundant wxHtmlDCRenderer::m_NumPages The actual number of pages is given by the number of elements in m_PageBreaks vector after CountPages() is shown and is unknown until then, so m_NumPages is completely unnecessary and can be just removed. --- include/wx/html/htmprint.h | 3 +-- src/html/htmprint.cpp | 7 ++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/include/wx/html/htmprint.h b/include/wx/html/htmprint.h index a455dec747..3c0d12f6ab 100644 --- a/include/wx/html/htmprint.h +++ b/include/wx/html/htmprint.h @@ -184,11 +184,10 @@ private: wxString TranslateHeader(const wxString& instr, int page); // substitute @PAGENUM@ and @PAGESCNT@ by real values void CountPages(); - // counts pages and fills m_NumPages and m_PageBreaks + // fills m_PageBreaks, which indirectly gives the number of pages private: - int m_NumPages; wxVector m_PageBreaks; wxString m_Document, m_BasePath; diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index 3b03b2e67c..781c9f4d98 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -199,7 +199,6 @@ wxVector wxHtmlPrintout::m_Filters; wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title) { - m_NumPages = INT_MAX; m_BasePathIsDir = true; m_HeaderHeight = m_FooterHeight = 0; SetMargins(); // to default values @@ -391,8 +390,8 @@ bool wxHtmlPrintout::OnPrintPage(int page) void wxHtmlPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) { *minPage = 1; - if ( m_NumPages >= (signed)m_PageBreaks.size()-1) - *maxPage = m_NumPages; + if ( m_PageBreaks.empty() ) + *maxPage = INT_MAX; else *maxPage = (signed)m_PageBreaks.size()-1; *selPageFrom = 1; @@ -479,8 +478,6 @@ void wxHtmlPrintout::CountPages() { wxBusyCursor wait; - m_NumPages = 0; - m_PageBreaks.clear(); for ( int pos = 0; pos != wxNOT_FOUND; ) From 8dffab05563c6833c3376ff238f5a15b1ea621f7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 May 2018 22:28:33 +0200 Subject: [PATCH 20/21] Add another page-break-before test to pagination unit test Check that the nested elements with this style are handled as expected. --- tests/html/htmprint.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/html/htmprint.cpp b/tests/html/htmprint.cpp index 905a70d34e..58df3ed3e2 100644 --- a/tests/html/htmprint.cpp +++ b/tests/html/htmprint.cpp @@ -86,6 +86,19 @@ TEST_CASE("wxHtmlPrintout::Pagination", "[html][print]") "Second page" ); CHECK( CountPages(pr) == 2 ); + + pr.SetHtmlText + ( + "Something" + "
" + "
" + "
" + "whatever" + "
" + "
" + "
" + ); + CHECK( CountPages(pr) == 2 ); } #endif //wxUSE_HTML From b55578e40c1cd7133bab2613feba24ee6c63b9c5 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 May 2018 22:43:28 +0200 Subject: [PATCH 21/21] Fix HTML pagination test for high DPI values The standard margins, expressed in millimeters, could result in the usable page space being much smaller than 1000px used for the DC size when using higher DPIs, which means that the test checking that a 2400px image took only 3 pages could fail, as it could require 4 of them in this case. Fix this by getting rid of the margins, as this should ensure that the page height is exactly 1000px now, independently of the actual DPI. --- tests/html/htmprint.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/html/htmprint.cpp b/tests/html/htmprint.cpp index 58df3ed3e2..34560d9cb8 100644 --- a/tests/html/htmprint.cpp +++ b/tests/html/htmprint.cpp @@ -51,6 +51,14 @@ TEST_CASE("wxHtmlPrintout::Pagination", "[html][print]") { wxHtmlPrintout pr; + // Pagination works in terms of printer page size, which is obtained by + // subtracting margins from the total size and margins are expressed in + // millimeters, so their conversion to pixels depends on DPI. To ensure + // that we get the same results for all values of DPI, get just get rid + // of the margins entirely (it would also be possible to adjust them by + // the DPI-dependent factor, but it doesn't seem to be worth doing it). + pr.SetMargins(0, 0, 0, 0, 0); + wxBitmap bmp(1000, 1000); wxMemoryDC dc(bmp); pr.SetUp(dc);