From 9db0234abcfad88c95f1839a2eecffb4d9700f5b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 25 Aug 2018 02:35:20 +0200 Subject: [PATCH] Allow passing already parsed HTML to wxHtmlDCRenderer This is more efficient when the same HTML is reused multiple times, e.g. for measuring it first and then rendering it. The new function also makes it simpler to parse HTML and manipulate it in some way before measuring and rendering it. --- include/wx/html/htmprint.h | 8 ++++++++ interface/wx/html/htmprint.h | 13 +++++++++++++ src/html/htmprint.cpp | 30 ++++++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/include/wx/html/htmprint.h b/include/wx/html/htmprint.h index 0c206ade6c..830a1d8362 100644 --- a/include/wx/html/htmprint.h +++ b/include/wx/html/htmprint.h @@ -54,6 +54,11 @@ public: // (see wxFileSystem for detailed explanation) void SetHtmlText(const wxString& html, const wxString& basepath = wxEmptyString, bool isdir = true); + // Sets the HTML cell that will be rendered: this is more efficient than + // using text as it allows to parse it only once. Note that the cell will + // be modified by this call. + void SetHtmlCell(wxHtmlContainerCell& cell); + // Sets fonts to be used when displaying HTML page. (if size null then default sizes used). void SetFonts(const wxString& normal_face, const wxString& fixed_face, const int *sizes = NULL); @@ -79,11 +84,14 @@ public: int GetTotalHeight() const; private: + void DoSetHtmlCell(wxHtmlContainerCell* cell); + wxDC *m_DC; wxHtmlWinParser *m_Parser; wxFileSystem *m_FS; wxHtmlContainerCell *m_Cells; int m_Width, m_Height; + bool m_ownsCells; wxDECLARE_NO_COPY_CLASS(wxHtmlDCRenderer); }; diff --git a/interface/wx/html/htmprint.h b/interface/wx/html/htmprint.h index 8e2dfdc9db..1b4a4e861b 100644 --- a/interface/wx/html/htmprint.h +++ b/interface/wx/html/htmprint.h @@ -168,6 +168,19 @@ public: const wxString& basepath = wxEmptyString, bool isdir = true); + /** + Associate the given HTML contents to the renderer. + + This is similar to SetHtmlText(), but is more efficient as the text can + be parsed only once, using wxHtmlParser::Parse(), and then passed to + wxHtmlDCRenderer multiple times or already reused for other purposes. + + Note that @a cell will be modified (e.g. laid out) by this function. + + @since 3.1.2 + */ + void SetHtmlCell(wxHtmlContainerCell& cell); + /** Set size of output rectangle, in pixels. Note that you @b can't change width of the rectangle between calls to Render() ! diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index a3acb7d007..86b0b7f51b 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -70,6 +70,7 @@ wxHtmlDCRenderer::wxHtmlDCRenderer() : wxObject() m_DC = NULL; m_Width = m_Height = 0; m_Cells = NULL; + m_ownsCells = false; m_Parser = new wxHtmlWinParser(); m_FS = new wxFileSystem(); m_Parser->SetFS(m_FS); @@ -80,7 +81,9 @@ wxHtmlDCRenderer::wxHtmlDCRenderer() : wxObject() wxHtmlDCRenderer::~wxHtmlDCRenderer() { - if (m_Cells) delete m_Cells; + if ( m_ownsCells ) + delete m_Cells; + if (m_Parser) delete m_Parser; if (m_FS) delete m_FS; } @@ -110,14 +113,33 @@ void wxHtmlDCRenderer::SetHtmlText(const wxString& html, const wxString& basepat wxCHECK_RET( m_DC, "SetDC() must be called before SetHtmlText()" ); wxCHECK_RET( m_Width, "SetSize() must be called before SetHtmlText()" ); - wxDELETE(m_Cells); - m_FS->ChangePathTo(basepath, isdir); - m_Cells = (wxHtmlContainerCell*) m_Parser->Parse(html); + + wxHtmlContainerCell* const cell = (wxHtmlContainerCell*) m_Parser->Parse(html); + wxCHECK_RET( cell, "Failed to parse HTML" ); + + DoSetHtmlCell(cell); + + m_ownsCells = true; +} + +void wxHtmlDCRenderer::DoSetHtmlCell(wxHtmlContainerCell* cell) +{ + if ( m_ownsCells ) + delete m_Cells; + + m_Cells = cell; m_Cells->SetIndent(0, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS); m_Cells->Layout(m_Width); } +void wxHtmlDCRenderer::SetHtmlCell(wxHtmlContainerCell& cell) +{ + DoSetHtmlCell(&cell); + + m_ownsCells = false; +} + void wxHtmlDCRenderer::SetFonts(const wxString& normal_face, const wxString& fixed_face, const int *sizes)