Battery applet and KIcon

Zack Rusin zack at kde.org
Sun Feb 14 22:52:16 CET 2010


On Sunday 14 February 2010 15:33:04 Marco Martin wrote:
> for a really generic thing, i fear something would be needed at the level
>  of QSvg.
> and always will have some approximate results.
> QSvg should do something like:
> -when rendering a shape, always adjust its bounding rect to the pixel grid.
> -if it has a border adjust the bounding rect of the border instead
> would probably yeld slightly better, even if not perfect results.

I'm not sure if I see what you're saying because it seems that you're 
advocating doing the opposite of what you're trying to do =)
You can't snap to a pixel grid, that's because SVG's aren't created on a pixel 
grid, e.g if the viewport is 0.5, 0.5 to 31.5, 31.5 and we snap it to 1,1, 
32,32 then the exact problem that you're trying to prevent will happen (pixel 
bleeding). SVG's, especially in KDE (due to combining multiple renderings in 
one SVG file) virtually never have integer coordinates. 

I think the problem that you're trying to prevent could be reformulated as 
"don't render SVG's in non-native viewports" as the native viewport is likely 
the only one that the SVG is definitely looking good at. And for that Plasma 
does have enough info and doesn't need QtSvg to do anything. The idea is that 
the rendering bounds need to be even uniform multiples of the scaling factor.

In a email hacking form:

//to and from are /always/ 0 <= val <= 1
qreal closestDistance(qreal to, qreal from)
{
	qreal a = to - from;
	if (qFuzzyCompare(to, from))
		return 0;
	else if ( to > from ) {
		qreal b = to - from - 1;
		return (qAbs(a) > qAbs(b)) ?  b : a;
	} else {
		qreal b = 1 + to - from;
		return (qAbs(a) > qAbs(b)) ? b : a;
	}	
}
QRectF makeUniform(const QRect &orig,
		const QRect &dst)
{
	QRectF res(dst);
	qreal div_w = dst.width() / orig.width();
	qreal div_h = dst.height() / orig.height();

	qreal div_x = dst.x() / orig.x();
	qreal div_y = dst.y() / orig.y();

	//horizontal snap
	if (!qFuzzyIsNull(div_x) && !qFuzzyCompare(div_w, div_x)) {
		qreal rem_orig = orig.x() - (floor(orig.x()));
		qreal rem_dst = dst.x() - (floor(dst.x()));
		qreal offset = closestDistance(rem_dst, rem_orig);
		res.adjust(offset/div_w, 0, 0, 0);
	}
	//vertical snap
	if (!qFuzzyIsNull(div_y) && !qFuzzyCompare(div_h, div_y)) {
		qreal rem_orig = orig.y() - (floor(orig.y()));
		qreal rem_dst = dst.y() - (floor(dst.y()));
		qreal offset = closestDistance(rem_dst, rem_orig);
		res.adjust(0, offset/div_h, 0, 0);
	}
}

res.adjust might not need the division of offset by respectively div_w and 
div_h but it probably would look better with divisor (verification would be 
needed).

and then in Plasma::Theme::paint
you'd call makeUniform with contentsRect and QSvgRenderer::boundsForElement 
for the element that you're rendering to get the properly adjusted 
contentsRect. 

I *think* that should sharpen up all SVG rendering in Plasma especially at 
smaller resolution, but someone would have to test this.

The other solution would be to impose restrictions on viewport coordinates 
inside the actual SVG's that plasma is using (while lot less flexible, would 
likely offer better results), e.g. always integer based.

z


More information about the Plasma-devel mailing list