Modified Preview Canvas

- Now the Preview can show free space around the image (the image's
corner will coincide with the center of the preview area)
- Editing objects can now be manipulated in this free space
- The editing mechanism has been split : it was completely handled in
rtengine before, now rtengine still handle the pipette's data provider,
but rtgui now handle the objects data provider.
- Bugfix: when using coarse rotate in the Editor panel, the Gradient
widgets are now correctly displayed
This commit is contained in:
Hombre
2016-01-29 22:09:56 +01:00
parent 8c3e6eab95
commit 4665b88788
22 changed files with 1413 additions and 848 deletions

View File

@@ -24,13 +24,16 @@
#include "cropwindow.h"
#include "../rtengine/dcrop.h"
#include "../rtengine/refreshmap.h"
#include "../rtengine/rt_math.h"
using namespace rtengine;
CropHandler::CropHandler ()
: zoom(10), ww(0), wh(0), cx(0), cy(0), cw(0), ch(0),
cropX(0), cropY(0), cropW(0), cropH(0), enabled(false),
cropimg(NULL), cropimgtrue(NULL), ipc(NULL), crop(NULL), listener(NULL), isLowUpdatePriority(false)
: zoom(10), ww(0), wh(0), imx(-1), imy(-1), imw(0), imh(0), cax(-1), cay(-1),
cx(0), cy(0), cw(0), ch(0), cropX(0), cropY(0), cropW(0), cropH(0), enabled(false),
cropimg(NULL), cropimgtrue(NULL), cropimg_width(0), cropimg_height(0),
initial(false), isLowUpdatePriority(false), ipc(NULL), crop(NULL),
displayHandler(NULL)
{
chi = new CropHandlerIdleHelper;
@@ -82,7 +85,7 @@ void CropHandler::newImage (StagedImageProcessor* ipc_, bool isDetailWindow)
}
EditDataProvider *editDataProvider = NULL;
CropWindow *cropWin = listener ? static_cast<CropWindow*>(listener) : NULL;
CropWindow *cropWin = displayHandler ? static_cast<CropWindow*>(displayHandler) : NULL;
if (cropWin) {
editDataProvider = cropWin->getImageArea();
@@ -126,16 +129,28 @@ double CropHandler::getFitZoom ()
void CropHandler::setZoom (int z, int centerx, int centery)
{
assert (ipc);
int x = cx + cw / 2;
int y = cy + ch / 2;
float oldScale = zoom >= 1000 ? float(zoom / 1000) : 1.f / float(zoom);
float newScale = z >= 1000 ? float(z / 1000) : 1.f / float(z);
if (centerx >= 0) {
x = centerx;
int oldcax = cax;
int oldcay = cay;
if (centerx == -1) {
cax = ipc->getFullWidth () / 2;
} else {
float distToAnchor = float(cax - centerx);
distToAnchor = distToAnchor / newScale * oldScale;
cax = centerx + int(distToAnchor);
}
if (centery >= 0) {
y = centery;
if (centery == -1) {
cay = ipc->getFullHeight () / 2;
} else {
float distToAnchor = float(cay - centery);
distToAnchor = distToAnchor / newScale * oldScale;
cay = centery + int(distToAnchor);
}
// maybe demosaic etc. if we cross the border to >100%
@@ -151,12 +166,18 @@ void CropHandler::setZoom (int z, int centerx, int centery)
ch = wh * zoom;
}
cx = x - cw / 2;
cy = y - ch / 2;
cx = cax - cw / 2;
cy = cay - ch / 2;
int oldCropX = cropX;
int oldCropY = cropY;
int oldCropW = cropW;
int oldCropH = cropH;
compDim ();
if (enabled) {
if (enabled && (oldcax != cax || oldcay != cay || oldCropX != cropX || oldCropY != cropY || oldCropW != cropW || oldCropH != cropH)) {
if (needsFullRefresh) {
ipc->startProcessing(M_HIGHQUAL);
} else {
@@ -194,11 +215,44 @@ void CropHandler::getWSize (int& w, int &h)
h = wh;
}
void CropHandler::setPosition (int x, int y, bool update_)
void CropHandler::getAnchorPosition (int& x, int& y)
{
x = cax;
y = cay;
}
cx = x;
cy = y;
void CropHandler::setAnchorPosition (int x, int y, bool update_)
{
cax = x;
cay = y;
compDim ();
if (enabled && update_) {
update ();
}
}
void CropHandler::moveAnchor (int deltaX, int deltaY, bool update_)
{
cax += deltaX;
cay += deltaY;
compDim ();
if (enabled && update_) {
update ();
}
}
void CropHandler::centerAnchor (bool update_)
{
assert (ipc);
// Computes the crop's size and position given the anchor's position and display size
cax = ipc->getFullWidth() / 2;
cay = ipc->getFullHeight() / 2;
compDim ();
@@ -280,11 +334,11 @@ int createpixbufs (void* data)
ch->cimg.unlock ();
if (ch->listener) {
ch->listener->cropImageUpdated ();
if (ch->displayHandler) {
ch->displayHandler->cropImageUpdated ();
if (ch->initial) {
ch->listener->initialImageArrived ();
ch->displayHandler->initialImageArrived ();
ch->initial = false;
}
}
@@ -365,7 +419,7 @@ bool CropHandler::getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip)
void CropHandler::update ()
{
if (crop) {
if (crop && enabled) {
// crop->setWindow (cropX, cropY, cropW, cropH, zoom>=1000 ? 1 : zoom); --> we use the "getWindow" hook instead of setting the size before
crop->setListener (this);
cropPixbuf.clear ();
@@ -428,41 +482,78 @@ void CropHandler::getFullImageSize (int& w, int& h)
void CropHandler::compDim ()
{
assert (ipc && displayHandler);
cropX = cx;
cropY = cy;
cropW = cw;
cropH = ch;
// Computes the crop's size and position given the anchor's position and display size
cutRectToImgBounds (cropX, cropY, cropW, cropH);
}
int fullW = ipc->getFullWidth();
int fullH = ipc->getFullHeight();
int imgX = -1, imgY = -1;
//int scaledFullW, scaledFullH;
int scaledCAX, scaledCAY;
int wwImgSpace;
int whImgSpace;
void CropHandler::cutRectToImgBounds (int& x, int& y, int& w, int& h)
{
cax = rtengine::LIM(cax, 0, fullW-1);
cay = rtengine::LIM(cay, 0, fullH-1);
if (ipc) {
if (w > ipc->getFullWidth()) {
w = ipc->getFullWidth();
}
if (h > ipc->getFullHeight()) {
h = ipc->getFullHeight();
}
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
if (x + w >= ipc->getFullWidth()) {
x = ipc->getFullWidth() - w;
}
if (y + h >= ipc->getFullHeight()) {
y = ipc->getFullHeight() - h;
}
if (zoom >= 1000) {
wwImgSpace = int(float(ww) / float(zoom/1000) + 0.5f);
whImgSpace = int(float(wh) / float(zoom/1000) + 0.5f);
//scaledFullW = fullW * (zoom/1000);
//scaledFullH = fullH * (zoom/1000);
scaledCAX = cax * (zoom/1000);
scaledCAY = cay * (zoom/1000);
} else {
wwImgSpace = int(float(ww) * float(zoom) + 0.5f);
whImgSpace = int(float(wh) * float(zoom) + 0.5f);
//scaledFullW = fullW / zoom;
//scaledFullH = fullH / zoom;
scaledCAX = cax / zoom;
scaledCAY = cay / zoom;
}
imgX = ww / 2 - scaledCAX;
if (imgX < 0) {
imgX = 0;
}
imgY = wh / 2 - scaledCAY;
if (imgY < 0) {
imgY = 0;
}
cropX = cax - (wwImgSpace/2);
cropY = cay - (whImgSpace/2);
cropW = wwImgSpace;
cropH = whImgSpace;
if (cropX + cropW > fullW) {
cropW = fullW - cropX;
}
if (cropY + cropH > fullH) {
cropH = fullH - cropY;
}
if (cropX < 0) {
cropW += cropX;
cropX = 0;
}
if (cropY < 0) {
cropH += cropY;
cropY = 0;
}
// Should be good already, but this will correct eventual rounding error
if (cropW > fullW) {
cropW = fullW;
}
if (cropH > fullH) {
cropH = fullH;
}
displayHandler->setDisplayPosition(imgX, imgY);
}