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