From 4665b88788528e1792aae5be435b421abb7ad1f4 Mon Sep 17 00:00:00 2001 From: Hombre Date: Fri, 29 Jan 2016 22:09:56 +0100 Subject: [PATCH] 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 --- rtengine/CMakeLists.txt | 2 +- rtengine/curves.h | 2 +- rtengine/dcrop.cc | 57 +- rtengine/dcrop.h | 15 +- rtengine/improcfun.cc | 32 +- rtengine/improcfun.h | 8 +- rtengine/{editbuffer.cc => pipettebuffer.cc} | 135 +---- rtengine/{editbuffer.h => pipettebuffer.h} | 57 +- rtgui/crophandler.cc | 195 +++++-- rtgui/crophandler.h | 32 +- rtgui/cropwindow.cc | 398 +++++++------- rtgui/cropwindow.h | 40 +- rtgui/edit.cc | 272 ++++++--- rtgui/edit.h | 107 +++- rtgui/gradient.cc | 185 ++++--- rtgui/gradient.h | 3 +- rtgui/imagearea.cc | 74 ++- rtgui/imageareapanel.cc | 8 +- rtgui/previewhandler.cc | 22 +- rtgui/previewwindow.cc | 2 + rtgui/toolpanelcoord.cc | 70 ++- tools/coordinate_system.svg | 545 +++++++++++++++---- 22 files changed, 1413 insertions(+), 848 deletions(-) rename rtengine/{editbuffer.cc => pipettebuffer.cc} (50%) rename rtengine/{editbuffer.h => pipettebuffer.h} (57%) diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index bf9ec442b..682d6ff3f 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -11,7 +11,7 @@ set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagona dfmanager.cc ffmanager.cc gauss.cc rawimage.cc image8.cc image16.cc imagefloat.cc imagedata.cc imageio.cc improcfun.cc init.cc dcrop.cc loadinitial.cc procparams.cc rawimagesource.cc demosaic_algos.cc shmap.cc simpleprocess.cc refreshmap.cc fast_demo.cc amaze_demosaic_RT.cc CA_correct_RT.cc cfa_linedn_RT.cc green_equil_RT.cc hilite_recon.cc expo_before_b.cc - stdimagesource.cc myfile.cc iccjpeg.cc hlmultipliers.cc improccoordinator.cc editbuffer.cc coord.cc + stdimagesource.cc myfile.cc iccjpeg.cc hlmultipliers.cc improccoordinator.cc pipettebuffer.cc coord.cc processingjob.cc rtthumbnail.cc utils.cc labimage.cc slicer.cc cieimage.cc iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc ipvibrance.cc imagedimensions.cc jpeg_memsrc.cc jdatasrc.cc iimage.cc diff --git a/rtengine/curves.h b/rtengine/curves.h index e55d7bc2a..fffd7dcb7 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -28,7 +28,7 @@ #include "../rtgui/mydiagonalcurve.h" #include "color.h" #include "procparams.h" -#include "editbuffer.h" +#include "pipettebuffer.h" #include "LUT.h" diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 2220f68c5..8979a68ea 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -31,7 +31,7 @@ namespace rtengine extern const Settings* settings; Crop::Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow) - : EditBuffer(editDataProvider), origCrop(NULL), laboCrop(NULL), labnCrop(NULL), + : PipetteBuffer(editDataProvider), origCrop(NULL), laboCrop(NULL), labnCrop(NULL), cropImg(NULL), cbuf_real(NULL), cshmap(NULL), transCrop(NULL), cieCrop(NULL), cbuffer(NULL), updating(false), newUpdatePending(false), skip(10), cropx(0), cropy(0), cropw(-1), croph(-1), @@ -77,7 +77,7 @@ void Crop::setListener (DetailedCropListener* il) EditUniqueID Crop::getCurrEditID() { - EditSubscriber *subscriber = EditBuffer::dataProvider ? EditBuffer::dataProvider->getCurrSubscriber() : NULL; + EditSubscriber *subscriber = PipetteBuffer::dataProvider ? PipetteBuffer::dataProvider->getCurrSubscriber() : NULL; return subscriber ? subscriber->getEditID() : EUID_None; } @@ -90,32 +90,25 @@ void Crop::setEditSubscriber(EditSubscriber* newSubscriber) MyMutex::MyLock lock(cropMutex); // At this point, editCrop.dataProvider->currSubscriber is the old subscriber - EditSubscriber *oldSubscriber = EditBuffer::dataProvider ? EditBuffer::dataProvider->getCurrSubscriber() : NULL; + EditSubscriber *oldSubscriber = PipetteBuffer::dataProvider ? PipetteBuffer::dataProvider->getCurrSubscriber() : NULL; - if (newSubscriber == NULL || (oldSubscriber != NULL && oldSubscriber->getEditBufferType() != newSubscriber->getEditBufferType())) { - if (EditBuffer::imgFloatBuffer != NULL) { - delete EditBuffer::imgFloatBuffer; - EditBuffer::imgFloatBuffer = NULL; + if (newSubscriber == NULL || (oldSubscriber != NULL && oldSubscriber->getPipetteBufferType() != newSubscriber->getPipetteBufferType())) { + if (PipetteBuffer::imgFloatBuffer != NULL) { + delete PipetteBuffer::imgFloatBuffer; + PipetteBuffer::imgFloatBuffer = NULL; } - if (EditBuffer::LabBuffer != NULL) { - delete EditBuffer::LabBuffer; - EditBuffer::LabBuffer = NULL; + if (PipetteBuffer::LabBuffer != NULL) { + delete PipetteBuffer::LabBuffer; + PipetteBuffer::LabBuffer = NULL; } - if (EditBuffer::singlePlaneBuffer.getW() != -1) { - EditBuffer::singlePlaneBuffer.flushData(); + if (PipetteBuffer::singlePlaneBuffer.getW() != -1) { + PipetteBuffer::singlePlaneBuffer.flushData(); } } - if (newSubscriber == NULL && oldSubscriber != NULL && oldSubscriber->getEditingType() == ET_OBJECTS) { - printf("Free object buffers\n"); - EditBuffer::resize(0, 0); // This will delete the objects buffer - } else if (newSubscriber && newSubscriber->getEditingType() == ET_OBJECTS) { - EditBuffer::resize(cropw, croph, newSubscriber); - } - - // If oldSubscriber == NULL && newSubscriber != NULL -> the image will be allocated when necessary + // If oldSubscriber == NULL && newSubscriber != NULL && newSubscriber->getEditingType() == ET_PIPETTE-> the image will be allocated when necessary } void Crop::update (int todo) @@ -984,7 +977,7 @@ void Crop::update (int todo) } // all pipette buffer processing should be finished now - EditBuffer::setReady(); + PipetteBuffer::setReady(); // switch back to rgb parent->ipf.lab2monitorRgb (labnCrop, cropImg); @@ -1085,7 +1078,7 @@ void Crop::freeAll () cshmap = NULL; } - EditBuffer::flush(); + PipetteBuffer::flush(); } cropAllocated = false; @@ -1157,6 +1150,15 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte printf ("setsizes starts (%d, %d, %d, %d, %d, %d)\n", orW, orH, trafw, trafh, cw, ch); } + EditType editType = ET_PIPETTE; + EditDataProvider *editProvider = PipetteBuffer::getDataProvider(); + if (editProvider) { + EditSubscriber *editSubscriber = editProvider->getCurrSubscriber(); + if (editSubscriber) { + editType = editSubscriber->getEditingType(); + } + } + if (cw != cropw || ch != croph || orW != trafw || orH != trafh) { cropw = cw; @@ -1223,7 +1225,11 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte cshmap = new SHMap (cropw, croph, true); } - EditBuffer::resize(cropw, croph); + if (editType == ET_PIPETTE) { + PipetteBuffer::resize(cropw, croph); + } else if (PipetteBuffer::bufferCreated()) { + PipetteBuffer::flush(); + } cropAllocated = true; @@ -1235,7 +1241,12 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte trafx = orx; trafy = ory; + if (settings->verbose) { + if (changed) { + printf("new crop size: cropx=%d, cropy=%d, cropw=%d, croph=%d / rqcropx=%d, rqcropy=%d, rqcropw=%d, rqcroph=%d / leftBorder=%d, upperBorder=%d\n", + cropx, cropy, cropw, croph, rqcropx, rqcropy, rqcropw, rqcroph, leftBorder, upperBorder); + } printf ("setsizes ends\n"); } diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h index 57f388a51..864bf7e9a 100644 --- a/rtengine/dcrop.h +++ b/rtengine/dcrop.h @@ -26,7 +26,7 @@ #include "image16.h" #include "imagesource.h" #include "procevents.h" -#include "editbuffer.h" +#include "pipettebuffer.h" #include "../rtgui/threadutils.h" namespace rtengine @@ -36,7 +36,7 @@ using namespace procparams; class ImProcCoordinator; -class Crop : public DetailedCrop, public EditBuffer +class Crop : public DetailedCrop, public PipetteBuffer { protected: @@ -57,6 +57,7 @@ protected: bool updating; /// Flag telling if an updater thread is currently processing bool newUpdatePending; /// Flag telling the updater thread that a new update is pending int skip; + int padding; /// Minimum space allowed around image in the display area int cropx, cropy, cropw, croph; /// size of the detail crop image ('skip' taken into account), with border int trafx, trafy, trafw, trafh; /// the size and position to get from the imagesource that is transformed to the requested crop area int rqcropx, rqcropy, rqcropw, rqcroph; /// size of the requested detail crop image (the image might be smaller) (without border) @@ -70,7 +71,7 @@ protected: ImProcCoordinator* parent; bool isDetailWindow; EditUniqueID getCurrEditID(); - bool setCropSizes (int cx, int cy, int cw, int ch, int skip, bool internal); + bool setCropSizes (int cropX, int cropY, int cropW, int cropH, int skip, bool internal); void freeAll (); public: @@ -91,9 +92,9 @@ public: return cropImageListener; } void update (int todo); - void setWindow (int cx, int cy, int cw, int ch, int skip) + void setWindow (int cropX, int cropY, int cropW, int cropH, int canvasX, int canvasY, int canvasW, int canvasH, int skip) { - setCropSizes (cx, cy, cw, ch, skip, false); + setCropSizes (cropX, cropY, cropW, cropH, skip, false); } /** @brief Synchronously look out if a full update is necessary @@ -109,6 +110,10 @@ public: { return skip; } + int getPadding () + { + return padding; + } int getLeftBorder () { return leftBorder; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index b1f47c3a9..468abbe13 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3106,15 +3106,15 @@ filmlike_clip(float *r, float *g, float *b) } } -void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, +void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf ) { - rgbProc (working, lab, editBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf); + rgbProc (working, lab, pipetteBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf); } // Process RGB image and convert to LAB space -void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, +void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf) { @@ -3125,20 +3125,20 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e Imagefloat* editImgFloat = NULL; LabImage* editLab = NULL; PlanarWhateverData* editWhatever = NULL; - EditUniqueID editID = editBuffer ? editBuffer->getEditID() : EUID_None; + EditUniqueID editID = pipetteBuffer ? pipetteBuffer->getEditID() : EUID_None; if (editID != EUID_None) { - switch (editBuffer->getDataProvider()->getCurrSubscriber()->getEditBufferType()) { + switch (pipetteBuffer->getDataProvider()->getCurrSubscriber()->getPipetteBufferType()) { case (BT_IMAGEFLOAT): - editImgFloat = editBuffer->getImgFloatBuffer(); + editImgFloat = pipetteBuffer->getImgFloatBuffer(); break; case (BT_LABIMAGE): - editLab = editBuffer->getLabBuffer(); + editLab = pipetteBuffer->getLabBuffer(); break; case (BT_SINGLEPLANE_FLOAT): - editWhatever = editBuffer->getSinglePlaneBuffer(); + editWhatever = pipetteBuffer->getSinglePlaneBuffer(); break; } } @@ -3447,7 +3447,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e int tW; int tH; - // Allocating buffer for the EditBuffer + // Allocating buffer for the PipetteBuffer float *editIFloatTmpR, *editIFloatTmpG, *editIFloatTmpB, *editWhateverTmp; if (editImgFloat) { @@ -5552,7 +5552,7 @@ void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, LUTf & cur -SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve, LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) +SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve, LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) { int W = lold->W; int H = lold->H; @@ -5566,23 +5566,23 @@ SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, EditUniqueID editID = EUID_None; bool editPipette = false; - if (editBuffer) { - editID = editBuffer->getEditID(); + if (pipetteBuffer) { + editID = pipetteBuffer->getEditID(); if (editID != EUID_None) { editPipette = true; - switch (editBuffer->getDataProvider()->getCurrSubscriber()->getEditBufferType()) { + switch (pipetteBuffer->getDataProvider()->getCurrSubscriber()->getPipetteBufferType()) { case (BT_IMAGEFLOAT): - editImgFloat = editBuffer->getImgFloatBuffer(); + editImgFloat = pipetteBuffer->getImgFloatBuffer(); break; case (BT_LABIMAGE): - editLab = editBuffer->getLabBuffer(); + editLab = pipetteBuffer->getLabBuffer(); break; case (BT_SINGLEPLANE_FLOAT): - editWhatever = editBuffer->getSinglePlaneBuffer(); + editWhatever = pipetteBuffer->getSinglePlaneBuffer(); break; } } diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 74db0ff3f..7a2e28441 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -33,7 +33,7 @@ #include "dcp.h" #include "curves.h" #include "cplx_wavelet_dec.h" -#include "editbuffer.h" +#include "pipettebuffer.h" #define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } @@ -235,10 +235,10 @@ public: void firstAnalysis (Imagefloat* working, const ProcParams* params, LUTu & vhist16); void updateColorProfiles (const ColorManagementParams& icm, const Glib::ustring& monitorProfile, RenderingIntent monitorIntent); - void rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, + void rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf); - void rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, + void rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf); @@ -259,7 +259,7 @@ public: void ciecam_02 (CieImage* ncie, double adap, int begh, int endh, int pW, int pwb, LabImage* lab, const ProcParams* params, const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, LUTu &histLCAM, LUTu &histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, double &d, int scalecd, int rtt); - void chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve, LUTf & satclcurve, LUTf &clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLCurve, LUTu &histLurve); + void chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve, LUTf & satclcurve, LUTf &clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLCurve, LUTu &histLurve); void vibrance (LabImage* lab);//Jacques' vibrance void colorCurve (LabImage* lold, LabImage* lnew); void sharpening (LabImage* lab, float** buffer, SharpeningParams &sharpenParam); diff --git a/rtengine/editbuffer.cc b/rtengine/pipettebuffer.cc similarity index 50% rename from rtengine/editbuffer.cc rename to rtengine/pipettebuffer.cc index caf657070..d76589e99 100644 --- a/rtengine/editbuffer.cc +++ b/rtengine/pipettebuffer.cc @@ -17,16 +17,15 @@ * along with RawTherapee. If not, see . */ -#include "editbuffer.h" +#include "pipettebuffer.h" namespace rtengine { -EditBuffer::EditBuffer(::EditDataProvider *dataProvider) : - objectMap(NULL), objectMap2(NULL), objectMode(OM_255), dataProvider(dataProvider), - imgFloatBuffer(NULL), LabBuffer(NULL), singlePlaneBuffer(), ready(false) {} +PipetteBuffer::PipetteBuffer(::EditDataProvider *dataProvider) : + dataProvider(dataProvider), imgFloatBuffer(NULL), LabBuffer(NULL), singlePlaneBuffer(), ready(false) {} -EditBuffer::~EditBuffer() +PipetteBuffer::~PipetteBuffer() { flush(); #ifndef NDEBUG @@ -37,13 +36,13 @@ EditBuffer::~EditBuffer() #endif } -void EditBuffer::createBuffer(int width, int height) +void PipetteBuffer::createBuffer(int width, int height) { //printf("Appel de createBuffer %d x %d\n", width, height); resize (width, height); } -void EditBuffer::flush() +void PipetteBuffer::flush() { if (imgFloatBuffer) { delete imgFloatBuffer; @@ -59,29 +58,7 @@ void EditBuffer::flush() ready = false; } -/* Upgrade or downgrade the objectModeType; we're assuming that objectMap has been allocated */ -void EditBuffer::setObjectMode(ObjectMode newType) -{ - switch (newType) { - case (OM_255): - if (objectMap2) { - objectMap2->unreference(); - } - - objectMode = OM_255; - break; - - case (OM_65535): - if (!objectMap2) { - objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, objectMap->get_width(), objectMap->get_height()); - } - - objectMode = OM_65535; - break; - } -} - -EditUniqueID EditBuffer::getEditID() +EditUniqueID PipetteBuffer::getEditID() { if (dataProvider && dataProvider->getCurrSubscriber()) { return dataProvider->getCurrSubscriber()->getEditID(); @@ -90,58 +67,17 @@ EditUniqueID EditBuffer::getEditID() } } -void EditBuffer::resize(int newWidth, int newHeight) +void PipetteBuffer::resize(int newWidth, int newHeight) { resize(newWidth, newHeight, dataProvider ? dataProvider->getCurrSubscriber() : NULL); } // Resize buffers if they already exist -void EditBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscriber) +void PipetteBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscriber) { if (newSubscriber) { - if (newSubscriber->getEditingType() == ET_OBJECTS) { - if (objectMap && (objectMap->get_width() != newWidth || objectMap->get_height() != newHeight)) { - objectMap.clear(); - } - - if (!objectMap && newWidth && newHeight) { - objectMap = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); - } - - if (objectMode == OM_65535) { - if (objectMap2) { - if (objectMap2->get_width() != newWidth || objectMap2->get_height() != newHeight) { - objectMap2.clear(); - } - } - - if (!objectMap2 && newWidth && newHeight) { - objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); - } - } - // OM_255 -> deleting objectMap2, if any - else if (objectMap2) { - objectMap2.clear(); - } - - // Should never happen! - if (imgFloatBuffer) { - delete imgFloatBuffer; - imgFloatBuffer = NULL; - } - - if (LabBuffer) { - delete LabBuffer; - LabBuffer = NULL; - } - - if (singlePlaneBuffer.data) { - singlePlaneBuffer.allocate(0, 0); - } - } - if (newSubscriber->getEditingType() == ET_PIPETTE) { - if (newSubscriber->getEditBufferType() == BT_IMAGEFLOAT) { + if (newSubscriber->getPipetteBufferType() == BT_IMAGEFLOAT) { if (!imgFloatBuffer) { imgFloatBuffer = new Imagefloat(newWidth, newHeight); } else { @@ -152,7 +88,7 @@ void EditBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscrib imgFloatBuffer = NULL; } - if (newSubscriber->getEditBufferType() == BT_LABIMAGE) { + if (newSubscriber->getPipetteBufferType() == BT_LABIMAGE) { if (LabBuffer && (LabBuffer->W != newWidth && LabBuffer->H != newHeight)) { delete LabBuffer; LabBuffer = NULL; @@ -166,73 +102,46 @@ void EditBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscrib LabBuffer = NULL; } - if (newSubscriber->getEditBufferType() == BT_SINGLEPLANE_FLOAT) { + if (newSubscriber->getPipetteBufferType() == BT_SINGLEPLANE_FLOAT) { singlePlaneBuffer.allocate(newWidth, newHeight); } else if (singlePlaneBuffer.data) { singlePlaneBuffer.allocate(0, 0); } - - // Should never happen! - if (objectMap ) { - objectMap.clear(); - } - - if (objectMap2) { - objectMap2.clear(); - } + } else { + // Should never happen + flush(); } } ready = false; } -bool EditBuffer::bufferCreated() +bool PipetteBuffer::bufferCreated() { EditSubscriber* subscriber; if (dataProvider && (subscriber = dataProvider->getCurrSubscriber())) { - switch (subscriber->getEditingType()) { - case ET_PIPETTE: - switch (dataProvider->getCurrSubscriber()->getEditBufferType()) { + if (subscriber->getEditingType() == ET_PIPETTE) { + switch (dataProvider->getCurrSubscriber()->getPipetteBufferType()) { case (BT_IMAGEFLOAT): return imgFloatBuffer != NULL; - case (BT_LABIMAGE): return LabBuffer != NULL; - case (BT_SINGLEPLANE_FLOAT): return singlePlaneBuffer.data != NULL; } - - break; - - case (ET_OBJECTS): - return bool(objectMap); + } else { + return false; } } return false; } -int EditBuffer::getObjectID(const Coord& location) -{ - int id = 0; - - if (objectMap && location.x > 0 && location.y > 0 && location.x < objectMap->get_width() && location.y < objectMap->get_height()) { - id = (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )); - - if (objectMap2) { - id |= (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )) << 8; - } - } - - return id - 1; -} - -void EditBuffer::getPipetteData(float* v, int x, int y, int squareSize) +void PipetteBuffer::getPipetteData(float* v, int x, int y, int squareSize) { if (ready && dataProvider && dataProvider->getCurrSubscriber()) { - switch (dataProvider->getCurrSubscriber()->getEditBufferType()) { + switch (dataProvider->getCurrSubscriber()->getPipetteBufferType()) { case (BT_IMAGEFLOAT): if (imgFloatBuffer) { imgFloatBuffer->getPipetteData(v[0], v[1], v[2], x, y, squareSize, 0); diff --git a/rtengine/editbuffer.h b/rtengine/pipettebuffer.h similarity index 57% rename from rtengine/editbuffer.h rename to rtengine/pipettebuffer.h index 1a55a39ed..e6db8eb68 100644 --- a/rtengine/editbuffer.h +++ b/rtengine/pipettebuffer.h @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef _EDITBUFFER_H_ -#define _EDITBUFFER_H_ +#ifndef _PIPETTEBUFFER_H_ +#define _PIPETTEBUFFER_H_ #include "../rtgui/edit.h" #include "array2D.h" @@ -28,16 +28,8 @@ namespace rtengine { /// @brief Structure that contains information about and pointers to the Edit buffer -class EditBuffer +class PipetteBuffer { -private: - - // Used to draw the objects where the color correspond to the object's ID, in order to find the correct object when hovering - Cairo::RefPtr objectMap; - // If more than 254 objects has to be handled, objectMap2 contains the "upper part" of the 16 bit int value. objectMap2 will be NULL otherwise. - Cairo::RefPtr objectMap2; - ObjectMode objectMode; - protected: // To avoid duplicated information, we points to a EditDataProvider that contains the current EditSubscriber @@ -52,39 +44,38 @@ protected: bool ready; // flag that indicates if the _pipette_ buffer is ready - void createBuffer(int width, int height); - void resize(int newWidth, int newHeight, EditSubscriber* newSubscriber); - void resize(int newWidth, int newHeight); - void flush(); + void createBuffer(int width, int height); + void resize(int newWidth, int newHeight, EditSubscriber* newSubscriber); + void resize(int newWidth, int newHeight); + void flush(); public: - EditBuffer(::EditDataProvider *dataProvider); - ~EditBuffer(); + PipetteBuffer(::EditDataProvider *dataProvider); + ~PipetteBuffer(); /** @brief Getter to know if the pipette buffer is correctly filled */ - bool isReady() + bool isReady() { return ready; } /** @brief Setter to tell that the pipette buffer is correctly filled * You have to use this method once the pipette is filled, so it can be read. */ - void setReady() + void setReady() { ready = true; } - void setObjectMode(ObjectMode newType); - ::EditDataProvider* getDataProvider() + ::EditDataProvider* getDataProvider() { return dataProvider; } - EditUniqueID getEditID(); - Imagefloat* getImgFloatBuffer() + EditUniqueID getEditID(); + Imagefloat* getImgFloatBuffer() { return imgFloatBuffer; } - LabImage* getLabBuffer() + LabImage* getLabBuffer() { return LabBuffer; } @@ -92,26 +83,12 @@ public: { return &singlePlaneBuffer; } - ObjectMode getObjectMode() - { - return objectMode; - } - - Cairo::RefPtr &getObjectMap () - { - return objectMap; - } - Cairo::RefPtr &getObjectMap2() - { - return objectMap2; - } // return true if the buffer has been allocated - bool bufferCreated(); + bool bufferCreated(); - int getObjectID(const Coord& location); // get the pipette values - void getPipetteData(float* v, int x, int y, int squareSize); + void getPipetteData(float* v, int x, int y, int squareSize); }; } diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index 4342c4973..b0c257101 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -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(listener) : NULL; + CropWindow *cropWin = displayHandler ? static_cast(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); } diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h index 60d7956ca..6e479bb16 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -24,14 +24,15 @@ #include "edit.h" #include -class CropHandlerListener +class CropDisplayHandler { public: - virtual ~CropHandlerListener() {} + virtual ~CropDisplayHandler() {} virtual void cropImageUpdated () {} virtual void cropWindowChanged () {} virtual void initialImageArrived () {} + virtual void setDisplayPosition (int x, int y) {} }; class CropHandler; @@ -41,16 +42,22 @@ struct CropHandlerIdleHelper { int pending; }; +/** + * This class handle the displayed part of the image, ask for the initial data and process it so it can display it. + * Its position on the preview is handled not set by this class but by the CropHandlerListener (i.e. CropWindow) with which it works closely. + */ class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener { friend int createpixbufs (void* data); protected: - int zoom; - int ww, wh; // size of the crop view on the screen - int cx, cy, cw, ch; // position and size of the requested crop - int cropX, cropY, cropW, cropH; // position and size of the crop corresponding to cropPixbuf + int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...) + int ww, wh; // size of the crop's canvas on the screen ; might be bigger than the displayed image, but not smaller + int imx, imy, imw, imh; // this is a copy of the cropwindow's parameters + int cax, cay; // clamped crop anchor's coordinate, i.e. point of the image that coincide to the center of the display area, expressed in image coordinates; cannot be outside the image's bounds; but if cax==cay==-1, designate the center of the image + int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size + int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds bool enabled; unsigned char* cropimg; unsigned char* cropimgtrue; @@ -61,7 +68,7 @@ protected: rtengine::StagedImageProcessor* ipc; rtengine::DetailedCrop* crop; - CropHandlerListener* listener; + CropDisplayHandler* displayHandler; CropHandlerIdleHelper* chi; void compDim (); @@ -81,9 +88,9 @@ public: CropHandler (); ~CropHandler (); - void setCropHandlerListener (CropHandlerListener* l) + void setDisplayHandler (CropDisplayHandler* l) { - listener = l; + displayHandler = l; } void setEditSubscriber (EditSubscriber* newSubscriber); @@ -93,7 +100,10 @@ public: double getFitCropZoom(); void setWSize (int w, int h); void getWSize (int& w, int &h); - void setPosition (int x, int y, bool update = true); + void getAnchorPosition (int& x, int& y); + void setAnchorPosition (int x, int y, bool update = true); + void moveAnchor (int deltaX, int deltaY, bool update = true); + void centerAnchor (bool update = true); void getPosition (int& x, int& y); void getSize (int& w, int& h); void getFullImageSize (int& w, int& h); @@ -112,8 +122,6 @@ public: bool getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip); // SizeListener interface void sizeChanged (int w, int h, int ow, int oh); - - void cutRectToImgBounds (int& x, int& y, int& w, int& h); }; #endif diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 1c5b62a33..12635839f 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -64,10 +64,10 @@ ZoomStep zoomSteps[] = { #define ZOOM11INDEX 13 CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow) - : onResizeArea(false), deleted(false), fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), + : ObjectMOBuffer(parent), onResizeArea(false), deleted(false), fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), backColor(options.bgcolor), decorated(true), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3), upperBorderWidth(1), sepWidth(2), - xpos(30), ypos(30), imgX(0), imgY(0), imgW(1), imgH(1), iarea(parent), + xpos(30), ypos(30), imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent), cropZoom(0), cropgl(NULL), pmlistener(NULL), observedCropWin(NULL), ipc(ipc_), isFlawnOver(false) { Glib::RefPtr context = parent->get_pango_context () ; @@ -107,7 +107,7 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, minWidth = bsw + iw + 2 * sideBorderWidth; - cropHandler.setCropHandlerListener (this); + cropHandler.setDisplayHandler(this); cropHandler.newImage (ipc_, isDetailWindow); state = SNormal; @@ -158,36 +158,27 @@ void CropWindow::getCropPosition (int& x, int& y) void CropWindow::getCropRectangle (int& x, int& y, int& w, int& h) { - int cropX, cropY, cropW, cropH; - cropHandler.getPosition (cropX, cropY); - cropHandler.getSize (cropW, cropH); - - if (state != SCropImgMove) { - x = cropX; - y = cropY; - } else { - x = cropX + action_x; - y = cropY + action_y; - } - - if (state != SCropWinResize) { - w = cropW; - h = cropH; - } else { - w = imgAreaW; - h = imgAreaH; - } - - cropHandler.cutRectToImgBounds (x, y, w, h); + cropHandler.getPosition (x, y); + cropHandler.getSize (w, h); } void CropWindow::setCropPosition (int x, int y, bool update) { - cropHandler.setPosition (x, y, update); + cropHandler.setAnchorPosition (x, y, update); - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropPositionChanged (this); + for (auto listener : listeners) { + listener->cropPositionChanged (this); + } +} + +void CropWindow::centerCrop (bool update) +{ + + cropHandler.centerAnchor (update); + + for (auto listener : listeners) { + listener->cropPositionChanged (this); } } @@ -240,6 +231,16 @@ void CropWindow::getCropSize (int& w, int& h) h = imgAreaH; } +void CropWindow::getCropAnchorPosition (int& x, int& y) +{ + cropHandler.getAnchorPosition(x, y); +} + +void CropWindow::setCropAnchorPosition (int& x, int& y) +{ + cropHandler.setAnchorPosition(x, y); +} + bool CropWindow::isInside (int x, int y) { @@ -288,11 +289,6 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) state = SNormal; } - //below code is no longer working/needed after adding buttons for each of the backColor values - /*else if (button==1 && type==GDK_2BUTTON_PRESS && onArea (CropBorder, x, y)) { - backColor = (backColor+1) % 3; - options.bgcolor = backColor; - }*/ else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropToolBar, x, y)) { if (!decorated || !buttonSet.pressNotify (x, y)) { state = SCropWinMove; @@ -307,48 +303,48 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) action_y = y; press_x = width; press_y = height; - } else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropImage, x, y)) { - if (onArea (CropTopLeft, x, y)) { + } else if (type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropImage, x, y)) { + if (button == 1 && onArea (CropTopLeft, x, y)) { state = SResizeTL; press_x = x; action_x = cropHandler.cropParams.x; press_y = y; action_y = cropHandler.cropParams.y; - } else if (onArea (CropTopRight, x, y)) { + } else if (button == 1 && onArea (CropTopRight, x, y)) { state = SResizeTR; press_x = x; action_x = cropHandler.cropParams.w; press_y = y; action_y = cropHandler.cropParams.y; - } else if (onArea (CropBottomLeft, x, y)) { + } else if (button == 1 && onArea (CropBottomLeft, x, y)) { state = SResizeBL; press_x = x; action_x = cropHandler.cropParams.x; press_y = y; action_y = cropHandler.cropParams.h; - } else if (onArea (CropBottomRight, x, y)) { + } else if (button == 1 && onArea (CropBottomRight, x, y)) { state = SResizeBR; press_x = x; action_x = cropHandler.cropParams.w; press_y = y; action_y = cropHandler.cropParams.h; - } else if (onArea (CropTop, x, y)) { + } else if (button == 1 && onArea (CropTop, x, y)) { state = SResizeH1; press_y = y; action_y = cropHandler.cropParams.y; - } else if (onArea (CropBottom, x, y)) { + } else if (button == 1 && onArea (CropBottom, x, y)) { state = SResizeH2; press_y = y; action_y = cropHandler.cropParams.h; - } else if (onArea (CropLeft, x, y)) { + } else if (button == 1 && onArea (CropLeft, x, y)) { state = SResizeW1; press_x = x; action_x = cropHandler.cropParams.x; - } else if (onArea (CropRight, x, y)) { + } else if (button == 1 && onArea (CropRight, x, y)) { state = SResizeW2; press_x = x; action_x = cropHandler.cropParams.w; - } else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, x, y)) { + } else if (button == 1 && (bstate & GDK_SHIFT_MASK) && onArea (CropInside, x, y)) { state = SCropMove; press_x = x; press_y = y; @@ -357,7 +353,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) } else if (iarea->getToolMode () == TMHand) { EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); - if (editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_OBJECTS)) { + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { if (button == 1) { needRedraw = editSubscriber->button1Pressed(bstate); @@ -385,7 +381,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) } if (state != SEditDrag1 && state != SEditDrag2 && state != SEditDrag3) { - if (onArea (CropObserved, x, y)) { + if (button == 1 && onArea (CropObserved, x, y)) { state = SObservedMove; press_x = x; press_y = y; @@ -398,7 +394,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) press_y = y; action_x = 0; action_y = 0; - } else if(zoomSteps[cropZoom].zoom > cropHandler.getFitZoom()) { // only allow move when image is only partial visible + } else if (button == 1) { // if(zoomSteps[cropZoom].zoom > cropHandler.getFitZoom()) { // only allow move when image is only partial visible state = SCropImgMove; press_x = x; press_y = y; @@ -406,22 +402,24 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) action_y = 0; } } - } else if (onArea (CropObserved, x, y)) { + } else if (button == 1 && onArea (CropObserved, x, y)) { state = SObservedMove; press_x = x; press_y = y; - } else if (iarea->getToolMode () == TMStraighten) { + action_x = 0; + action_y = 0; + } else if (button == 1 && iarea->getToolMode () == TMStraighten) { state = SRotateSelecting; press_x = x; press_y = y; action_x = x; action_y = y; rot_deg = 0; - } else if (iarea->getToolMode () == TMSpotWB) { + } else if (button == 1 && iarea->getToolMode () == TMSpotWB) { int spotx, spoty; screenCoordToImage (x, y, spotx, spoty); iarea->spotWBSelected (spotx, spoty); - } else if (iarea->getToolMode () == TMCropSelect && cropgl) { + } else if (button == 1 && iarea->getToolMode () == TMCropSelect && cropgl) { state = SCropSelecting; screenCoordToImage (x, y, press_x, press_y); cropHandler.cropParams.enabled = true; @@ -430,6 +428,36 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) cropHandler.cropParams.w = cropHandler.cropParams.h = 1; cropgl->cropInit (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); } + } else if (type == GDK_BUTTON_PRESS && state == SNormal && iarea->getToolMode () == TMHand) { + // Any other case... i.e. we're assuming to be on the canvas, looking for editing objects + EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); + + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { + if (button == 1) { + needRedraw = editSubscriber->button1Pressed(bstate); + + if (editSubscriber->isDragging()) { + state = SEditDrag1; + } + } else if (button == 2) { + needRedraw = editSubscriber->button2Pressed(bstate); + + if (editSubscriber->isDragging()) { + state = SEditDrag2; + } + } else if (button == 3) { + needRedraw = editSubscriber->button3Pressed(bstate); + + if (editSubscriber->isDragging()) { + state = SEditDrag3; + } + } + + press_x = x; + press_y = y; + action_x = 0; + action_y = 0; + } } if (button == 3) { @@ -474,16 +502,14 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) state = SNormal; - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropWindowSizeChanged (this); + for (auto listener : listeners) { + listener->cropWindowSizeChanged (this); } needRedraw = true; } else if (state == SCropImgMove) { - int cropX, cropY; - cropHandler.getPosition (cropX, cropY); - cropHandler.setPosition (cropX + action_x, cropY + action_y); - cropHandler.getPosition (cropX, cropY); + cropHandler.update (); + state = SNormal; for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { @@ -519,9 +545,9 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) iarea->posScreen.set(x, y); Coord cropPos; - screenCoordToCropBuffer(x, y, cropPos.x, cropPos.y); - if (state == SEditDrag1 && editSubscriber->getEditingType() == ET_PIPETTE) { + screenCoordToCropBuffer (x, y, cropPos.x, cropPos.y); + iarea->object = onArea (CropImage, x, y) && !onArea (CropObserved, x, y) ? 1 : 0; //iarea->object = cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) ? 1 : 0; @@ -532,8 +558,10 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; } } else if (editSubscriber->getEditingType() == ET_OBJECTS) { + screenCoordToCropCanvas (x, y, cropPos.x, cropPos.y); + if (onArea (CropImage, x, y)) { - iarea->object = crop->getObjectID(cropPos); + iarea->object = ObjectMOBuffer::getObjectID(cropPos); } else { iarea->object = -1; } @@ -588,8 +616,8 @@ void CropWindow::pointerMoved (int bstate, int x, int y) } else if (state == SCropWinResize) { setSize (press_x + x - action_x, press_y + y - action_y, true); - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropWindowSizeChanged (this); + for (auto listener : listeners) { + listener->cropWindowSizeChanged (this); } iarea->redraw (); @@ -602,11 +630,19 @@ void CropWindow::pointerMoved (int bstate, int x, int y) factor = 1.0; } - action_x = (press_x - x) / zoomSteps[cropZoom].zoom * factor; - action_y = (press_y - y) / zoomSteps[cropZoom].zoom * factor; + int newAction_x = (press_x - x) / zoomSteps[cropZoom].zoom * factor; + int newAction_y = (press_y - y) / zoomSteps[cropZoom].zoom * factor; - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropPositionChanged (this); + int deltaX = newAction_x - action_x; + int deltaY = newAction_y - action_y; + + action_x = newAction_x; + action_y = newAction_y; + + cropHandler.moveAnchor(deltaX, deltaY, false); + + for (auto listener : listeners) { + listener->cropPositionChanged (this); } iarea->redraw (); @@ -695,7 +731,11 @@ void CropWindow::pointerMoved (int bstate, int x, int y) iarea->redraw (); } else if (state == SObservedMove) { - observedCropWin->remoteMove ((x - press_x) / zoomSteps[cropZoom].zoom, (y - press_y) / zoomSteps[cropZoom].zoom); + int new_action_x = x - press_x; + int new_action_y = y - press_y; + observedCropWin->remoteMove ((new_action_x - action_x) / zoomSteps[cropZoom].zoom, (new_action_y - action_y) / zoomSteps[cropZoom].zoom); + action_x = new_action_x; + action_y = new_action_y; iarea->redraw (); } else if (editSubscriber) { rtengine::Crop* crop = static_cast(cropHandler.getCrop()); @@ -710,9 +750,10 @@ void CropWindow::pointerMoved (int bstate, int x, int y) iarea->posScreen.set(x, y); Coord cropPos; - screenCoordToCropBuffer(x, y, cropPos.x, cropPos.y); if (editSubscriber->getEditingType() == ET_PIPETTE) { + screenCoordToCropBuffer (x, y, cropPos.x, cropPos.y); + iarea->object = onArea (CropImage, x, y) && !onArea (CropObserved, x, y) ? 1 : 0; //iarea->object = cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) ? 1 : 0; @@ -723,11 +764,8 @@ void CropWindow::pointerMoved (int bstate, int x, int y) iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; } } else if (editSubscriber->getEditingType() == ET_OBJECTS) { - if (onArea (CropImage, x, y)) { - iarea->object = crop->getObjectID(cropPos); - } else { - iarea->object = -1; - } + screenCoordToCropCanvas (x, y, cropPos.x, cropPos.y); + iarea->object = ObjectMOBuffer::getObjectID(cropPos); } if (editSubscriber->mouseOver(bstate)) { @@ -850,7 +888,7 @@ bool CropWindow::onArea (CursorArea a, int x, int y) return x > xpos && y > ypos && x < xpos + width - 1 && y < ypos + imgAreaY; case CropImage: - return x >= xpos + imgX && y >= ypos + imgY && x < xpos + imgX + imgW && y < ypos + imgY + imgH; + return x >= xpos + imgX + imgAreaX && y >= ypos + imgY + imgAreaY && x < xpos + imgX + imgAreaX + imgW && y < ypos + imgY + imgAreaY + imgH; case CropBorder: return @@ -985,10 +1023,10 @@ void CropWindow::updateCursor (int x, int y) } else if (onArea (CropImage, x, y)) { int objectID = -1; - if (editSubscriber) { + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { Coord cropPos; - screenCoordToCropBuffer(iarea->posScreen.x, iarea->posScreen.y, cropPos.x, cropPos.y); - objectID = static_cast(cropHandler.getCrop())->getObjectID(cropPos); + screenCoordToCropCanvas (iarea->posScreen.x, iarea->posScreen.y, cropPos.x, cropPos.y); + objectID = ObjectMOBuffer::getObjectID(cropPos); } if (objectID > -1) { @@ -1007,7 +1045,19 @@ void CropWindow::updateCursor (int x, int y) cursorManager.setCursor (iarea->get_window(), CSStraighten); } } else { - cursorManager.setCursor (iarea->get_window(), CSArrow); + int objectID = -1; + + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { + Coord cropPos; + screenCoordToCropCanvas (iarea->posScreen.x, iarea->posScreen.y, cropPos.x, cropPos.y); + objectID = ObjectMOBuffer::getObjectID(cropPos); + } + + if (objectID > -1) { + cursorManager.setCursor (iarea->get_window(), editSubscriber->getCursor(objectID)); + } else { + cursorManager.setCursor (iarea->get_window(), CSArrow); + } } } else if (state == SCropSelecting) { cursorManager.setCursor (iarea->get_window(), CSCropSelect); @@ -1042,7 +1092,7 @@ void CropWindow::expose (Cairo::RefPtr cr) drawDecoration (cr); } - int x = xpos, y = ypos, h = height, w = width; + int x = xpos, y = ypos; // draw the background backColor = iarea->previewModePanel->GetbackColor(); @@ -1069,15 +1119,10 @@ void CropWindow::expose (Cairo::RefPtr cr) int cropX, cropY; cropHandler.getPosition (cropX, cropY); - if (state == SCropImgMove) { - cropX += action_x; - cropY += action_y; - } - Glib::RefPtr rough = iarea->getPreviewHandler()->getRoughImage (cropX, cropY, imgAreaW, imgAreaH, zoomSteps[cropZoom].zoom); if (rough) { - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + (imgAreaW - rough->get_width()) / 2, y + imgAreaY + (imgAreaH - rough->get_height()) / 2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + imgX, y + imgAreaY + imgY, rtengine::min (rough->get_width (), imgAreaW-imgX), rtengine::min (rough->get_height (), imgAreaH-imgY), Gdk::RGB_DITHER_NORMAL, 0, 0); // if (cropHandler.cropParams.enabled) // drawCrop (cr, x+imgX, y+imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams); } @@ -1089,8 +1134,6 @@ void CropWindow::expose (Cairo::RefPtr cr) if (cropHandler.cropPixbuf) { imgW = cropHandler.cropPixbuf->get_width (); imgH = cropHandler.cropPixbuf->get_height (); - imgX = imgAreaX + (imgAreaW - imgW) / 2; - imgY = imgAreaY + (imgAreaH - imgH) / 2; exposeVersion++; bool showcs = iarea->indClippedPanel->showClippedShadows(); @@ -1240,8 +1283,8 @@ void CropWindow::expose (Cairo::RefPtr cr) } } - float sum_L2 = tmpLsum[i * bWidth + j]; - float sumsq_L2 = tmpLsumSq[i * bWidth + j]; + //float sum_L2 = tmpLsum[i * bWidth + j]; + //float sumsq_L2 = tmpLsumSq[i * bWidth + j]; //************* // averages // Optimized formulas to avoid divisions @@ -1484,16 +1527,15 @@ void CropWindow::expose (Cairo::RefPtr cr) } } -//printf("zoomSteps[cropZoom].zoom=%d\n",zoomSteps[cropZoom].zoom); - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), tmp, 0, 0, x + imgX, y + imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), tmp, 0, 0, x + imgAreaX + imgX, y + imgAreaY + imgY, rtengine::min (tmp->get_width (), imgAreaW-imgX), rtengine::min (tmp->get_height (), imgAreaH-imgY), Gdk::RGB_DITHER_NORMAL, 0, 0); } else { - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), cropHandler.cropPixbuf, 0, 0, x + imgX, y + imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), cropHandler.cropPixbuf, 0, 0, x + imgAreaX + imgX, y + imgAreaY + imgY, rtengine::min (cropHandler.cropPixbuf->get_width (), imgAreaW-imgX), rtengine::min (cropHandler.cropPixbuf->get_height (), imgAreaH-imgY), Gdk::RGB_DITHER_NORMAL, 0, 0); } if (cropHandler.cropParams.enabled) { int cropX, cropY; cropHandler.getPosition (cropX, cropY); - drawCrop (cr, x + imgX, y + imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom() ); + drawCrop (cr, x + imgAreaX + imgX, y + imgAreaY + imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom() ); } if (observedCropWin) { @@ -1501,13 +1543,12 @@ void CropWindow::expose (Cairo::RefPtr cr) } EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); - rtengine::Crop* crop = static_cast(cropHandler.getCrop()); - if (editSubscriber && crop->bufferCreated()) { + if (editSubscriber && bufferCreated()) { if (this != iarea->mainCropWindow) { cr->set_line_width (0.); - cr->rectangle (x + imgX, y + imgY, imgW, imgH); + cr->rectangle (x + imgAreaX, y + imgAreaY, imgAreaW, imgAreaH); cr->clip(); } @@ -1518,17 +1559,13 @@ void CropWindow::expose (Cairo::RefPtr cr) cr->set_line_join(Cairo::LINE_JOIN_ROUND); // drawing outer lines - for (std::vector::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i) { - (*i)->drawOuterGeometry(cr, crop, *this); + for (auto geom : visibleGeom) { + geom->drawOuterGeometry(cr, this, *this); } // drawing inner lines - for (std::vector::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i) { - (*i)->drawInnerGeometry(cr, crop, *this); - } - - if (this != iarea->mainCropWindow) { - cr->reset_clip(); + for (auto geom : visibleGeom) { + geom->drawInnerGeometry(cr, this, *this); } // drawing to the "mouse over" channel @@ -1536,8 +1573,8 @@ void CropWindow::expose (Cairo::RefPtr cr) const std::vector mouseOverGeom = editSubscriber->getMouseOverGeometry(); if (mouseOverGeom.size()) { - //printf("ObjectMap (%d x %d)\n", crop->getObjectMap()->get_width(), crop->getObjectMap()->get_height()); - Cairo::RefPtr crMO = Cairo::Context::create(crop->getObjectMap()); + //printf("ObjectMap (%d x %d)\n", ObjectMOBuffer::getObjectMap()->get_width(), ObjectMOBuffer::getObjectMap()->get_height()); + Cairo::RefPtr crMO = Cairo::Context::create(ObjectMOBuffer::getObjectMap()); crMO->set_antialias(Cairo::ANTIALIAS_NONE); crMO->set_line_cap(Cairo::LINE_CAP_SQUARE); crMO->set_line_join(Cairo::LINE_JOIN_ROUND); @@ -1545,14 +1582,14 @@ void CropWindow::expose (Cairo::RefPtr cr) // clear the bitmap crMO->set_source_rgba(0., 0., 0., 0.); - crMO->rectangle(0., 0., crop->getObjectMap()->get_width(), crop->getObjectMap()->get_height()); + crMO->rectangle(0., 0., ObjectMOBuffer::getObjectMap()->get_width(), ObjectMOBuffer::getObjectMap()->get_height()); crMO->set_line_width(0.); crMO->fill(); Cairo::RefPtr crMO2; - if (crop->getObjectMode() > OM_255) { - crMO2 = Cairo::Context::create(crop->getObjectMap2()); + if (ObjectMOBuffer::getObjectMode() > OM_255) { + crMO2 = Cairo::Context::create(ObjectMOBuffer::getObjectMap2()); crMO2->set_antialias(Cairo::ANTIALIAS_NONE); crMO2->set_line_cap(Cairo::LINE_CAP_SQUARE); crMO2->set_line_join(Cairo::LINE_JOIN_ROUND); @@ -1560,28 +1597,29 @@ void CropWindow::expose (Cairo::RefPtr cr) // clear the bitmap crMO2->set_source_rgba(0., 0., 0., 0.); - crMO2->rectangle(0., 0., crop->getObjectMap2()->get_width(), crop->getObjectMap2()->get_height()); + crMO2->rectangle(0., 0., ObjectMOBuffer::getObjectMap2()->get_width(), ObjectMOBuffer::getObjectMap2()->get_height()); crMO2->set_line_width(0.); crMO2->fill(); } std::vector::const_iterator i; - int a; + int a=0; - for (a = 0, i = mouseOverGeom.begin(); i != mouseOverGeom.end(); ++i, ++a) { - (*i)->drawToMOChannel(crMO, crMO2, a, crop, *this); + for (auto moGeom : mouseOverGeom) { + moGeom->drawToMOChannel(crMO, crMO2, a, this, *this); + ++a; } // Debug code: save the "mouse over" image to a new file at each occurrence #if 0 { static unsigned int count = 0; - int w = crop->getObjectMap()->get_width(); - int h = crop->getObjectMap()->get_height(); + int w = ObjectMOBuffer::getObjectMap()->get_width(); + int h = ObjectMOBuffer::getObjectMap()->get_height(); Glib::RefPtr img = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, false, 8, w, h); guint8 *dst = img->get_pixels(); - unsigned char *src1 = crop->getObjectMap()->get_data(); - unsigned char *src2 = crop->getObjectMode() > OM_255 ? crop->getObjectMap()->get_data() : NULL; + unsigned char *src1 = ObjectMOBuffer::getObjectMap()->get_data(); + unsigned char *src2 = ObjectMOBuffer::getObjectMode() > OM_255 ? ObjectMOBuffer::getObjectMap()->get_data() : NULL; memcpy(dst, src1, w * h); for (int n = 0, n3 = 0; n < w * h;) { @@ -1602,6 +1640,10 @@ void CropWindow::expose (Cairo::RefPtr cr) #endif } } + if (this != iarea->mainCropWindow) { + cr->reset_clip(); + } + } } else { // cropHandler.cropPixbuf is null @@ -1610,14 +1652,14 @@ void CropWindow::expose (Cairo::RefPtr cr) Glib::RefPtr rough = iarea->getPreviewHandler()->getRoughImage (cropX, cropY, imgAreaW, imgAreaH, zoomSteps[cropZoom].zoom); if (rough) { - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + (imgAreaW - rough->get_width()) / 2, y + imgAreaY + (imgAreaH - rough->get_height()) / 2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + imgX, y + imgAreaY + imgY, rtengine::min (rough->get_width (), imgAreaW-imgX), rtengine::min (rough->get_height (), imgAreaH-imgY), Gdk::RGB_DITHER_NORMAL, 0, 0); if (cropHandler.cropParams.enabled) { - drawCrop (cr, x + imgAreaX + (imgAreaW - rough->get_width()) / 2, y + imgAreaY + (imgAreaH - rough->get_height()) / 2, rough->get_width(), rough->get_height(), cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom()); + drawCrop (cr, x + imgAreaX + imgX, y + imgAreaY + imgY, rough->get_width(), rough->get_height(), cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom()); } if (observedCropWin) { - drawObservedFrame (cr, rough->get_width(), rough->get_height()); + drawObservedFrame (cr); } } } @@ -1641,24 +1683,10 @@ void CropWindow::expose (Cairo::RefPtr cr) // printf ("etime --> %d, %d\n", t2.etime (t1), t4.etime (t3)); } -// calculate the center of the zoomed in/out preview given a cursor position -void CropWindow::findCenter (int deltaZoom, int& x, int& y) -{ - int cursorX, cursorY; - screenCoordToImage(x, y, cursorX, cursorY); - - int cropX, cropY, cropW, cropH, skip; - cropHandler.getWindow (cropX, cropY, cropW, cropH, skip); - - int currCenterX = cropX + cropW / 2; - int currCenterY = cropY + cropH / 2; - - int deltaX = currCenterX - cursorX; - int deltaY = currCenterY - cursorY; - - double factor = zoomSteps[cropZoom].zoom / zoomSteps[cropZoom + deltaZoom].zoom; - x = cursorX + (int)((double)(deltaX) * factor); - y = cursorY + (int)((double)(deltaY) * factor); +void CropWindow::setEditSubscriber (EditSubscriber* newSubscriber) { + // Delete, create, update all buffers based upon newSubscriber's type + ObjectMOBuffer::resize(imgAreaW, imgAreaH, newSubscriber); + cropHandler.setEditSubscriber(newSubscriber); } // zoom* is called from the zoomPanel or the scroll wheel in the preview area @@ -1806,7 +1834,7 @@ double CropWindow::getZoomFitVal () } -void CropWindow::zoomFit (bool skipZoomIfUnchanged) +void CropWindow::zoomFit () { double z = cropHandler.getFitZoom (); @@ -1822,7 +1850,7 @@ void CropWindow::zoomFit (bool skipZoomIfUnchanged) } zoomVersion = exposeVersion; - changeZoom (cz, true, -1, -1, skipZoomIfUnchanged); + changeZoom (cz, true, -1, -1); fitZoom = true; } @@ -1845,7 +1873,7 @@ void CropWindow::zoomFitCrop () int centerX, centerY; centerX = cropHandler.cropParams.x + cropHandler.cropParams.w / 2; centerY = cropHandler.cropParams.y + cropHandler.cropParams.h / 2; - changeZoom (cz, true, centerX, centerY, false); + changeZoom (cz, true, centerX, centerY); fitZoom = false; } } @@ -1874,7 +1902,7 @@ void CropWindow::redrawNeeded (LWButton* button) iarea->redraw (); } -void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery, bool skipZoomIfUnchanged) +void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery) { if (zoom < 0) { @@ -1883,19 +1911,14 @@ void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery, b zoom = MAXZOOMSTEPS; } - if (cropZoom == zoom && skipZoomIfUnchanged) { - // We are already at the start/end of the zoom range, so we do nothing - return; - } - cropZoom = zoom; cropLabel = zoomSteps[cropZoom].label; cropHandler.setZoom (zoomSteps[cropZoom].czoom, centerx, centery); if (notify) - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropZoomChanged (this); + for (auto listener : listeners) { + listener->cropZoomChanged (this); } iarea->redraw (); @@ -1905,8 +1928,8 @@ void CropWindow::screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& c { rtengine::Crop* crop = static_cast(cropHandler.getCrop()); - cropx = phyx - xpos - imgX; - cropy = phyy - ypos - imgY; + cropx = phyx - xpos - imgX - imgAreaX; + cropy = phyy - ypos - imgY - imgAreaY; if (zoomSteps[cropZoom].zoom > 1.) { cropx = int(double(cropx) / zoomSteps[cropZoom].zoom); @@ -1926,11 +1949,11 @@ void CropWindow::screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) imgy = cropY + (phyy - ypos - imgY) / zoomSteps[cropZoom].zoom; } -void CropWindow::screenCoordToPreview (int phyx, int phyy, int& prevx, int& prevy) +void CropWindow::screenCoordToCropCanvas (int phyx, int phyy, int& prevx, int& prevy) { - prevx = phyx - xpos - imgX; - prevy = phyy - ypos - imgY; + prevx = phyx - xpos - imgAreaX; + prevy = phyy - ypos - imgAreaY; } void CropWindow::imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) @@ -1938,9 +1961,17 @@ void CropWindow::imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) int cropX, cropY; cropHandler.getPosition (cropX, cropY); - phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + xpos + imgX; - phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + ypos + imgY; - // printf("imgx:%d / imgy:%d / cropX:%d / cropY:%d / xpos:%d / ypos:%d / imgX:%d / imgY:%d / leftBorder: %d / upperBorder:%d / phyx:%d / phyy:%d\n", imgx, imgy, cropX, cropY, xpos, ypos, imgX, imgY, crop->getLeftBorder(), crop->getUpperBorder(), phyx, phyy); + phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + xpos + imgX + imgAreaX; + phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + ypos + imgY + imgAreaY; +} + +void CropWindow::imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy) +{ + + int cropX, cropY; + cropHandler.getPosition (cropX, cropY); + phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + imgX; + phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + imgY; } void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) @@ -1950,7 +1981,6 @@ void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phy cropHandler.getPosition (cropX, cropY); phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + /*xpos + imgX +*/ crop->getLeftBorder(); phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + /*ypos + imgY +*/ crop->getUpperBorder(); - //printf("imgx:%d / imgy:%d / cropX:%d / cropY:%d / xpos:%d / ypos:%d / imgX:%d / imgY:%d / leftBorder: %d / upperBorder:%d / phyx:%d / phyy:%d\n", imgx, imgy, cropX, cropY, xpos, ypos, imgX, imgY, crop->getLeftBorder(), crop->getUpperBorder(), phyx, phyy); } int CropWindow::scaleValueToImage (int value) @@ -1968,17 +1998,17 @@ double CropWindow::scaleValueToImage (double value) return value / zoomSteps[cropZoom].zoom; } -int CropWindow::scaleValueToScreen (int value) +int CropWindow::scaleValueToCanvas (int value) { return int(double(value) * zoomSteps[cropZoom].zoom); } -float CropWindow::scaleValueToScreen (float value) +float CropWindow::scaleValueToCanvas (float value) { return float(double(value) * zoomSteps[cropZoom].zoom); } -double CropWindow::scaleValueToScreen (double value) +double CropWindow::scaleValueToCanvas (double value) { return value * zoomSteps[cropZoom].zoom; } @@ -2113,7 +2143,7 @@ void CropWindow::drawScaledSpotRectangle (Cairo::RefPtr cr, int int x2 = action_x / zoomSteps[cropZoom].zoom + rectSize; cr->set_line_width (1.0); - cr->rectangle (xpos + imgX - 0.5, ypos + imgY - 0.5, imgW, imgH); + cr->rectangle (xpos + imgX + imgAreaX - 0.5, ypos + imgY + imgAreaY - 0.5, imgAreaW, imgAreaH); cr->clip (); cr->set_source_rgb (1.0, 1.0, 1.0); @@ -2135,7 +2165,7 @@ void CropWindow::drawUnscaledSpotRectangle (Cairo::RefPtr cr, in int x2 = action_x + rectSize; cr->set_line_width (1.0); - cr->rectangle (xpos + imgX - 0.5, ypos + imgY - 0.5, imgW, imgH); + cr->rectangle (xpos + imgX + imgAreaX - 0.5, ypos + imgY + imgAreaY - 0.5, imgAreaW, imgAreaH); cr->clip (); cr->set_source_rgb (1.0, 1.0, 1.0); @@ -2151,22 +2181,22 @@ void CropWindow::drawUnscaledSpotRectangle (Cairo::RefPtr cr, in void CropWindow::getObservedFrameArea (int& x, int& y, int& w, int& h, int rw, int rh) { - int cropX, cropY, cropW, cropH; - observedCropWin->getCropRectangle (cropX, cropY, cropW, cropH); - int myCropX, myCropY, myCropW, myCropH; - getCropRectangle (myCropX, myCropY, myCropW, myCropH); + int observedCropX, observedCropY, observedCropW, observedCropH; + observedCropWin->getCropRectangle (observedCropX, observedCropY, observedCropW, observedCropH); + int mainCropX, mainCropY, mainCropW, mainCropH; + getCropRectangle (mainCropX, mainCropY, mainCropW, mainCropH); // translate it to screen coordinates - if (rw) { - x = xpos + imgAreaX + (imgAreaW - rw) / 2 + (cropX - myCropX) * zoomSteps[cropZoom].zoom; - y = ypos + imgAreaY + (imgAreaH - rh) / 2 + (cropY - myCropY) * zoomSteps[cropZoom].zoom; + if (rw) { // rw and rh are the rough image's dimension + x = xpos + imgAreaX + (imgAreaW - rw) / 2 + (observedCropX - mainCropX) * zoomSteps[cropZoom].zoom; + y = ypos + imgAreaY + (imgAreaH - rh) / 2 + (observedCropY - mainCropY) * zoomSteps[cropZoom].zoom; } else { - x = xpos + imgX + (cropX - myCropX) * zoomSteps[cropZoom].zoom; - y = ypos + imgY + (cropY - myCropY) * zoomSteps[cropZoom].zoom; + x = xpos + imgX + (observedCropX - mainCropX) * zoomSteps[cropZoom].zoom; + y = ypos + imgY + (observedCropY - mainCropY) * zoomSteps[cropZoom].zoom; } - w = cropW * zoomSteps[cropZoom].zoom; - h = cropH * zoomSteps[cropZoom].zoom; + w = observedCropW * zoomSteps[cropZoom].zoom; + h = observedCropH * zoomSteps[cropZoom].zoom; } void CropWindow::drawObservedFrame (Cairo::RefPtr cr, int rw, int rh) @@ -2206,35 +2236,35 @@ void CropWindow::cropWindowChanged () void CropWindow::initialImageArrived () { - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->initialImageArrived (this); + for (auto listener : listeners) { + listener->initialImageArrived (this); } } +void CropWindow::setDisplayPosition (int x, int y) { + imgX = x; + imgY = y; +} void CropWindow::remoteMove (int deltaX, int deltaY) { state = SCropImgMove; - action_x = deltaX; - action_y = deltaY; + cropHandler.moveAnchor(deltaX, deltaY, false); - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropPositionChanged (this); + for (auto listener : listeners) { + listener->cropPositionChanged (this); } } void CropWindow::remoteMoveReady () { - int cropX, cropY; - cropHandler.getPosition (cropX, cropY); - cropHandler.setPosition (cropX + action_x, cropY + action_y); - cropHandler.getPosition (cropX, cropY); + cropHandler.update (); state = SNormal; - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropPositionChanged (this); + for (auto listener : listeners) { + listener->cropPositionChanged (this); } } diff --git a/rtgui/cropwindow.h b/rtgui/cropwindow.h index aad6b9ef5..c74664814 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -28,6 +28,7 @@ #include #include "cropguilistener.h" #include "pointermotionlistener.h" +#include "edit.h" class CropWindow; class CropWindowListener @@ -42,12 +43,13 @@ public: }; class ImageArea; -class CropWindow : public LWButtonListener, public CropHandlerListener, public EditCoordSystem +class CropWindow : public LWButtonListener, public CropDisplayHandler, public EditCoordSystem, public ObjectMOBuffer { // state management - ImgEditState state; // current state of user (see enum State) - int action_x, action_y, press_x, press_y; + ImgEditState state; // current state of user (see enum State) + int press_x, press_y; // position of the cursor in the GUI space on button press + int action_x, action_y; // parameter that will evolve during a pan or drag action double rot_deg; bool onResizeArea; bool deleted; @@ -85,7 +87,7 @@ class CropWindow : public LWButtonListener, public CropHandlerListener, public E PointerMotionListener* pmhlistener; std::list listeners; - CropWindow* observedCropWin; + CropWindow* observedCropWin; // Pointer to the currently active detail CropWindow rtengine::StagedImageProcessor* ipc; bool onArea (CursorArea a, int x, int y); @@ -95,7 +97,9 @@ class CropWindow : public LWButtonListener, public CropHandlerListener, public E void drawScaledSpotRectangle (Cairo::RefPtr cr, int rectSize); void drawUnscaledSpotRectangle (Cairo::RefPtr cr, int rectSize); void drawObservedFrame (Cairo::RefPtr cr, int rw = 0, int rh = 0); - void changeZoom (int zoom, bool notify = true, int centerx = -1, int centery = -1, bool skipZoomIfUnchanged = true); + void changeZoom (int zoom, bool notify = true, int centerx = -1, int centery = -1); + + // Used by the mainCropWindow only void getObservedFrameArea (int& x, int& y, int& w, int& h, int rw = 0, int rh = 0); public: @@ -117,15 +121,16 @@ public: void screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy); void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy); - void screenCoordToPreview (int phyx, int phyy, int& prevx, int& prevy); + void screenCoordToCropCanvas (int phyx, int phyy, int& prevx, int& prevy); + void imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy); void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy); void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy); int scaleValueToImage (int value); float scaleValueToImage (float value); double scaleValueToImage (double value); - int scaleValueToScreen (int value); - float scaleValueToScreen (float value); - double scaleValueToScreen (double value); + int scaleValueToCanvas (int value); + float scaleValueToCanvas (float value); + double scaleValueToCanvas (double value); double getZoomFitVal (); void setPosition (int x, int y); void getPosition (int& x, int& y); @@ -140,14 +145,13 @@ public: void zoomIn (bool toCursor = false, int cursorX = -1, int cursorY = -1); void zoomOut (bool toCursor = false, int cursorX = -1, int cursorY = -1); void zoom11 (); - void zoomFit (bool skipZoomIfUnchanged = true); + void zoomFit (); void zoomFitCrop (); double getZoom (); bool isMinZoom (); bool isMaxZoom (); void setZoom (double zoom); - void findCenter (int deltaZoom, int& x, int& y); bool isInside (int x, int y); @@ -157,15 +161,20 @@ public: void expose (Cairo::RefPtr cr); + void setEditSubscriber (EditSubscriber* newSubscriber); + // interface lwbuttonlistener void buttonPressed (LWButton* button, int actionCode, void* actionData); void redrawNeeded (LWButton* button); // crop handling - void getCropRectangle (int& x, int& y, int& w, int& h); - void getCropPosition (int& x, int& y); - void setCropPosition (int x, int y, bool update = true); - void getCropSize (int& w, int& h); + void getCropRectangle (int& x, int& y, int& w, int& h); + void getCropPosition (int& x, int& y); + void setCropPosition (int x, int y, bool update = true); + void centerCrop (bool update = true); + void getCropSize (int& w, int& h); + void getCropAnchorPosition (int& w, int& h); + void setCropAnchorPosition (int& w, int& h); // listeners void setCropGUIListener (CropGUIListener* cgl) @@ -192,6 +201,7 @@ public: void cropImageUpdated (); void cropWindowChanged (); void initialImageArrived (); + void setDisplayPosition (int x, int y); void remoteMove (int deltaX, int deltaY); void remoteMoveReady (); diff --git a/rtgui/edit.cc b/rtgui/edit.cc index 3efdea7f4..d88e2bcb3 100644 --- a/rtgui/edit.cc +++ b/rtgui/edit.cc @@ -18,9 +18,119 @@ */ #include "edit.h" -#include "../rtengine/editbuffer.h" #include "rtimage.h" +ObjectMOBuffer::ObjectMOBuffer(EditDataProvider *dataProvider) : objectMap(NULL), objectMap2(NULL), objectMode(OM_255), dataProvider(dataProvider) {} + +ObjectMOBuffer::~ObjectMOBuffer() +{ + flush(); +} + + +/* Upgrade or downgrade the objectModeType; we're assuming that objectMap has been allocated */ +void ObjectMOBuffer::setObjectMode(ObjectMode newType) +{ + switch (newType) { + case (OM_255): + if (objectMap2) { + objectMap2->unreference(); + } + + objectMode = OM_255; + break; + + case (OM_65535): + if (!objectMap2) { + objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, objectMap->get_width(), objectMap->get_height()); + } + + objectMode = OM_65535; + break; + } +} + +void ObjectMOBuffer::flush() +{ + if (objectMap ) { + objectMap.clear(); + } + + if (objectMap2) { + objectMap2.clear(); + } +} + +EditSubscriber *ObjectMOBuffer::getEditSubscriber () { + if (dataProvider) { + return dataProvider->getCurrSubscriber(); + } else { + return NULL; + } +} + + +// Resize buffers if they already exist +void ObjectMOBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscriber) +{ + if (newSubscriber) { + if (newSubscriber->getEditingType() == ET_OBJECTS) { + if (objectMap && (objectMap->get_width() != newWidth || objectMap->get_height() != newHeight)) { + objectMap.clear(); + } + + if (!objectMap && newWidth>0 && newHeight>0) { + objectMap = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); + } + + if (objectMode == OM_65535) { + if (objectMap2) { + if (objectMap2->get_width() != newWidth || objectMap2->get_height() != newHeight) { + objectMap2.clear(); + } + } + + if (!objectMap2 && newWidth>0 && newHeight>0) { + objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); + } + } else if (objectMap2) { + // OM_255 -> deleting objectMap2, if any + objectMap2.clear(); + } + } else { + flush(); + } + } else { + flush(); + } +} + +int ObjectMOBuffer::getObjectID(const rtengine::Coord& location) +{ + int id = 0; + + if (objectMap && location.x > 0 && location.y > 0 && location.x < objectMap->get_width() && location.y < objectMap->get_height()) { + id = (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )); + + if (objectMap2) { + id |= (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )) << 8; + } + } + + return id - 1; +} + +bool ObjectMOBuffer::bufferCreated() +{ + EditSubscriber* subscriber; + + if (dataProvider && (subscriber = dataProvider->getCurrSubscriber())) { + return subscriber->getEditingType() == ET_OBJECTS ? bool(objectMap) : false; + } + + return false; +} + RGBColor Geometry::getInnerLineColor () { RGBColor color; @@ -60,7 +170,7 @@ RGBColor Geometry::getOuterLineColor () return color; } -void Circle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Circle::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && state != INSENSITIVE) { RGBColor color; @@ -75,14 +185,14 @@ void Circle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::Edit cr->set_line_width( getOuterLineWidth() ); rtengine::Coord center_ = center; - double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); + double radius_ = radiusInImageSpace ? coordSystem.scaleValueToCanvas(double(radius)) : double(radius); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y); + coordSystem.imageCoordToScreen (center.x, center.y, center_.x, center_.y); } else if (datum == CLICKED_POINT) { - center_ += editBuffer->getDataProvider()->posScreen; + center_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + center_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*M_PI); @@ -90,7 +200,7 @@ void Circle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::Edit } } -void Circle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Circle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_VISIBLE) { if (state != INSENSITIVE) { @@ -108,14 +218,14 @@ void Circle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Edit cr->set_line_width( innerLineWidth ); rtengine::Coord center_ = center; - double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); + double radius_ = radiusInImageSpace ? coordSystem.scaleValueToCanvas(double(radius)) : double(radius); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y); + coordSystem.imageCoordToScreen (center.x, center.y, center_.x, center_.y); } else if (datum == CLICKED_POINT) { - center_ += editBuffer->getDataProvider()->posScreen; + center_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + center_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (filled && state != INSENSITIVE) { @@ -147,19 +257,19 @@ void Circle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Edit } } -void Circle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Circle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_HOVERABLE) { cr->set_line_width( getMouseOverLineWidth() ); rtengine::Coord center_ = center; - double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); + double radius_ = radiusInImageSpace ? coordSystem.scaleValueToCanvas(double(radius)) : double(radius); if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(center.x, center.y, center_.x, center_.y); + coordSystem.imageCoordToCropCanvas (center.x, center.y, center_.x, center_.y); } else if (datum == CLICKED_POINT) { - center_ += editBuffer->getDataProvider()->posScreen; + center_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + center_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } // drawing the lower byte's value @@ -179,7 +289,7 @@ void Circle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtrgetObjectMode() == OM_65535) { + if (objectBuffer->getObjectMode() == OM_65535) { a = (id + 1) >> 8; cr2->set_source_rgba (0., 0., 0., double(a) / 255.); cr2->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0, 2.*M_PI); @@ -198,7 +308,7 @@ void Circle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Line::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && state != INSENSITIVE) { RGBColor color; @@ -216,14 +326,14 @@ void Line::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBu rtengine::Coord end_ = end; if (datum == IMAGE) { - coordSystem.imageCoordToScreen(begin.x, begin.y, begin_.x, begin_.y); - coordSystem.imageCoordToScreen(end.x, end.y, end_.x, end_.y); + coordSystem.imageCoordToScreen (begin.x, begin.y, begin_.x, begin_.y); + coordSystem.imageCoordToScreen (end.x, end.y, end_.x, end_.y); } else if (datum == CLICKED_POINT) { - begin_ += editBuffer->getDataProvider()->posScreen; - end_ += editBuffer->getDataProvider()->posScreen; + begin_ += objectBuffer->getDataProvider()->posScreen; + end_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; - end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + begin_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; + end_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } cr->move_to(begin_.x + 0.5, begin_.y + 0.5); @@ -232,7 +342,7 @@ void Line::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBu } } -void Line::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Line::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && innerLineWidth > 0.) { if (state != INSENSITIVE) { @@ -253,14 +363,14 @@ void Line::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBu rtengine::Coord end_ = end; if (datum == IMAGE) { - coordSystem.imageCoordToScreen(begin.x, begin.y, begin_.x, begin_.y); - coordSystem.imageCoordToScreen(end.x, end.y, end_.x, end_.y); + coordSystem.imageCoordToScreen (begin.x, begin.y, begin_.x, begin_.y); + coordSystem.imageCoordToScreen (end.x, end.y, end_.x, end_.y); } else if (datum == CLICKED_POINT) { - begin_ += editBuffer->getDataProvider()->posScreen; - end_ += editBuffer->getDataProvider()->posScreen; + begin_ += objectBuffer->getDataProvider()->posScreen; + end_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; - end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + begin_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; + end_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } cr->move_to(begin_.x + 0.5, begin_.y + 0.5); @@ -284,7 +394,7 @@ void Line::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBu void Line::drawToMOChannel(Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, - rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) + ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_HOVERABLE) { cr->set_line_width( getMouseOverLineWidth() ); @@ -292,14 +402,14 @@ void Line::drawToMOChannel(Cairo::RefPtr &cr, rtengine::Coord end_ = end; if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(begin.x, begin.y, begin_.x, begin_.y); - coordSystem.imageCoordToCropBuffer(end.x, end.y, end_.x, end_.y); + coordSystem.imageCoordToCropCanvas (begin.x, begin.y, begin_.x, begin_.y); + coordSystem.imageCoordToCropCanvas (end.x, end.y, end_.x, end_.y); } else if (datum == CLICKED_POINT) { - begin_ += editBuffer->getDataProvider()->posScreen; - end_ += editBuffer->getDataProvider()->posScreen; + begin_ += objectBuffer->getDataProvider()->posScreen; + end_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; - end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + begin_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; + end_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } // drawing the lower byte's value @@ -310,7 +420,7 @@ void Line::drawToMOChannel(Cairo::RefPtr &cr, cr->stroke(); // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { + if (objectBuffer->getObjectMode() == OM_65535) { a = (id + 1) >> 8; cr2->set_source_rgba (0., 0., 0., double(a) / 255.); cr2->move_to(begin_.x + 0.5, begin_.y + 0.5); @@ -320,7 +430,7 @@ void Line::drawToMOChannel(Cairo::RefPtr &cr, } } -void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && state != INSENSITIVE && points.size() > 1) { RGBColor color; @@ -340,11 +450,11 @@ void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::Ed currPos = points.at(i); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + coordSystem.imageCoordToScreen (points.at(i).x, points.at(i).y, currPos.x, currPos.y); } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; + currPos += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + currPos += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (!i) { @@ -363,7 +473,7 @@ void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::Ed } } -void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && points.size() > 1) { if (state != INSENSITIVE) { @@ -387,11 +497,11 @@ void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Ed currPos = points.at(i); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + coordSystem.imageCoordToScreen (points.at(i).x, points.at(i).y, currPos.x, currPos.y); } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; + currPos += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + currPos += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (!i) { @@ -414,11 +524,11 @@ void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Ed currPos = points.at(i); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + coordSystem.imageCoordToScreen (points.at(i).x, points.at(i).y, currPos.x, currPos.y); } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; + currPos += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + currPos += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (!i) { @@ -445,7 +555,7 @@ void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Ed } } -void Polyline::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Polyline::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_HOVERABLE) && points.size() > 1) { rtengine::Coord currPos; @@ -459,11 +569,11 @@ void Polyline::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr currPos = points.at(i); if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + coordSystem.imageCoordToCropCanvas (points.at(i).x, points.at(i).y, currPos.x, currPos.y); } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; + currPos += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + currPos += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (!i) { @@ -485,7 +595,7 @@ void Polyline::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr } // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { + if (objectBuffer->getObjectMode() == OM_65535) { a = (id + 1) >> 8; cr2->set_source_rgba (0., 0., 0., double(a) / 255.); @@ -494,11 +604,11 @@ void Polyline::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr currPos = points.at(i); if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + coordSystem.imageCoordToCropCanvas (points.at(i).x, points.at(i).y, currPos.x, currPos.y); } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; + currPos += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + currPos += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (!i) { @@ -546,7 +656,7 @@ void Rectangle::setXYXY(rtengine::Coord topLeft, rtengine::Coord bottomRight) this->bottomRight = bottomRight; } -void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && state != INSENSITIVE) { RGBColor color; @@ -563,19 +673,19 @@ void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::E rtengine::Coord tl, br; if (datum == IMAGE) { - coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y); + coordSystem.imageCoordToScreen (topLeft.x, topLeft.y, tl.x, tl.y); } else if (datum == CLICKED_POINT) { - tl = topLeft + editBuffer->getDataProvider()->posScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - tl = topLeft + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (datum == IMAGE) { - coordSystem.imageCoordToScreen(bottomRight.x, bottomRight.y, br.x, br.y); + coordSystem.imageCoordToScreen (bottomRight.x, bottomRight.y, br.x, br.y); } else if (datum == CLICKED_POINT) { - br = bottomRight + editBuffer->getDataProvider()->posScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - br = bottomRight + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); @@ -589,7 +699,7 @@ void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::E } } -void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_VISIBLE) { if (state != INSENSITIVE) { @@ -609,19 +719,19 @@ void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::E rtengine::Coord tl, br; if (datum == IMAGE) { - coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y); + coordSystem.imageCoordToScreen (topLeft.x, topLeft.y, tl.x, tl.y); } else if (datum == CLICKED_POINT) { - tl = topLeft + editBuffer->getDataProvider()->posScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - tl = topLeft + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (datum == IMAGE) { - coordSystem.imageCoordToScreen(bottomRight.x, bottomRight.y, br.x, br.y); + coordSystem.imageCoordToScreen (bottomRight.x, bottomRight.y, br.x, br.y); } else if (datum == CLICKED_POINT) { - br = bottomRight + editBuffer->getDataProvider()->posScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - br = bottomRight + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (filled && state != INSENSITIVE) { @@ -653,7 +763,7 @@ void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::E } } -void Rectangle::drawToMOChannel(Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Rectangle::drawToMOChannel(Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_HOVERABLE) { cr->set_line_width( getMouseOverLineWidth() ); @@ -661,19 +771,19 @@ void Rectangle::drawToMOChannel(Cairo::RefPtr &cr, Cairo::RefPtr rtengine::Coord tl, br; if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(topLeft.x, topLeft.y, tl.x, tl.y); + coordSystem.imageCoordToCropCanvas (topLeft.x, topLeft.y, tl.x, tl.y); } else if (datum == CLICKED_POINT) { - tl = topLeft + editBuffer->getDataProvider()->posScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - tl = topLeft + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(bottomRight.x, bottomRight.y, br.x, br.y); + coordSystem.imageCoordToCropCanvas (bottomRight.x, bottomRight.y, br.x, br.y); } else if (datum == CLICKED_POINT) { - br = bottomRight + editBuffer->getDataProvider()->posScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - br = bottomRight + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } // drawing the lower byte's value @@ -693,7 +803,7 @@ void Rectangle::drawToMOChannel(Cairo::RefPtr &cr, Cairo::RefPtr } // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { + if (objectBuffer->getObjectMode() == OM_65535) { a = (id + 1) >> 8; cr2->set_source_rgba (0., 0., 0., double(a) / 255.); cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); @@ -766,7 +876,7 @@ EditType EditSubscriber::getEditingType() return editingType; } -BufferType EditSubscriber::getEditBufferType() +BufferType EditSubscriber::getPipetteBufferType() { return bufferType; } diff --git a/rtgui/edit.h b/rtgui/edit.h index c8b8090fb..b1acf7e15 100644 --- a/rtgui/edit.h +++ b/rtgui/edit.h @@ -29,11 +29,7 @@ #include "options.h" class EditDataProvider; - -namespace rtengine -{ -class EditBuffer; -} +class EditSubscriber; /** @file * @@ -41,9 +37,6 @@ class EditBuffer; * Subscribers will be tools that need to create some graphics in the preview area, to let the user interact * with it in a more user friendly way. * - * Subscribers will be tools that need to create some graphics in the preview area, to let the user interact - * with it in a more user friendly way. - * * Do not confuse with _local_ editing, which is another topic implemented in another class. The Edit feature * is also not supported in batch editing from the File Browser. * @@ -84,7 +77,7 @@ class EditBuffer; * * ## Object edition * - * By using this class, object can be drawn and manipulated on the preview. + * By using this class, objects can be drawn and manipulated on the preview. * * The developer has to handle the buttonPress, buttonRelease, drag and mouseOver method that he needs. There * are buttonPress, buttonRelease and drag methods dedicated to each mouse button, for better flexibility @@ -92,7 +85,7 @@ class EditBuffer; * does not handle multiple mouse button event (e.g. button1 + button2), only one at a time. The first button pressed * set the mechanism, all other combined button press are ignored. * - * The developer also have to fill 2 display list with object of the Geometry subclass. Each geometrical shape + * The developer also have to fill 2 display list with object of the Geometry subclass. Each geometric shape * _can_ be used in one or the other, or both list at a time. * * The first list (visibleGeometry) is used to be displayed on the preview. The developer will have to set their state @@ -152,6 +145,59 @@ class EditBuffer; * */ + + +class ObjectMOBuffer +{ +private: + + // Used to draw the objects where the color correspond to the object's ID, in order to find the correct object when hovering + Cairo::RefPtr objectMap; + // If more than 254 objects has to be handled, objectMap2 contains the "upper part" of the 16 bit int value. objectMap2 will be NULL otherwise. + Cairo::RefPtr objectMap2; + ObjectMode objectMode; + +protected: + + // To avoid duplicated information, we points to a EditDataProvider that contains the current EditSubscriber + // instead of pointing to the EditSubscriber directly + EditDataProvider* dataProvider; + + void createBuffer(int width, int height); + void resize(int newWidth, int newHeight, EditSubscriber* newSubscriber); + void flush(); + EditSubscriber *getEditSubscriber (); + +public: + ObjectMOBuffer(EditDataProvider *dataProvider); + ~ObjectMOBuffer(); + + EditDataProvider* getDataProvider() + { + return dataProvider; + } + void setObjectMode(ObjectMode newType); + ObjectMode getObjectMode() + { + return objectMode; + } + + Cairo::RefPtr &getObjectMap () + { + return objectMap; + } + Cairo::RefPtr &getObjectMap2() + { + return objectMap2; + } + + // return true if the buffer has been allocated + bool bufferCreated(); + + int getObjectID(const rtengine::Coord& location); +}; + + /** @brief Coordinate system where the widgets will be drawn * * The EditCoordSystem is used to define a screen and an image coordinate system. @@ -167,6 +213,8 @@ public: virtual void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) = 0; /// Convert the image coords to the widget's DrawingArea (i.e. preview area) coords virtual void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) = 0; + /// Convert the image coords to the crop's canvas coords + virtual void imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy) = 0; /// Convert the image coords to the edit buffer coords virtual void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) = 0; /// Convert a size value from the preview's scale to the image's scale @@ -176,11 +224,11 @@ public: /// Convert a size value from the preview's scale to the image's scale virtual double scaleValueToImage (double value) = 0; /// Convert a size value from the image's scale to the preview's scale - virtual int scaleValueToScreen (int value) = 0; + virtual int scaleValueToCanvas (int value) = 0; /// Convert a size value from the image's scale to the preview's scale - virtual float scaleValueToScreen (float value) = 0; + virtual float scaleValueToCanvas (float value) = 0; /// Convert a size value from the image's scale to the preview's scale - virtual double scaleValueToScreen (double value) = 0; + virtual double scaleValueToCanvas (double value) = 0; }; class RGBColor @@ -373,9 +421,9 @@ public: } } - virtual void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *parent, EditCoordSystem &coordSystem) = 0; - virtual void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *parent, EditCoordSystem &coordSystem) = 0; - virtual void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) = 0; + virtual void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *parent, EditCoordSystem &coordSystem) = 0; + virtual void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *parent, EditCoordSystem &coordSystem) = 0; + virtual void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem) = 0; }; class Circle : public Geometry @@ -390,9 +438,9 @@ public: Circle (rtengine::Coord ¢er, int radius, bool filled = false, bool radiusInImageSpace = false) : center(center), radius(radius), filled(filled), radiusInImageSpace(radiusInImageSpace) {} Circle (int centerX, int centerY, int radius, bool filled = false, bool radiusInImageSpace = false) : center(centerX, centerY), radius(radius), filled(filled), radiusInImageSpace(radiusInImageSpace) {} - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); }; class Line : public Geometry @@ -405,9 +453,9 @@ public: Line (rtengine::Coord &begin, rtengine::Coord &end) : begin(begin), end(end) {} Line (int beginX, int beginY, int endX, int endY) : begin(beginX, beginY), end(endX, endY) {} - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); }; class Polyline : public Geometry @@ -418,9 +466,9 @@ public: Polyline() : filled(false) {} - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); }; class Rectangle : public Geometry @@ -436,9 +484,9 @@ public: void setXYXY(int left, int top, int right, int bottom); void setXYWH(rtengine::Coord topLeft, rtengine::Coord widthHeight); void setXYXY(rtengine::Coord topLeft, rtengine::Coord bottomRight); - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem); }; /// @brief Method for client tools needing Edit information @@ -474,7 +522,7 @@ public: virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode EditUniqueID getEditID(); EditType getEditingType(); - BufferType getEditBufferType(); + BufferType getPipetteBufferType(); bool isDragging(); /// Returns true if something is being dragged and drag events has to be sent (object mode only) /** @brief Get the cursor to be displayed when above handles @@ -487,7 +535,6 @@ public: /** @brief Triggered when the mouse is moving over an object This method is also triggered when the cursor is moving over the image in ET_PIPETTE mode @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) - @param editBuffer buffer to get the pipette values and the from @return true if the preview has to be redrawn, false otherwise */ virtual bool mouseOver(int modifierKey) { diff --git a/rtgui/gradient.cc b/rtgui/gradient.cc index 49cc3ee59..352183d18 100644 --- a/rtgui/gradient.cc +++ b/rtgui/gradient.cc @@ -136,88 +136,99 @@ void Gradient::read (const ProcParams* pp, const ParamsEdited* pedited) enableListener (); } -void Gradient::updateGeometry(int centerX_, int centerY_, double feather_, double degree_) +void Gradient::updateGeometry(const int centerX_, const int centerY_, const double feather_, const double degree_, const int fullWidth, const int fullHeight) { EditDataProvider* dataProvider = getEditProvider(); - if (dataProvider) { - int imW, imH; - PolarCoord polCoord1, polCoord2; - dataProvider->getImageSize(imW, imH); - double decay = feather_ * sqrt(double(imW) * double(imW) + double(imH) * double(imH)) / 200.; - - rtengine::Coord origin(imW / 2 + centerX_ * imW / 200.f, imH / 2 + centerY_ * imH / 200.f); - - Line *currLine; - Circle *currCircle; - // update horizontal line - currLine = static_cast(visibleGeometry.at(0)); - polCoord1.set(1500.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1); - currLine->begin += origin; - polCoord1.set(1500.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1); - currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(0)); - polCoord1.set(1500.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1); - currLine->begin += origin; - polCoord1.set(1500.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1); - currLine->end += origin; - // update vertical line - currLine = static_cast(visibleGeometry.at(1)); - polCoord1.set( 700.f, float(-degree_ + 90 )); - currLine->begin.setFromPolar(polCoord1); - currLine->begin += origin; - polCoord1.set( 700.f, float(-degree_ + 270)); - currLine->end.setFromPolar (polCoord1); - currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(1)); - polCoord1.set( 700.f, float(-degree_ + 90 )); - currLine->begin.setFromPolar(polCoord1); - currLine->begin += origin; - polCoord1.set( 700.f, float(-degree_ + 270)); - currLine->end.setFromPolar (polCoord1); - currLine->end += origin; - // update upper feather line - currLine = static_cast(visibleGeometry.at(2)); - polCoord2.set(decay, float(-degree_ + 270)); - polCoord1.set(350.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1 + polCoord2); - currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1 + polCoord2); - currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(2)); - polCoord1.set(350.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1 + polCoord2); - currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1 + polCoord2); - currLine->end += origin; - // update lower feather line - currLine = static_cast(visibleGeometry.at(3)); - polCoord2.set(decay, float(-degree_ + 90)); - polCoord1.set(350.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1 + polCoord2); - currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1 + polCoord2); - currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(3)); - polCoord1.set(350.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1 + polCoord2); - currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1 + polCoord2); - currLine->end += origin; - // update circle's position - currCircle = static_cast(visibleGeometry.at(4)); - currCircle->center = origin; - currCircle = static_cast(mouseOverGeometry.at(4)); - currCircle->center = origin; + if (!dataProvider) { + return; } + + int imW, imH; + if (fullWidth != -1 && fullHeight != -1) { + imW = fullWidth; + imH = fullHeight; + } else { + dataProvider->getImageSize(imW, imH); + if (!imW || !imH) { + return; + } + } + + PolarCoord polCoord1, polCoord2; + double decay = feather_ * sqrt(double(imW) * double(imW) + double(imH) * double(imH)) / 200.; + + rtengine::Coord origin(imW / 2 + centerX_ * imW / 200.f, imH / 2 + centerY_ * imH / 200.f); + + Line *currLine; + Circle *currCircle; + // update horizontal line + currLine = static_cast(visibleGeometry.at(0)); + polCoord1.set(1500.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1); + currLine->begin += origin; + polCoord1.set(1500.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1); + currLine->end += origin; + currLine = static_cast(mouseOverGeometry.at(0)); + polCoord1.set(1500.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1); + currLine->begin += origin; + polCoord1.set(1500.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1); + currLine->end += origin; + // update vertical line + currLine = static_cast(visibleGeometry.at(1)); + polCoord1.set( 700.f, float(-degree_ + 90 )); + currLine->begin.setFromPolar(polCoord1); + currLine->begin += origin; + polCoord1.set( 700.f, float(-degree_ + 270)); + currLine->end.setFromPolar (polCoord1); + currLine->end += origin; + currLine = static_cast(mouseOverGeometry.at(1)); + polCoord1.set( 700.f, float(-degree_ + 90 )); + currLine->begin.setFromPolar(polCoord1); + currLine->begin += origin; + polCoord1.set( 700.f, float(-degree_ + 270)); + currLine->end.setFromPolar (polCoord1); + currLine->end += origin; + // update upper feather line + currLine = static_cast(visibleGeometry.at(2)); + polCoord2.set(decay, float(-degree_ + 270)); + polCoord1.set(350.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1 + polCoord2); + currLine->begin += origin; + polCoord1.set(350.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1 + polCoord2); + currLine->end += origin; + currLine = static_cast(mouseOverGeometry.at(2)); + polCoord1.set(350.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1 + polCoord2); + currLine->begin += origin; + polCoord1.set(350.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1 + polCoord2); + currLine->end += origin; + // update lower feather line + currLine = static_cast(visibleGeometry.at(3)); + polCoord2.set(decay, float(-degree_ + 90)); + polCoord1.set(350.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1 + polCoord2); + currLine->begin += origin; + polCoord1.set(350.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1 + polCoord2); + currLine->end += origin; + currLine = static_cast(mouseOverGeometry.at(3)); + polCoord1.set(350.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1 + polCoord2); + currLine->begin += origin; + polCoord1.set(350.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1 + polCoord2); + currLine->end += origin; + // update circle's position + currCircle = static_cast(visibleGeometry.at(4)); + currCircle->center = origin; + currCircle = static_cast(mouseOverGeometry.at(4)); + currCircle->center = origin; } void Gradient::write (ProcParams* pp, ParamsEdited* pedited) @@ -399,7 +410,7 @@ bool Gradient::button1Pressed(int modifierKey) { EditDataProvider *provider = getEditProvider(); - if (!(modifierKey & GDK_CONTROL_MASK)) { + if (!(modifierKey & GDK_CONTROL_MASK) && lastObject > -1) { // button press is valid (no modifier key) PolarCoord pCoord; int imW, imH; @@ -447,20 +458,20 @@ bool Gradient::button1Pressed(int modifierKey) EditSubscriber::dragging = true; return false; - } else { + } else if (lastObject > -1) { // should theoretically always be true // this will let this class ignore further drag events - if (lastObject > -1) { // should theoretically always be true - if (lastObject == 2 || lastObject == 3) { - EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL; - EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL; - } else { - EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL; - } + if (lastObject == 2 || lastObject == 3) { + EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL; + EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL; + } else { + EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL; } lastObject = -1; return true; } + + return false; } bool Gradient::button1Released() diff --git a/rtgui/gradient.h b/rtgui/gradient.h index 4117c3859..67cb5b2fc 100644 --- a/rtgui/gradient.h +++ b/rtgui/gradient.h @@ -42,12 +42,11 @@ public: void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void updateGeometry (int centerX_, int centerY_, double feather_, double degree_); - void adjusterChanged (Adjuster* a, double newval); void enabledChanged (); void setAdjusterBehavior (bool degreeadd, bool featheradd, bool strengthadd, bool centeradd); void trimValues (rtengine::procparams::ProcParams* pp); + void updateGeometry (const int centerX_, const int centerY_, const double feather_, const double degree_, const int fullWidth=-1, const int fullHeight=-1); void setEditProvider (EditDataProvider* provider); diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index b77e90f09..15ef36078 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -56,8 +56,8 @@ ImageArea::ImageArea (ImageAreaPanel* p) : parent(p), firstOpen(true) ImageArea::~ImageArea () { - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - delete *i; + for (auto cropWin : cropWins) { + delete cropWin; } cropWins.clear (); @@ -110,10 +110,9 @@ void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) { if( !ipc_ ) { focusGrabber = NULL; - std::list::iterator i = cropWins.begin(); - for( ; i != cropWins.end(); i++ ) { - delete *i; + for (auto cropWin : cropWins) { + delete cropWin; } cropWins.clear(); @@ -170,10 +169,11 @@ CropWindow* ImageArea::getCropWindow (int x, int y) CropWindow* cw = mainCropWindow; - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) - if ((*i)->isInside (x, y)) { - return *i; + for (auto cropWin : cropWins) { + if (cropWin->isInside (x, y)) { + return cropWin; } + } return cw; } @@ -200,7 +200,6 @@ bool ImageArea::on_expose_event(GdkEventExpose* event) Cairo::RefPtr cr = get_window()->create_cairo_context(); if (mainCropWindow) { - //printf("MainCropWindow (%d x %d)\n", window->get_width(), window->get_height()); mainCropWindow->expose (cr); } @@ -275,11 +274,11 @@ bool ImageArea::on_scroll_event (GdkEventScroll* event) int newCenterX = (int)event->x; int newCenterY = (int)event->y; + cw->screenCoordToImage(newCenterX, newCenterY, newCenterX, newCenterY); + if (event->direction == GDK_SCROLL_UP && !cw->isMaxZoom()) { - cw->findCenter (1, newCenterX, newCenterY); cw->zoomIn (true, newCenterX, newCenterY); } else if (!cw->isMinZoom()) { - cw->findCenter (-1, newCenterX, newCenterY); cw->zoomOut (true, newCenterX, newCenterY); } } @@ -327,10 +326,10 @@ bool ImageArea::on_leave_notify_event (GdkEventCrossing* event) void ImageArea::subscribe(EditSubscriber *subscriber) { - mainCropWindow->cropHandler.setEditSubscriber(subscriber); + mainCropWindow->setEditSubscriber(subscriber); - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->cropHandler.setEditSubscriber(subscriber); + for (auto cropWin : cropWins) { + cropWin->setEditSubscriber(subscriber); } EditDataProvider::subscribe(subscriber); @@ -339,7 +338,7 @@ void ImageArea::subscribe(EditSubscriber *subscriber) listener->getToolBar()->startEditMode (); } - if (subscriber->getEditingType() == ET_OBJECTS) { + if (subscriber && subscriber->getEditingType() == ET_OBJECTS) { // In this case, no need to reprocess the image, so we redraw the image to display the geometry queue_draw(); } @@ -358,8 +357,8 @@ void ImageArea::unsubscribe() // Ask the Crops to free-up edit mode buffers mainCropWindow->cropHandler.setEditSubscriber(NULL); - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->cropHandler.setEditSubscriber(NULL); + for (auto cropWin : cropWins) { + cropWin->cropHandler.setEditSubscriber(NULL); } setToolHand(); @@ -473,12 +472,10 @@ void ImageArea::addCropWindow () y = cropheight * (N % maxRows); cw->setPosition (x, y); + cw->setEditSubscriber (getCurrSubscriber()); cw->enable(); // start processing! - int x0, y0, w, h, wc, hc; - mainCropWindow->getCropRectangle(x0, y0, w, h ); - cw->getCropSize(wc, hc); - cw->setCropPosition(x0 + w / 2 - wc / 2, y0 + h / 2 - hc / 2); + cw->centerCrop(); mainCropWindow->setObservedCropWin (cropWins.front()); if(cropWins.size() == 1) { // after first detail window we already have high quality @@ -539,9 +536,8 @@ void ImageArea::getScrollImageSize (int& w, int& h) { if (mainCropWindow && ipc) { - double z = mainCropWindow->getZoom (); - w = ipc->getFullWidth() * z; - h = ipc->getFullHeight() * z; + w = ipc->getFullWidth(); + h = ipc->getFullHeight(); } else { w = h = 0; } @@ -551,10 +547,7 @@ void ImageArea::getScrollPosition (int& x, int& y) { if (mainCropWindow) { - int cropX, cropY; - mainCropWindow->getCropPosition (cropX, cropY); - x = cropX * mainCropWindow->getZoom (); - y = cropY * mainCropWindow->getZoom (); + mainCropWindow->getCropAnchorPosition (x, y); } else { x = y = 0; } @@ -565,7 +558,7 @@ void ImageArea::setScrollPosition (int x, int y) if (mainCropWindow) { mainCropWindow->delCropWindowListener (this); - mainCropWindow->setCropPosition (x / mainCropWindow->getZoom (), y / mainCropWindow->getZoom ()); + mainCropWindow->setCropAnchorPosition (x, y); mainCropWindow->addCropWindowListener (this); } } @@ -618,19 +611,18 @@ void ImageArea::initialImageArrived (CropWindow* cw) if (mainCropWindow) { if(firstOpen || options.prevdemo != PD_Sidecar || (!options.rememberZoomAndPan) ) { - mainCropWindow->zoomFit (false); + mainCropWindow->zoomFit (); firstOpen = false; mainCropWindow->cropHandler.getFullImageSize(fullImageWidth, fullImageHeight); } else { int w, h; mainCropWindow->cropHandler.getFullImageSize(w, h); - if(w == fullImageWidth && h == fullImageHeight) { // && mainCropWindow->getZoom() != mainCropWindow->getZoomFitVal()) { - int x, y; - mainCropWindow->getCropPosition(x, y); - mainCropWindow->setCropPosition(x, y, false); + if(w != fullImageWidth || h != fullImageHeight) { + printf("zoomFit !\n"); + mainCropWindow->zoomFit (); } else { - mainCropWindow->zoomFit (false); + printf("no-zoomFit\n"); } fullImageWidth = w; @@ -649,8 +641,8 @@ void ImageArea::setCropGUIListener (CropGUIListener* l) cropgl = l; - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->setCropGUIListener (cropgl); + for (auto cropWin : cropWins) { + cropWin->setCropGUIListener (cropgl); } if (mainCropWindow) { @@ -663,8 +655,8 @@ void ImageArea::setPointerMotionListener (PointerMotionListener* pml) pmlistener = pml; - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->setPointerMotionListener (pml); + for (auto cropWin : cropWins) { + cropWin->setPointerMotionListener (pml); } if (mainCropWindow) { @@ -677,8 +669,8 @@ void ImageArea::setPointerMotionHListener (PointerMotionListener* pml) pmhlistener = pml; - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->setPointerMotionHListener (pml); + for (auto cropWin : cropWins) { + cropWin->setPointerMotionHListener (pml); } if (mainCropWindow) { diff --git a/rtgui/imageareapanel.cc b/rtgui/imageareapanel.cc index b456de2c7..9a351d66a 100644 --- a/rtgui/imageareapanel.cc +++ b/rtgui/imageareapanel.cc @@ -84,9 +84,7 @@ void ImageAreaPanel::synchronize () after->imageArea->getScrollPosition (x, y); if (imgw > 0 && imgh > 0) { - int bimgw, bimgh; - imageArea->getScrollImageSize (bimgw, bimgh); - imageArea->setScrollPosition (x * bimgw / imgw, y * bimgh / imgh); + imageArea->setScrollPosition (x, y); imageArea->queue_draw (); } } else if (before && this == after) { @@ -95,9 +93,7 @@ void ImageAreaPanel::synchronize () before->imageArea->getScrollPosition (x, y); if (imgw > 0 && imgh > 0) { - int bimgw, bimgh; - imageArea->getScrollImageSize (bimgw, bimgh); - imageArea->setScrollPosition (x * bimgw / imgw, y * bimgh / imgh); + imageArea->setScrollPosition (x, y); imageArea->queue_draw (); } } diff --git a/rtgui/previewhandler.cc b/rtgui/previewhandler.cc index e2b635e07..aedd2e800 100644 --- a/rtgui/previewhandler.cc +++ b/rtgui/previewhandler.cc @@ -204,27 +204,19 @@ Glib::RefPtr PreviewHandler::getRoughImage (int x, int y, int w, in h = image->getHeight() * totalZoom; } - int ix = x * zoom; - int iy = y * zoom; + x *= zoom; + y *= zoom; - if (ix < 0) { - ix = 0; + if ((x + w) / totalZoom > previewImg->get_width()) { + w = previewImg->get_width() * totalZoom - x; } - if (iy < 0) { - iy = 0; - } - - if ((ix + w) / totalZoom > previewImg->get_width()) { - ix = previewImg->get_width() * totalZoom - w; - } - - if ((iy + h) / totalZoom > previewImg->get_height()) { - iy = previewImg->get_height() * totalZoom - h; + if ((y + h) / totalZoom > previewImg->get_height()) { + h = previewImg->get_height() * totalZoom - y; } resPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, w, h); - previewImg->scale (resPixbuf, 0, 0, w, h, -ix, -iy, totalZoom, totalZoom, Gdk::INTERP_NEAREST); + previewImg->scale (resPixbuf, 0, 0, w, h, -x, -y, totalZoom, totalZoom, Gdk::INTERP_NEAREST); } return resPixbuf; diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index be932df5f..c9bc080e3 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -199,6 +199,8 @@ bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) if (isMoving) { mainCropWin->remoteMove ((event->x - press_x) / zoom, (event->y - press_y) / zoom); + press_x = event->x; + press_y = event->y; } else if (inside && !moreInside) { cursorManager.setCursor (get_window(), CSClosedHand); } else { diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 2c7ae9115..8a37772f1 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -269,8 +269,8 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) toolPanelNotebook->set_scrollable (); toolPanelNotebook->show_all (); - for (size_t i = 0; i < toolPanels.size(); i++) { - toolPanels[i]->setListener (this); + for (auto toolPanel : toolPanels) { + toolPanel->setListener (this); } whitebalance->setWBProvider (this); @@ -323,8 +323,8 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: ProcParams* params = ipc->beginUpdateParams (); - for (size_t i = 0; i < toolPanels.size(); i++) { - toolPanels[i]->write (params); + for (auto toolPanel : toolPanels) { + toolPanel->write (params); } // Compensate rotation on flip @@ -336,6 +336,24 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: } } + int tr = TR_NONE; + if (params->coarse.rotate == 90) { + tr = TR_R90; + } else if (params->coarse.rotate == 180) { + tr = TR_R180; + } else if (params->coarse.rotate == 270) { + tr = TR_R270; + } + + // Update "on preview" geometry + if (event == rtengine::EvPhotoLoaded || event == rtengine::EvProfileChanged || event == rtengine::EvHistoryBrowsed || event == rtengine::EvCTRotate) { + // updating the "on preview" geometry + int fw, fh; + rtengine::ImageSource *ii = (rtengine::ImageSource*)ipc->getInitialImage(); + ii->getFullSize (fw, fh, tr); + gradient->updateGeometry (params->gradient.centerX, params->gradient.centerY, params->gradient.feather, params->gradient.degree, fw, fh); + } + // some transformations make the crop change for convenience if (event == rtengine::EvCTHFlip) { crop->hFlipCrop (); @@ -357,8 +375,8 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: hasChanged = true; - for (size_t i = 0; i < paramcListeners.size(); i++) { - paramcListeners[i]->procParamsChanged (params, event, descr); + for (auto paramcListener : paramcListeners) { + paramcListener->procParamsChanged (params, event, descr); } } @@ -403,17 +421,12 @@ void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengi delete mergedParams; tr = TR_NONE; - if (params->coarse.rotate == 90) { - tr |= TR_R90; - } - - if (params->coarse.rotate == 180) { - tr |= TR_R180; - } - - if (params->coarse.rotate == 270) { - tr |= TR_R270; + tr = TR_R90; + } else if (params->coarse.rotate == 180) { + tr = TR_R180; + } else if (params->coarse.rotate == 270) { + tr = TR_R270; } // trimming overflowing cropped area @@ -422,14 +435,19 @@ void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengi crop->trim(params, fw, fh); // updating the GUI with updated values - for (unsigned int i = 0; i < toolPanels.size(); i++) { - toolPanels[i]->read (params); + for (auto toolPanel : toolPanels) { + toolPanel->read (params); if (event == rtengine::EvPhotoLoaded || event == rtengine::EvProfileChanged) { - toolPanels[i]->autoOpenCurve(); + toolPanel->autoOpenCurve(); } } + if (event == rtengine::EvPhotoLoaded || event == rtengine::EvProfileChanged || event == rtengine::EvHistoryBrowsed || event == rtengine::EvCTRotate) { + // updating the "on preview" geometry + gradient->updateGeometry (params->gradient.centerX, params->gradient.centerY, params->gradient.feather, params->gradient.degree, fw, fh); + } + // start the IPC processing if (filterRawRefresh) { ipc->endUpdateParams ( refreshmap[(int)event] & ALLNORAW ); @@ -439,8 +457,8 @@ void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengi hasChanged = event != rtengine::EvProfileChangeNotification; - for (size_t i = 0; i < paramcListeners.size(); i++) { - paramcListeners[i]->procParamsChanged (params, event, descr); + for (auto paramcListener : paramcListeners) { + paramcListener->procParamsChanged (params, event, descr); } } @@ -448,8 +466,8 @@ void ToolPanelCoordinator::setDefaults (ProcParams* defparams) { if (defparams) - for (size_t i = 0; i < toolPanels.size(); i++) { - toolPanels[i]->setDefaults (defparams); + for (auto toolPanel : toolPanels) { + toolPanel->setDefaults (defparams); } } @@ -746,9 +764,9 @@ void ToolPanelCoordinator::updateCurveBackgroundHistogram (LUTu & histToneCurve, void ToolPanelCoordinator::foldAllButOne (Gtk::Box* parent, FoldableToolPanel* openedSection) { - for (size_t i = 0; i < toolPanels.size(); i++) { - if (toolPanels[i]->getParent() != NULL) { - ToolPanel* currentTP = toolPanels[i]; + for (auto toolPanel : toolPanels) { + if (toolPanel->getParent() != NULL) { + ToolPanel* currentTP = toolPanel; if (currentTP->getParent() == parent) { // Section in the same tab, we unfold it if it's not the one that has been clicked diff --git a/tools/coordinate_system.svg b/tools/coordinate_system.svg index 73227e6ac..2c3efc42b 100644 --- a/tools/coordinate_system.svg +++ b/tools/coordinate_system.svg @@ -13,10 +13,38 @@ height="1052.3622047" id="svg2" version="1.1" - inkscape:version="0.48.4 r9939" + inkscape:version="0.91 r13725" sodipodi:docname="coordinate_system.svg"> + + + + + + + + + @@ -94,6 +135,27 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1"> + + + imgAreaW + x="393.50574" + y="1104.9916">imgAreaW imgAreaH + x="-931.88525" + y="925.78394">imgAreaH - leftBorder + style="font-size:14px">cropHandler.getCrop()->getLeftBorder() upperBorder + style="font-size:14px">cropHandler.getCrop()->getUpperBorder() imgX imgY + style="fill:#ffffff;fill-opacity:1;stroke:none" /> @@ -377,19 +434,19 @@ style="font-size:14px">xpos ypos - imgX + sodipodi:role="line">imgAreaX imgY - + sodipodi:role="line">imgAreaY CropWindow (mainCropWindow) + x="10.089189" + y="-4.9809637">CropWindow (mainCropWindow) CropWindow + sodipodi:role="line">CropWindow (detail) + Scaled full image + + Editing canvas = Full image + padding, Scaled + + cropHandler.getCrop()->getPadding() + + + + CropWindow class, geometry explained + + + imgX + + + + + imgY + imgAreaW + imgAreaH + + + + + + + + + imgW + + + + + + + + + + width + + + + height