Fix drawing of background for multipage QTextTable cells

Task-number: QTBUG-31330
Change-Id: I0103919ee2864b7cd8bed41e6d6fe4ac5b84142e
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Joni Poikelin 2014-11-18 14:58:34 +02:00
parent f9c70128bb
commit fc3733cba4
2 changed files with 146 additions and 8 deletions

View File

@ -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<int>(cellRect.top() / pageHeight) : 0;
const int bottomPage = pageHeight > 0 ? static_cast<int>((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());

View File

@ -44,6 +44,11 @@
#ifndef QT_NO_WIDGETS
#include <qtextedit.h>
#endif
#ifndef QT_NO_PRINTER
#include <QPagedPaintDevice>
#include <QPainter>
#include <QPaintEngine>
#endif
typedef QList<int> 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<QRectF> 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"