[Panel-devel] rfc: Plasma::Theme and Plasma::Svg

Zack Rusin zack at kde.org
Tue Mar 6 21:40:10 CET 2007


On Tuesday 06 March 2007 13:46, Aaron J. Seigo wrote:
<snip>
> i sat down last night and put together a design that will provide for these
> use cases to avoid duplicating this pattern over and over in the code.

Sounds like a great idea.

> Plasma::Svg will provide the following public methods:
>
> - Svg(const QString& imagePath, const QSize& size)
> 	constructor that takes a path to be used with Plasma::Theme

Right on.

> - paint( QPainter*, const QRect& )
> 	pretty obvious =)

If Svg has a native size then I think the natural paint method for it would 
simply take a point. Otherwise if you'd like to extand to the whole rect 
(which will imply rerendering on the fly anyway) I'd suggest following the 
Qt's scenario where you both accept the source rectangle and destination 
rectangle. But yeah, the QPoint method would be enough.

> - resize( int width, int height )
> 	also pretty obvious
> - resize( const QSize& size )
> 	even more obvious ;)

Neat.

> the pixmaps will be stored in a QPixmapCache for use throughout the app.
> therefore, if more than one instance of the same Plasma::Theme image path
> with the same rendering size is available, there should be no need to hit
> disk, parse or render the svg. woo! item keys will be constructed this way:
>
>   ${IMAGE_PATH}_${WIDTH}_${HEIGHT}

Damn, I have to spoil the party =) This won't work. This won't work because 
you accept an arbitrary painter and try this experiment in widget of your 
choice: 

QSvgRender r("file.svg");
QPixmap px(100, 100);
QPainter p(&px);
r.render(&p);
p.end();
p.begin(this);
p.setRenderHint(QPainter::Antialiasing);
p.scale(2, 2);
p.drawPixmap(0, 0, px);
p.end();

Spot Waldo? :) When rendering the pixmap on the widget the painter is scaled 
so we're upscaling the pixmap itself which will produce very ugly results. 
Even worse when you think about any other transformations besides scaling.
By stuffing pixmap into cache while using the filename/size as the key this is 
the behavior you'll get. The good news is that I did the code to correctly 
cache svg's in an application global fashion in QGraphicsSvgItem so it's not 
a hard problem to get it right (it does involve a bit of math though but I'm 
here :) ). I guess Plasma::Svg will be very similar to QGraphicsSvgItem 
without the QGraphicsItem inheritance and with some nice code to mix it in 
with the rest of Plasma contents. I probably should have created 
QSvgCacheRenderer or maybe even adding caching to QSvgRenderer instead of 
adding it only to QGraphicsSvgItem. Oh, well, maybe in Qt 4.4 ;)

> profiling should later show if/when/how the shared renderer should be
> instantiated and removed. e.g. it may make sense to create the renderer and
> after a certain amount of time w/out calls to resize to delete it to
> conserve memory.

Sounds like a great plan. I'm not sure how well the refcounting of pixmaps 
would work, but it's not a burning thing.

z


More information about the Panel-devel mailing list