Fix infinite loop in wxHtmlEasyPrinting page break code.

The code didn't handle cells higher than the page height correctly and entered
an infinite loop when trying to adjust page breaks in their presence, e.g.
when trying to print a very tall image.

Closes #13935.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70528 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2012-02-07 13:02:32 +00:00
parent d7235613f4
commit 846f4568e5
6 changed files with 50 additions and 18 deletions

View File

@@ -469,6 +469,8 @@ All:
All (GUI): All (GUI):
- Added strike-through support to wxFont (Igor Korot). - Added strike-through support to wxFont (Igor Korot).
- Fix infinite loop in wxHtmlEasyPrinting when trying to page break images
taller than the page height in wxHtmlEasyPrinting (Laurent Poujoulat).
- Added wxFilePickerCtrl::SetInitialDirectory(). - Added wxFilePickerCtrl::SetInitialDirectory().
- Added wxDataViewItemAttr::SetBackgroundColour() and implemented it in generic - Added wxDataViewItemAttr::SetBackgroundColour() and implemented it in generic
wxDataViewCtrl (Andrew Xu). wxDataViewCtrl (Andrew Xu).

View File

@@ -280,10 +280,13 @@ public:
// Returned value : true if pagebreak was modified, false otherwise // Returned value : true if pagebreak was modified, false otherwise
// Usage : while (container->AdjustPagebreak(&p)) {} // Usage : while (container->AdjustPagebreak(&p)) {}
virtual bool AdjustPagebreak(int *pagebreak, virtual bool AdjustPagebreak(int *pagebreak,
const wxArrayInt& known_pagebreaks) const; const wxArrayInt& known_pagebreaks,
int pageHeight) const;
// Sets cell's behaviour on pagebreaks (see AdjustPagebreak). Default // Sets cell's behaviour on pagebreaks (see AdjustPagebreak). Default
// is true - the cell can be split on two pages // is true - the cell can be split on two pages
// If there is no way to fit a cell in the current page size, the cell
// is always split, ignoring this setting.
void SetCanLiveOnPagebreak(bool can) { m_CanLiveOnPagebreak = can; } void SetCanLiveOnPagebreak(bool can) { m_CanLiveOnPagebreak = can; }
// Can the line be broken before this cell? // Can the line be broken before this cell?
@@ -439,8 +442,10 @@ public:
wxHtmlRenderingInfo& info); wxHtmlRenderingInfo& info);
virtual void DrawInvisible(wxDC& dc, int x, int y, virtual void DrawInvisible(wxDC& dc, int x, int y,
wxHtmlRenderingInfo& info); wxHtmlRenderingInfo& info);
/* virtual bool AdjustPagebreak(int *pagebreak, int *known_pagebreaks = NULL, int number_of_pages = 0) const;*/
virtual bool AdjustPagebreak(int *pagebreak, const wxArrayInt& known_pagebreaks) const; virtual bool AdjustPagebreak(int *pagebreak,
const wxArrayInt& known_pagebreaks,
int pageHeight) const;
// insert cell at the end of m_Cells list // insert cell at the end of m_Cells list
void InsertCell(wxHtmlCell *cell); void InsertCell(wxHtmlCell *cell);

View File

@@ -95,19 +95,33 @@ public:
/** /**
This method is used to adjust pagebreak position. This method is used to adjust pagebreak position.
The parameter is variable that contains y-coordinate of page break 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.). (= 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) If this cell cannot be divided into two pieces (each one on another page)
then it moves the pagebreak few pixels up. 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.
Returns @true if pagebreak was modified, @false otherwise. Returns @true if pagebreak was modified, @false otherwise.
@param pagebreak
position in pixel of the pagebreak.
@param known_pagebreaks
the list of the previous pagebreaks
@param pageHeight
the height in pixel of the page drawable area
Usage: Usage:
@code @code
while (container->AdjustPagebreak(&p)) {} while (container->AdjustPagebreak(&p, kp, ph)) {}
@endcode @endcode
*/ */
virtual bool AdjustPagebreak(int* pagebreak, virtual bool AdjustPagebreak(int* pagebreak,
const wxArrayInt& known_pagebreaks) const; const wxArrayInt& known_pagebreaks,
int pageHeight) const;
/** /**
Renders the cell. Renders the cell.

View File

@@ -220,11 +220,16 @@ wxCursor wxHtmlCell::GetMouseCursor(wxHtmlWindowInterface *window) const
} }
bool wxHtmlCell::AdjustPagebreak(int *pagebreak, bool
const wxArrayInt& WXUNUSED(known_pagebreaks)) const wxHtmlCell::AdjustPagebreak(int *pagebreak,
const wxArrayInt& WXUNUSED(known_pagebreaks),
int pageHeight) const
{ {
if ((!m_CanLiveOnPagebreak) && // Notice that we always break the cells bigger than the page height here
m_PosY < *pagebreak && m_PosY + m_Height > *pagebreak) // as otherwise we wouldn't be able to break them at all.
if ( m_Height <= pageHeight &&
(!m_CanLiveOnPagebreak &&
m_PosY < *pagebreak && m_PosY + m_Height > *pagebreak) )
{ {
*pagebreak = m_PosY; *pagebreak = m_PosY;
return true; return true;
@@ -774,11 +779,13 @@ int wxHtmlContainerCell::GetIndentUnits(int ind) const
} }
bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak, bool
const wxArrayInt& known_pagebreaks) const wxHtmlContainerCell::AdjustPagebreak(int *pagebreak,
const wxArrayInt& known_pagebreaks,
int pageHeight) const
{ {
if (!m_CanLiveOnPagebreak) if (!m_CanLiveOnPagebreak)
return wxHtmlCell::AdjustPagebreak(pagebreak, known_pagebreaks); return wxHtmlCell::AdjustPagebreak(pagebreak, known_pagebreaks, pageHeight);
wxHtmlCell *c = GetFirstChild(); wxHtmlCell *c = GetFirstChild();
bool rt = false; bool rt = false;
@@ -786,7 +793,7 @@ bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak,
while (c) while (c)
{ {
if (c->AdjustPagebreak(&pbrk, known_pagebreaks)) if (c->AdjustPagebreak(&pbrk, known_pagebreaks, pageHeight))
rt = true; rt = true;
c = c->GetNext(); c = c->GetNext();
} }

View File

@@ -151,7 +151,7 @@ int wxHtmlDCRenderer::Render(int x, int y,
int pbreak, hght; int pbreak, hght;
pbreak = (int)(from + m_Height); pbreak = (int)(from + m_Height);
while (m_Cells->AdjustPagebreak(&pbreak, known_pagebreaks)) {} while (m_Cells->AdjustPagebreak(&pbreak, known_pagebreaks, m_Height)) {}
hght = pbreak - from; hght = pbreak - from;
if(to < hght) if(to < hght)
hght = to; hght = to;

View File

@@ -71,7 +71,8 @@ public:
wxHtmlPageBreakCell() {} wxHtmlPageBreakCell() {}
bool AdjustPagebreak(int* pagebreak, bool AdjustPagebreak(int* pagebreak,
const wxArrayInt& known_pagebreaks) const; const wxArrayInt& known_pagebreaks,
int pageHeight) const;
void Draw(wxDC& WXUNUSED(dc), void Draw(wxDC& WXUNUSED(dc),
int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(x), int WXUNUSED(y),
@@ -82,7 +83,10 @@ private:
wxDECLARE_NO_COPY_CLASS(wxHtmlPageBreakCell); wxDECLARE_NO_COPY_CLASS(wxHtmlPageBreakCell);
}; };
bool wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak, const wxArrayInt& known_pagebreaks) const bool
wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak,
const wxArrayInt& known_pagebreaks,
int WXUNUSED(pageHeight)) const
{ {
// When we are counting pages, 'known_pagebreaks' is non-NULL. // When we are counting pages, 'known_pagebreaks' is non-NULL.
// That's the only time we change 'pagebreak'. Otherwise, pages // That's the only time we change 'pagebreak'. Otherwise, pages