diff --git a/ui/pageview.cpp b/ui/pageview.cpp index d96a0906b02b2a6b6da15ae0c7145a84c33d4f67..77b4f324513566998a8e554b20cdfc10348f6715 100644 --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@ -3500,55 +3500,24 @@ void PageView::drawDocumentOnPainter( const QRect & contentsRect, QPainter * p ) else backColor = viewport()->palette().color( QPalette::Dark ); - // when checking if an Item is contained in contentsRect, instead of - // growing PageViewItems rects (for keeping outline into account), we - // grow the contentsRect - QRect checkRect = contentsRect; - checkRect.adjust( -3, -3, 1, 1 ); - // create a region from which we'll subtract painted rects QRegion remainingArea( contentsRect ); + // This loop draws the actual pages // iterate over all items painting the ones intersecting contentsRect for ( const PageViewItem * item : qAsConst( d->items ) ) { // check if a piece of the page intersects the contents rect - if ( !item->isVisible() || !item->croppedGeometry().intersects( checkRect ) ) + if ( !item->isVisible() || !item->croppedGeometry().intersects( contentsRect ) ) continue; // get item and item's outline geometries - QRect itemGeometry = item->croppedGeometry(), - outlineGeometry = itemGeometry; - outlineGeometry.adjust( -1, -1, 3, 3 ); + QRect itemGeometry = item->croppedGeometry(); // move the painter to the top-left corner of the real page p->save(); p->translate( itemGeometry.left(), itemGeometry.top() ); - // draw the page outline (black border and 2px bottom-right shadow) - if ( !itemGeometry.contains( contentsRect ) ) - { - int itemWidth = itemGeometry.width(), - itemHeight = itemGeometry.height(); - // draw simple outline - p->setPen( Qt::black ); - p->drawRect( -1, -1, itemWidth + 1, itemHeight + 1 ); - // draw bottom/right gradient - static const int levels = 2; - int r = backColor.red() / (levels + 2) + 6, - g = backColor.green() / (levels + 2) + 6, - b = backColor.blue() / (levels + 2) + 6; - for ( int i = 0; i < levels; i++ ) - { - p->setPen( QColor( r * (i+2), g * (i+2), b * (i+2) ) ); - p->drawLine( i, i + itemHeight + 1, i + itemWidth + 1, i + itemHeight + 1 ); - p->drawLine( i + itemWidth + 1, i, i + itemWidth + 1, i + itemHeight ); - p->setPen( backColor ); - p->drawLine( -1, i + itemHeight + 1, i - 1, i + itemHeight + 1 ); - p->drawLine( i + itemWidth + 1, -1, i + itemWidth + 1, i - 1 ); - } - } - // draw the page using the PagePainter with all flags active if ( contentsRect.intersects( itemGeometry ) ) { @@ -3567,15 +3536,70 @@ void PageView::drawDocumentOnPainter( const QRect & contentsRect, QPainter * p ) } // remove painted area from 'remainingArea' and restore painter - remainingArea -= outlineGeometry.intersected( contentsRect ); + remainingArea -= itemGeometry; p->restore(); } - // fill with background color the unpainted area - const QVector &backRects = remainingArea.rects(); - int backRectsNumber = backRects.count(); - for ( int jr = 0; jr < backRectsNumber; jr++ ) - p->fillRect( backRects[ jr ], backColor ); + // fill the visible area around the page with the background color + for (const QRect& backRect : remainingArea ) + p->fillRect( backRect, backColor ); + + // take outline and shadow into account when testing whether a repaint is necessary + auto dpr = devicePixelRatioF(); + QRect checkRect = contentsRect; + checkRect.adjust( -3, -3, 1, 1 ); + + // Method to linearly interpolate between black (=(0,0,0), omitted) and the background color + auto interpolateColor = [&backColor]( double t ) + { + return QColor( t*backColor.red(), t*backColor.green(), t*backColor.blue() ); + }; + + // width of the shadow in device pixels + static const int shadowWidth = 2*dpr; + + // iterate over all items painting a black outline and a simple bottom/right gradient + for ( const PageViewItem * item : qAsConst( d->items ) ) + { + // check if a piece of the page intersects the contents rect + if ( !item->isVisible() || !item->croppedGeometry().intersects( checkRect ) ) + continue; + + // get item and item's outline geometries + QRect itemGeometry = item->croppedGeometry(); + + // move the painter to the top-left corner of the real page + p->save(); + p->translate( itemGeometry.left(), itemGeometry.top() ); + + // draw the page outline (black border and bottom-right shadow) + if ( !itemGeometry.contains( contentsRect ) ) + { + int itemWidth = itemGeometry.width(); + int itemHeight = itemGeometry.height(); + // draw simple outline + QPen pen( Qt::black ); + pen.setWidth(0); + p->setPen( pen ); + + QRectF outline( -1.0/dpr, -1.0/dpr, itemWidth + 1.0/dpr, itemHeight + 1.0/dpr ); + p->drawRect( outline ); + + // draw bottom/right gradient + for ( int i = 1; i <= shadowWidth; i++ ) + { + pen.setColor( interpolateColor( double(i)/( shadowWidth+1 ) ) ); + p->setPen( pen ); + QPointF left( (i-1)/dpr, itemHeight + i/dpr ); + QPointF up( itemWidth + i/dpr, (i-1)/dpr ); + QPointF corner( itemWidth + i/dpr, itemHeight + i/dpr); + p->drawLine( left, corner ); + p->drawLine( up, corner ); + } + } + + p->restore(); + } } void PageView::updateItemSize( PageViewItem * item, int colWidth, int rowHeight )