20
20
#include < QPainter>
21
21
#include < QStyleOptionGraphicsItem>
22
22
23
+ #define CACHE_SIZE_LIMIT 5000
24
+
23
25
QgsLayoutItem::QgsLayoutItem ( QgsLayout *layout )
24
26
: QgsLayoutObject( layout )
25
27
, QGraphicsRectItem( 0 )
@@ -44,23 +46,89 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it
44
46
}
45
47
46
48
// TODO - remember to disable saving/restoring on graphics view!!
47
- painter->save ();
48
- preparePainter ( painter );
49
49
50
50
if ( shouldDrawDebugRect () )
51
51
{
52
52
drawDebugRect ( painter );
53
+ return ;
54
+ }
55
+
56
+ double destinationDpi = itemStyle->matrix .m11 () * 25.4 ;
57
+ bool useImageCache = true ;
58
+
59
+ if ( useImageCache )
60
+ {
61
+ double widthInPixels = boundingRect ().width () * itemStyle->matrix .m11 ();
62
+ double heightInPixels = boundingRect ().height () * itemStyle->matrix .m11 ();
63
+
64
+ // limit size of image for better performance
65
+ double scale = 1.0 ;
66
+ if ( widthInPixels > CACHE_SIZE_LIMIT || heightInPixels > CACHE_SIZE_LIMIT )
67
+ {
68
+ if ( widthInPixels > heightInPixels )
69
+ {
70
+ scale = widthInPixels / CACHE_SIZE_LIMIT;
71
+ widthInPixels = CACHE_SIZE_LIMIT;
72
+ heightInPixels /= scale;
73
+ }
74
+ else
75
+ {
76
+ scale = heightInPixels / CACHE_SIZE_LIMIT;
77
+ heightInPixels = CACHE_SIZE_LIMIT;
78
+ widthInPixels /= scale;
79
+ }
80
+ destinationDpi = destinationDpi / scale;
81
+ }
82
+
83
+ if ( !mItemCachedImage .isNull () && qgsDoubleNear ( mItemCacheDpi , destinationDpi ) )
84
+ {
85
+ // can reuse last cached image
86
+ QgsRenderContext context = QgsLayoutUtils::createRenderContextForMap ( nullptr , painter, destinationDpi );
87
+ painter->save ();
88
+ preparePainter ( painter );
89
+ double cacheScale = destinationDpi / mItemCacheDpi ;
90
+ painter->scale ( cacheScale / context.scaleFactor (), cacheScale / context.scaleFactor () );
91
+ painter->drawImage ( boundingRect ().x () * context.scaleFactor () / cacheScale,
92
+ boundingRect ().y () * context.scaleFactor () / cacheScale, mItemCachedImage );
93
+ painter->restore ();
94
+ return ;
95
+ }
96
+ else
97
+ {
98
+ mItemCacheDpi = destinationDpi;
99
+
100
+ mItemCachedImage = QImage ( widthInPixels, heightInPixels, QImage::Format_ARGB32 );
101
+ mItemCachedImage .fill ( Qt::transparent );
102
+ mItemCachedImage .setDotsPerMeterX ( 1000 * destinationDpi * 25.4 );
103
+ mItemCachedImage .setDotsPerMeterY ( 1000 * destinationDpi * 25.4 );
104
+ QPainter p ( &mItemCachedImage );
105
+
106
+ preparePainter ( &p );
107
+ QgsRenderContext context = QgsLayoutUtils::createRenderContextForMap ( nullptr , &p, destinationDpi );
108
+ // painter is already scaled to dots
109
+ // need to translate so that item origin is at 0,0 in painter coordinates (not bounding rect origin)
110
+ p.translate ( -boundingRect ().x () * context.scaleFactor (), -boundingRect ().y () * context.scaleFactor () );
111
+ draw ( context, itemStyle );
112
+ p.end ();
113
+
114
+ painter->save ();
115
+ // scale painter from mm to dots
116
+ painter->scale ( 1.0 / context.scaleFactor (), 1.0 / context.scaleFactor () );
117
+ painter->drawImage ( boundingRect ().x () * context.scaleFactor (),
118
+ boundingRect ().y () * context.scaleFactor (), mItemCachedImage );
119
+ painter->restore ();
120
+ }
53
121
}
54
122
else
55
123
{
56
- double destinationDpi = itemStyle->matrix .m11 () * 25.4 ;
124
+ // no caching or flattening
125
+ painter->save ();
57
126
QgsRenderContext context = QgsLayoutUtils::createRenderContextForMap ( nullptr , painter, destinationDpi );
58
127
// scale painter from mm to dots
59
128
painter->scale ( 1.0 / context.scaleFactor (), 1.0 / context.scaleFactor () );
60
129
draw ( context, itemStyle );
130
+ painter->restore ();
61
131
}
62
-
63
- painter->restore ();
64
132
}
65
133
66
134
void QgsLayoutItem::setReferencePoint ( const QgsLayoutItem::ReferencePoint &point )
0 commit comments