QTextDocument: Fix device scaling for QTextFrameFormat margins, padding and border

Those values must be scaled to device coordinates - otherwise borders,
margins etc. will be too small when rendered on high dpi devices
(printers etc.).

This change will add the scaling to those values.

QTextDocument::print applies 2cm margins to the root frame of a
unpaginated QTextDocument. Those margins were previously scaled to
device coordinates in order to give the correct result. But because
scaling is now done inside QTextDocumentLayout that scaling must be
removed and pixel values based on qt_defaultDpi are provided instead.

Fixes: QTBUG-78318
Change-Id: I6fe6dcc25f846341f6a2fe5df2f54baea473fdfd
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Nils Jeisecke 2016-09-01 14:26:18 +02:00 committed by Nils Jeisecke
parent 6cee284001
commit 4a240bb67e
3 changed files with 39 additions and 16 deletions
src/gui/text
tests/auto/widgets/widgets/qtextedit

View File

@ -1970,9 +1970,12 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
QRectF body = QRectF(QPointF(0, 0), d->pageSize);
QPointF pageNumberPos;
qreal sourceDpiX = qt_defaultDpiX();
qreal sourceDpiY = qt_defaultDpiY();
const qreal dpiScaleX = qreal(printer->logicalDpiX()) / sourceDpiX;
const qreal dpiScaleY = qreal(printer->logicalDpiY()) / sourceDpiY;
if (documentPaginated) {
qreal sourceDpiX = qt_defaultDpi();
qreal sourceDpiY = sourceDpiX;
QPaintDevice *dev = doc->documentLayout()->paintDevice();
if (dev) {
@ -1980,9 +1983,6 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
sourceDpiY = dev->logicalDpiY();
}
const qreal dpiScaleX = qreal(printer->logicalDpiX()) / sourceDpiX;
const qreal dpiScaleY = qreal(printer->logicalDpiY()) / sourceDpiY;
// scale to dpi
p.scale(dpiScaleX, dpiScaleY);
@ -2011,15 +2011,21 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
// copy the custom object handlers
layout->d_func()->handlers = documentLayout()->d_func()->handlers;
int dpiy = p.device()->logicalDpiY();
int margin = (int) ((2/2.54)*dpiy); // 2 cm margins
// 2 cm margins, scaled to device in QTextDocumentLayoutPrivate::layoutFrame
const int horizontalMargin = int((2/2.54)*sourceDpiX);
const int verticalMargin = int((2/2.54)*sourceDpiY);
QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
fmt.setMargin(margin);
fmt.setLeftMargin(horizontalMargin);
fmt.setRightMargin(horizontalMargin);
fmt.setTopMargin(verticalMargin);
fmt.setBottomMargin(verticalMargin);
doc->rootFrame()->setFrameFormat(fmt);
// pageNumberPos must be in device coordinates, so scale to device here
const int dpiy = p.device()->logicalDpiY();
body = QRectF(0, 0, printer->width(), printer->height());
pageNumberPos = QPointF(body.width() - margin,
body.height() - margin
pageNumberPos = QPointF(body.width() - horizontalMargin * dpiScaleX,
body.height() - verticalMargin * dpiScaleY
+ QFontMetrics(doc->defaultFont(), p.device()).ascent()
+ 5 * dpiy / 72.0);
clonedDoc->setPageSize(body.size());

View File

@ -2915,24 +2915,24 @@ QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, in
{
QTextFrameFormat fformat = f->frameFormat();
// set sizes of this frame from the format
QFixed tm = QFixed::fromReal(fformat.topMargin());
QFixed tm = QFixed::fromReal(scaleToDevice(fformat.topMargin())).round();
if (tm != fd->topMargin) {
fd->topMargin = tm;
fullLayout = true;
}
QFixed bm = QFixed::fromReal(fformat.bottomMargin());
QFixed bm = QFixed::fromReal(scaleToDevice(fformat.bottomMargin())).round();
if (bm != fd->bottomMargin) {
fd->bottomMargin = bm;
fullLayout = true;
}
fd->leftMargin = QFixed::fromReal(fformat.leftMargin());
fd->rightMargin = QFixed::fromReal(fformat.rightMargin());
QFixed b = QFixed::fromReal(fformat.border());
fd->leftMargin = QFixed::fromReal(scaleToDevice(fformat.leftMargin())).round();
fd->rightMargin = QFixed::fromReal(scaleToDevice(fformat.rightMargin())).round();
QFixed b = QFixed::fromReal(scaleToDevice(fformat.border())).round();
if (b != fd->border) {
fd->border = b;
fullLayout = true;
}
QFixed p = QFixed::fromReal(fformat.padding());
QFixed p = QFixed::fromReal(scaleToDevice(fformat.padding())).round();
if (p != fd->padding) {
fd->padding = p;
fullLayout = true;

View File

@ -1978,8 +1978,23 @@ void tst_QTextEdit::fullWidthSelection_data()
#endif
#ifdef QT_BUILD_INTERNAL
// With the fix for QTBUG-78318 scaling of documentMargin is added. The testing framework
// forces qt_defaultDpi() to always return 96 DPI. For systems where the actual DPI differs
// (typically 72 DPI) this would now cause scaling of the documentMargin when
// drawing QTextEdit into QImage. In order to avoid the need of multiple reference PNGs
// for comparison we disable the Qt::AA_Use96Dpi attribute for these tests.
struct ForceSystemDpiHelper {
ForceSystemDpiHelper() { QCoreApplication::setAttribute(Qt::AA_Use96Dpi, false); }
~ForceSystemDpiHelper() { QCoreApplication::setAttribute(Qt::AA_Use96Dpi, old); }
bool old = QCoreApplication::testAttribute(Qt::AA_Use96Dpi);
};
void tst_QTextEdit::fullWidthSelection()
{
ForceSystemDpiHelper useSystemDpi;
QFETCH(int, cursorFrom);
QFETCH(int, cursorTo);
QFETCH(QString, imageFileName);
@ -2048,6 +2063,8 @@ void tst_QTextEdit::fullWidthSelection()
#ifdef QT_BUILD_INTERNAL
void tst_QTextEdit::fullWidthSelection2()
{
ForceSystemDpiHelper useSystemDpi;
QPalette myPalette;
myPalette.setColor(QPalette::All, QPalette::HighlightedText, QColor(0,0,0,0));
myPalette.setColor(QPalette::All, QPalette::Highlight, QColor(239,221,85));