From fc3733cba4652f2b8930c66665103fcb20874735 Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Tue, 18 Nov 2014 14:58:34 +0200 Subject: [PATCH] Fix drawing of background for multipage QTextTable cells Task-number: QTBUG-31330 Change-Id: I0103919ee2864b7cd8bed41e6d6fe4ac5b84142e Reviewed-by: Lars Knoll --- src/gui/text/qtextdocumentlayout.cpp | 39 ++++-- .../gui/text/qtexttable/tst_qtexttable.cpp | 115 ++++++++++++++++++ 2 files changed, 146 insertions(+), 8 deletions(-) diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index 163d51aec2..1ddc9141af 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -1115,6 +1115,13 @@ void QTextDocumentLayoutPrivate::drawTableCell(const QRectF &cellRect, QPainter const QFixed leftPadding = td->leftPadding(fmt); const QFixed topPadding = td->topPadding(fmt); + qreal topMargin = (td->effectiveTopMargin + td->cellSpacing + td->border).toReal(); + qreal bottomMargin = (td->effectiveBottomMargin + td->cellSpacing + td->border).toReal(); + + const int headerRowCount = qMin(table->format().headerRowCount(), table->rows() - 1); + if (r >= headerRowCount) + topMargin += td->headerHeight.toReal(); + if (td->border != 0) { const QBrush oldBrush = painter->brush(); const QPen oldPen = painter->pen(); @@ -1142,13 +1149,6 @@ void QTextDocumentLayoutPrivate::drawTableCell(const QRectF &cellRect, QPainter break; } - qreal topMargin = (td->effectiveTopMargin + td->cellSpacing + td->border).toReal(); - qreal bottomMargin = (td->effectiveBottomMargin + td->cellSpacing + td->border).toReal(); - - const int headerRowCount = qMin(table->format().headerRowCount(), table->rows() - 1); - if (r >= headerRowCount) - topMargin += td->headerHeight.toReal(); - drawBorder(painter, borderRect, topMargin, bottomMargin, border, table->format().borderBrush(), cellBorder); @@ -1159,7 +1159,30 @@ void QTextDocumentLayoutPrivate::drawTableCell(const QRectF &cellRect, QPainter const QBrush bg = cell.format().background(); const QPointF brushOrigin = painter->brushOrigin(); if (bg.style() != Qt::NoBrush) { - fillBackground(painter, cellRect, bg, cellRect.topLeft()); + const qreal pageHeight = document->pageSize().height(); + const int topPage = pageHeight > 0 ? static_cast(cellRect.top() / pageHeight) : 0; + const int bottomPage = pageHeight > 0 ? static_cast((cellRect.bottom()) / pageHeight) : 0; + + if (topPage == bottomPage) + fillBackground(painter, cellRect, bg, cellRect.topLeft()); + else { + for (int i = topPage; i <= bottomPage; ++i) { + QRectF clipped = cellRect.toRect(); + + if (topPage != bottomPage) { + const qreal top = qMax(i * pageHeight + topMargin, cell_context.clip.top()); + const qreal bottom = qMin((i + 1) * pageHeight - bottomMargin, cell_context.clip.bottom()); + + clipped.setTop(qMax(clipped.top(), top)); + clipped.setBottom(qMin(clipped.bottom(), bottom)); + + if (clipped.bottom() <= clipped.top()) + continue; + + fillBackground(painter, clipped, bg, cellRect.topLeft()); + } + } + } if (bg.style() > Qt::SolidPattern) painter->setBrushOrigin(cellRect.topLeft()); diff --git a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp index 9cc092d8ab..e542e8f3f7 100644 --- a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp +++ b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp @@ -44,6 +44,11 @@ #ifndef QT_NO_WIDGETS #include #endif +#ifndef QT_NO_PRINTER +#include +#include +#include +#endif typedef QList IntList; @@ -96,6 +101,9 @@ private slots: void QTBUG11282_insertBeforeMergedEnding(); #endif void QTBUG22011_insertBeforeRowSpan(); +#ifndef QT_NO_PRINTER + void QTBUG31330_renderBackground(); +#endif private: QTextTable *create2x2Table(); @@ -1024,5 +1032,112 @@ void tst_QTextTable::QTBUG22011_insertBeforeRowSpan() QCOMPARE(table->columns(), 6); } +#ifndef QT_NO_PRINTER +namespace { +class QTBUG31330_PaintDevice : public QPagedPaintDevice +{ +public: + class PaintEngine : public QPaintEngine + { + public: + QList rects; + + PaintEngine() + : QPaintEngine(0) + {} + virtual Type type() const + { + return User; + } + virtual bool begin(QPaintDevice *) + { + return true; + } + virtual bool end() + { + return true; + } + virtual void updateState(const QPaintEngineState &) + {} + virtual void drawRects(const QRect *, int) + {} + virtual void drawRects(const QRectF *r, int) + { + if (painter()->brush() == QBrush(Qt::green)) + { + rects.append(*r); + } + } + virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) + {} + }; + + int pages; + QPaintEngine* engine; + + QTBUG31330_PaintDevice(QPaintEngine* engine) + : pages(1), engine(engine) + { + QPageLayout layout = pageLayout(); + layout.setUnits(QPageLayout::Point); + setPageLayout(layout); + } + virtual int metric(PaintDeviceMetric metric) const + { + if (PdmDevicePixelRatio == metric) + return 1; + if (PdmDpiY == metric) + return 96; + if (PdmDpiX == metric) + return 96; + if (PdmHeight == metric) + return 1000; + if (PdmWidth == metric) + return 700; + return 900; + } + virtual QPaintEngine *paintEngine() const + { + return engine; + } + bool newPage() + { + ++pages; + return true; + } +}; +} + +void tst_QTextTable::QTBUG31330_renderBackground() +{ + QTextDocument doc; + QTextCursor cursor(&doc); + QTextTable* table = cursor.insertTable(4, 2); + + QTextTableCell cell = table->cellAt(3, 0); + + QTextCharFormat cellFormat = cell.format(); + cellFormat.setBackground(QBrush(Qt::green)); + cell.setFormat(cellFormat); + + QTextCursor tc = cell.firstCursorPosition(); + for (int i = 0; i < 60; ++i) { + tc.insertBlock(); + } + QTBUG31330_PaintDevice::PaintEngine engine; + QTBUG31330_PaintDevice paintDevice(&engine); + paintDevice.setPageSize(QPagedPaintDevice::A4); + doc.print(&paintDevice); + + QVERIFY(paintDevice.pages >= 2); + QCOMPARE(engine.rects.count(), paintDevice.pages); + for (int i = 0; i < engine.rects.count(); ++i) { + QRectF rect = engine.rects[i]; + QVERIFY(rect.top() > 0); + QVERIFY(rect.bottom() < 1000); + } +} +#endif + QTEST_MAIN(tst_QTextTable) #include "tst_qtexttable.moc"