fix(StatusImageCrop): fix wrong initial image fit

The initial fit was computed for the square crop-window

updates: 5118
This commit is contained in:
Stefan 2022-05-20 23:05:19 +03:00 committed by Michał Cieślak
parent b9088427d7
commit 13b41cbd00
2 changed files with 41 additions and 52 deletions

View File

@ -82,12 +82,7 @@ Item {
\qmlproperty rect StatusImageCropPanel::cropRect
\sa StatusImageCrop::cropRect
*/
property alias cropRect: cropEditor.cropRect
/*!
\qmlproperty rect StatusImageCropPanel::cropRect
\sa StatusImageCrop::cropRect
*/
readonly property alias cropWindow: cropEditor.cropWindow
readonly property alias cropRect: cropEditor.cropRect
/*!
\qmlproperty real StatusImageCrop::scrollZoomFactor
How fast is image scaled (zoomed) when using mouse scroll
@ -116,16 +111,11 @@ Item {
QtObject {
id: d
readonly property int referenceWindowWidth: 1000
function updateAspectRatio(newAR) {
// Keep width and adjust height
const eW = cropEditor.cropRect.width
const w = (eW <= 0) ? cropEditor.sourceSize.width : eW
const h = w/newAR
const c = (eW <= 0)
? Qt.point(cropEditor.sourceSize.width/2, cropEditor.sourceSize.height/2)
: Qt.point(cropEditor.cropRect.x + w/2, cropEditor.cropRect.y + cropEditor.cropRect.height/2)
const nR = Qt.rect(c.x - w/2, c.y-h/2, w, h)
cropEditor.setCropRect(nR)
if(root.sourceSize.width === 0 || root.sourceSize.height === 0)
return
cropEditor.setCropRect(cropEditor.fillContentInWindow(root.sourceSize, Qt.size(referenceWindowWidth, referenceWindowWidth / root.aspectRatio)))
}
}

View File

@ -123,12 +123,6 @@ Item {
e.g. to set the crop window to show and match image's AR use Qt.rect(0, 0, sourceSize.width, sourceSize.height)
*/
readonly property rect cropRect: d.cropRect
/*!
\qmlproperty rect StatusImageCrop::cropRect
The position and zis of the crop rectangle in item's space; without extra spacing
*/
readonly property alias cropWindow: d.cropWindow
/*!
\qmlproperty real StatusImageCrop::aspectRatio
*/
@ -146,7 +140,7 @@ Item {
\sa StatusImageCrop::source
*/
readonly property size sourceSize: mainImage.sourceSize
readonly property alias sourceSize: mainImage.sourceSize
/*!
\qmlproperty real StatusImageCrop::scrToImgScale
@ -218,7 +212,7 @@ Item {
function getZoomRect(scale /*real*/) {
const oldCenter = root.rectCenter(root.cropRect)
const inflatedRect = root.inflateRectBy(root.minimumCropRect(), 1/scale)
const inflatedRect = root.inflateRectBy(d.minimumCropRect(), 1/scale)
return root.recenterRect(inflatedRect, oldCenter);
}
@ -248,44 +242,34 @@ Item {
return Qt.rect(newCenter.x - target.width/2 , newCenter.y - target.height/2, target.width, target.height)
}
//> cropRect for minimum zoom: 1.0
function minimumCropRect() {
const sourceAR = root.sourceSize.width/root.sourceSize.height
const widthBound = sourceAR > root.aspectRatio
const minCropSize = widthBound ? Qt.size(root.sourceSize.width, root.sourceSize.width/root.aspectRatio)
: Qt.size(root.sourceSize.height * root.aspectRatio, root.sourceSize.height)
let res = Qt.rect(widthBound ? 0 : -(root.sourceSize.width - minCropSize.width)/2, // x
widthBound ? -(root.sourceSize.height - minCropSize.height)/2 : 0, // y
minCropSize.width, minCropSize.height)
return res
function fillContentInWindow(contentSize /*size*/, windowSize /*size*/) {
const contentAR = contentSize.width/contentSize.height
const windowAR = windowSize.width/windowSize.height
const heightBound = contentAR > windowAR
if(heightBound) {
const wWidth = contentSize.height * windowAR
const horizontalBorder = (contentSize.width - wWidth)/2
return Qt.rect(horizontalBorder, 0, wWidth, contentSize.height)
}
else {
const wHeight = contentSize.width / windowAR
const verticalBorder = (contentSize.height - wHeight)/2
return Qt.rect(0, verticalBorder, contentSize.width, wHeight)
}
}
QtObject {
id: d
property rect cropRect: fillContentInSquaredWindow(root.sourceSize)
property rect cropRect
onCropRectChanged: windowRect.requestPaint()
readonly property real zoomToFill: {
const rectangle = fillContentInSquaredWindow(root.sourceSize)
const rectangle = root.fillContentInWindow(root.sourceSize, d.cropWindowSize)
return d.currentZoom(root.sourceSize, Qt.size(rectangle.width, rectangle.height))
}
property rect cropWindow
// Probably called from render thread, run async
signal updateCropWindow(rect newRect)
onUpdateCropWindow: cropWindow = newRect
function fillContentInSquaredWindow(c /*size*/) {
if(c.width > c.height) {
const border = (c.width - c.height)/2
return Qt.rect(border, 0, c.height, c.height)
}
else {
const border = (c.height - c.width)/2
return Qt.rect(0, border, c.width, c.width)
}
}
property size cropWindowSize: Qt.size(d.cropRect.width, d.cropRect.height)
//> 1.0 is the content represented by w fully inscribed in c
function currentZoom(c /*size*/, w /*size*/) {
@ -293,10 +277,26 @@ Item {
const hScale = c.height/w.height
return Math.max(wScale, hScale)
}
//> cropRect for minimum zoom: 1.0
function minimumCropRect() {
const sourceAR = root.sourceSize.width/root.sourceSize.height
const widthBound = sourceAR > root.aspectRatio
const minCropSize = widthBound ? Qt.size(root.sourceSize.width, root.sourceSize.width/root.aspectRatio)
: Qt.size(root.sourceSize.height * root.aspectRatio, root.sourceSize.height)
let res = Qt.rect(widthBound ? 0 : -(root.sourceSize.width - minCropSize.width)/2, // x
widthBound ? -(root.sourceSize.height - minCropSize.height)/2 : 0, // y
minCropSize.width, minCropSize.height)
return res
}
}
onWindowStyleChanged: windowRect.requestPaint()
onSourceSizeChanged: d.cropRect = d.fillContentInSquaredWindow(sourceSize)
onRadiusChanged: windowRect.requestPaint()
onSourceSizeChanged: {
if(d.cropWindowSize.width > 0 && d.cropWindowSize.height > 0)
d.cropRect = root.fillContentInWindow(sourceSize, d.cropWindowSize)
}
Canvas {
id: windowRect
@ -330,7 +330,6 @@ Item {
ctx.roundedRect(cW.x, cW.y, cW.width, cW.height, root.radius, root.radius)
ctx.fill()
ctx.restore()
d.updateCropWindow(cW)
}
}