Reputation: 22346
I have a QML Canvas
that can be scaled (more specifically it is a child of an object that is scaled), and scaling it causes it's output to become aliased. This is occurring because the Canvas
uses its size to determine the framebuffer size.
What I actually want to happen is for the framebuffer to track the Canvas
size multiplied by its scale i.e. its on-screen pixel size.
My initial idea was to set the canvasWindow
and canvasSize
to the scaled size, but it seems that there is no decoupling between the Canvas
'pixel' size and the framebuffer's because the whole image began to render beyond the bounds of the Canvas
.
In this example the black ring in rendered inside a Canvas
that is parented to the scaled grey rectangle:
Canvas {
id: borderCanvas
anchors {
fill: parent
margins: 4
}
antialiasing: true
canvasWindow: Qt.rect( 0,0,
width * parent.scale,
height * parent.scale );
canvasSize: Qt.size( width * parent.scale,
height * parent.scale );
onCanvasWindowChanged: {
requestPaint();
}
onPaint: {
var ctx = getContext( "2d" );
ctx.save();
ctx.clearRect( 0, 0, canvasWindow.width, canvasWindow.height );
ctx.strokeStyle = Sy_application_qml.paletteObject.buttonText;
ctx.lineWidth = 4 * parent.scale;
ctx.beginPath();
ctx.arc( canvasWindow.width / 2,
canvasWindow.height / 2,
( canvasWindow.width / 2 ) - ctx.lineWidth,
0,
Math.PI * 2 );
ctx.stroke();
ctx.restore();
}
}
So is there anyway to set the Canvas
framebuffer size such that scaling transformations do not affect it?
If I leave canvasWindow
at the default, and just update the canvasSize
then I don't get the framebuffer rendering beyond the Canvas
bounds - but the output is still at a low resolution so canvasSize
still isn't actually changing the
size of the framebuffer...
Upvotes: 2
Views: 2365
Reputation: 22346
The solution was to inverse the inherited scale transformation on the Canvas
, and then increase the height and width by the scale amount. This leaves the the Canvas
the same size on the screen but with a framebuffer to match.
Canvas {
id: borderCanvas
anchors {
top: parent.top
left: parent.left
margins: 4
}
property real viewScale: base.parent.scale
scale: 1.0 / viewScale
height: ( parent.height - ( anchors.margins * 2 ) ) * viewScale
width: ( parent.width - ( anchors.margins * 2 ) ) * viewScale
antialiasing: true
transformOrigin: Item.TopLeft
onPaint: {
var ctx = getContext( "2d" );
ctx.save();
ctx.clearRect( 0, 0, width, height );
ctx.strokeStyle = Sy_application_qml.paletteObject.buttonText;
ctx.lineWidth = 4 * viewScale;
ctx.beginPath();
ctx.arc( width / 2,
height / 2,
( width / 2 ) - ctx.lineWidth,
0,
Math.PI * 2 );
ctx.stroke();
ctx.restore();
}
}
Upvotes: 4