On preview widgets for the Gradient tool (center & angle). Also includes some rudimentary bounds checking (optional) when accessing some kind of array.
This commit is contained in:
@@ -75,6 +75,7 @@
|
||||
#include "sleefsseavx.c"
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include "rt_math.h"
|
||||
|
||||
template<typename T>
|
||||
class LUT {
|
||||
@@ -204,15 +205,7 @@ public:
|
||||
}
|
||||
// use with integer indices
|
||||
T& operator[](int index) const {
|
||||
if (((unsigned int)index)<size) return data[index];
|
||||
else
|
||||
{
|
||||
if (index < 0)
|
||||
return data[0];
|
||||
else
|
||||
return data[size - 1];
|
||||
}
|
||||
|
||||
return data[ rtengine::LIM<int>(index, 0, size-1) ];
|
||||
}
|
||||
|
||||
#if defined( __SSE2__ ) && defined( __x86_64__ )
|
||||
@@ -325,19 +318,17 @@ public:
|
||||
// use with float indices
|
||||
T operator[](float index) const {
|
||||
int idx = (int)index; // don't use floor! The difference in negative space is no problems here
|
||||
if (((unsigned int)idx) > maxs) {
|
||||
if (idx<0)
|
||||
{
|
||||
if (clip & LUT_CLIP_BELOW)
|
||||
return data[0];
|
||||
idx=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clip & LUT_CLIP_ABOVE)
|
||||
return data[size - 1];
|
||||
idx =maxs;
|
||||
}
|
||||
if (index<0.f)
|
||||
{
|
||||
if (clip & LUT_CLIP_BELOW)
|
||||
return data[0];
|
||||
idx=0;
|
||||
}
|
||||
else if (index > float(maxs))
|
||||
{
|
||||
if (clip & LUT_CLIP_ABOVE)
|
||||
return data[size - 1];
|
||||
idx =maxs;
|
||||
}
|
||||
float diff = index - (float) idx;
|
||||
T p1 = data[idx];
|
||||
|
@@ -31,6 +31,7 @@ private:
|
||||
void* real ;
|
||||
char alignment;
|
||||
size_t allocatedSize;
|
||||
int unitSize;
|
||||
|
||||
public:
|
||||
T* data ;
|
||||
@@ -40,7 +41,7 @@ public:
|
||||
* @param size Number of elements of size T to allocate, i.e. allocated size will be sizeof(T)*size ; set it to 0 if you want to defer the allocation
|
||||
* @param align Expressed in bytes; SSE instructions need 128 bits alignment, which mean 16 bytes, which is the default value
|
||||
*/
|
||||
AlignedBuffer (size_t size=0, size_t align=16) : real(NULL), alignment(align), allocatedSize(0), data(NULL), inUse(false) {
|
||||
AlignedBuffer (size_t size=0, size_t align=16) : real(NULL), alignment(align), allocatedSize(0), unitSize(0), data(NULL), inUse(false) {
|
||||
if (size)
|
||||
resize(size);
|
||||
}
|
||||
@@ -69,11 +70,12 @@ public:
|
||||
data = NULL;
|
||||
inUse = false;
|
||||
allocatedSize = 0;
|
||||
unitSize = 0;
|
||||
}
|
||||
else {
|
||||
int sSize = structSize ? structSize : sizeof(T);
|
||||
unitSize = structSize ? structSize : sizeof(T);
|
||||
size_t oldAllocatedSize = allocatedSize;
|
||||
allocatedSize = size*sSize;
|
||||
allocatedSize = size*unitSize;
|
||||
|
||||
// realloc were used here to limit memory fragmentation, specially when the size was smaller than the previous one.
|
||||
// But realloc copies the content to the eventually new location, which is unnecessary. To avoid this performance penalty,
|
||||
@@ -93,6 +95,7 @@ public:
|
||||
}
|
||||
else {
|
||||
allocatedSize = 0;
|
||||
unitSize = 0;
|
||||
data = NULL;
|
||||
inUse = false;
|
||||
return false;
|
||||
@@ -123,6 +126,10 @@ public:
|
||||
other.inUse = inUse;
|
||||
inUse = tmpInUse;
|
||||
}
|
||||
|
||||
unsigned int getSize() {
|
||||
return unitSize ? allocatedSize/unitSize : 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Multi processor version, use with OpenMP
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "rt_math.h"
|
||||
#include "colortemp.h"
|
||||
|
||||
// "ceil" rounding
|
||||
#define SKIPS(a,b) ((a) / (b) + ((a) % (b) > 0))
|
||||
|
||||
namespace rtengine {
|
||||
@@ -95,6 +96,13 @@ void Crop::setEditSubscriber(EditSubscriber* newSubscriber) {
|
||||
EditBuffer::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
|
||||
}
|
||||
|
||||
|
@@ -58,7 +58,8 @@ class Crop : public DetailedCrop, public EditBuffer {
|
||||
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)
|
||||
int borderRequested, upperBorder, leftBorder;
|
||||
int borderRequested; /// requested extra border size for image processing
|
||||
int upperBorder, leftBorder; /// extra border size really allocated for image processing
|
||||
|
||||
bool cropAllocated;
|
||||
DetailedCropListener* cropImageListener;
|
||||
|
@@ -36,6 +36,7 @@ EditBuffer::~EditBuffer() {
|
||||
}
|
||||
|
||||
void EditBuffer::createBuffer(int width, int height) {
|
||||
//printf("Appel de createBuffer %d x %d\n", width, height);
|
||||
resize (width, height);
|
||||
}
|
||||
|
||||
@@ -76,30 +77,33 @@ EditUniqueID EditBuffer::getEditID() {
|
||||
else return EUID_None;
|
||||
}
|
||||
|
||||
// Resize buffers if they already exist
|
||||
void EditBuffer::resize(int newWidth, int newHeight) {
|
||||
EditSubscriber* subscriber = NULL;
|
||||
if (dataProvider && (subscriber = dataProvider->getCurrSubscriber())) {
|
||||
if (subscriber->getEditingType() == ET_OBJECTS) {
|
||||
if (objectMap && (objectMap->get_width() != newWidth || objectMap->get_height() != newHeight))
|
||||
objectMap->unreference();
|
||||
resize(newWidth, newHeight, dataProvider ? dataProvider->getCurrSubscriber() : NULL);
|
||||
}
|
||||
|
||||
if (!objectMap) {
|
||||
// Resize buffers if they already exist
|
||||
void EditBuffer::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->unreference();
|
||||
objectMap2.clear();
|
||||
}
|
||||
}
|
||||
if (!objectMap2) {
|
||||
if (!objectMap2 && newWidth && newHeight) {
|
||||
objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
// OM_255 -> deleting objectMap2, if any
|
||||
else if (objectMap2)
|
||||
objectMap2->unreference();
|
||||
objectMap2.clear();
|
||||
|
||||
// Should never happen!
|
||||
if (imgFloatBuffer) {
|
||||
@@ -115,8 +119,8 @@ void EditBuffer::resize(int newWidth, int newHeight) {
|
||||
}
|
||||
}
|
||||
|
||||
if (subscriber->getEditingType() == ET_PIPETTE) {
|
||||
if (subscriber->getEditBufferType() == BT_IMAGEFLOAT) {
|
||||
if (newSubscriber->getEditingType() == ET_PIPETTE) {
|
||||
if (newSubscriber->getEditBufferType() == BT_IMAGEFLOAT) {
|
||||
if (!imgFloatBuffer)
|
||||
imgFloatBuffer = new Imagefloat(newWidth, newHeight);
|
||||
else
|
||||
@@ -127,7 +131,7 @@ void EditBuffer::resize(int newWidth, int newHeight) {
|
||||
imgFloatBuffer = NULL;
|
||||
}
|
||||
|
||||
if (subscriber->getEditBufferType() == BT_LABIMAGE) {
|
||||
if (newSubscriber->getEditBufferType() == BT_LABIMAGE) {
|
||||
if (LabBuffer && (LabBuffer->W != newWidth && LabBuffer->H != newHeight)) {
|
||||
delete LabBuffer;
|
||||
LabBuffer = NULL;
|
||||
@@ -140,43 +144,49 @@ void EditBuffer::resize(int newWidth, int newHeight) {
|
||||
LabBuffer = NULL;
|
||||
}
|
||||
|
||||
if (subscriber->getEditBufferType() == BT_SINGLEPLANE_FLOAT) {
|
||||
if (newSubscriber->getEditBufferType() == BT_SINGLEPLANE_FLOAT) {
|
||||
singlePlaneBuffer.allocate(newWidth, newHeight);
|
||||
}
|
||||
else if (singlePlaneBuffer.data)
|
||||
singlePlaneBuffer.allocate(0,0);
|
||||
|
||||
// Should never happen!
|
||||
if (objectMap ) objectMap->unreference();
|
||||
if (objectMap2) objectMap2->unreference();
|
||||
if (objectMap ) objectMap.clear();
|
||||
if (objectMap2) objectMap2.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EditBuffer::bufferCreated() {
|
||||
if (dataProvider && dataProvider->getCurrSubscriber()) {
|
||||
switch (dataProvider->getCurrSubscriber()->getEditBufferType()) {
|
||||
case (BT_IMAGEFLOAT):
|
||||
return imgFloatBuffer != NULL;
|
||||
case (BT_LABIMAGE):
|
||||
return LabBuffer != NULL;
|
||||
case (BT_SINGLEPLANE_FLOAT):
|
||||
return singlePlaneBuffer.data != NULL;
|
||||
EditSubscriber* subscriber;
|
||||
if (dataProvider && (subscriber = dataProvider->getCurrSubscriber())) {
|
||||
switch (subscriber->getEditingType()) {
|
||||
case ET_PIPETTE:
|
||||
switch (dataProvider->getCurrSubscriber()->getEditBufferType()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned short EditBuffer::getObjectID(const Coord& location) {
|
||||
unsigned short id = 0;
|
||||
int EditBuffer::getObjectID(const Coord& location) {
|
||||
int id = 0;
|
||||
|
||||
if (objectMap)
|
||||
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;
|
||||
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) {
|
||||
|
@@ -48,6 +48,7 @@ protected:
|
||||
PlanarWhateverData<float> singlePlaneBuffer;
|
||||
|
||||
void createBuffer(int width, int height);
|
||||
void resize(int newWidth, int newHeight, EditSubscriber* newSubscriber);
|
||||
void resize(int newWidth, int newHeight);
|
||||
void flush();
|
||||
|
||||
@@ -70,7 +71,7 @@ public:
|
||||
// return true if the buffer has been allocated
|
||||
bool bufferCreated();
|
||||
|
||||
unsigned short getObjectID(const Coord& location);
|
||||
int getObjectID(const Coord& location);
|
||||
// get the pipette values
|
||||
void getPipetteData(float* v, int x, int y, int squareSize);
|
||||
};
|
||||
|
@@ -41,6 +41,8 @@
|
||||
#define TR_HFLIP 8
|
||||
#define TR_ROT 3
|
||||
|
||||
#define CHECK_BOUNDS 0
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
extern const char sImage8[];
|
||||
@@ -120,9 +122,17 @@ namespace rtengine {
|
||||
protected:
|
||||
AlignedBuffer<T*> ab;
|
||||
public:
|
||||
#if CHECK_BOUNDS
|
||||
int width_, height_;
|
||||
#endif
|
||||
T** ptrs;
|
||||
|
||||
PlanarPtr() : ptrs (NULL) {}
|
||||
#if CHECK_BOUNDS
|
||||
PlanarPtr() : width_(0), height_(0), ptrs (NULL) {}
|
||||
#else
|
||||
PlanarPtr() : ptrs (NULL){}
|
||||
#endif
|
||||
|
||||
bool resize(int newSize) {
|
||||
if (ab.resize(newSize)) {
|
||||
ptrs=ab.data;
|
||||
@@ -138,14 +148,43 @@ namespace rtengine {
|
||||
T** tmpsPtrs = other.ptrs;
|
||||
other.ptrs = ptrs;
|
||||
ptrs = tmpsPtrs;
|
||||
|
||||
#if CHECK_BOUNDS
|
||||
int tmp = other.width_;
|
||||
other.width_ = width_;
|
||||
width_ = tmp;
|
||||
tmp = other.height_;
|
||||
other.height_ = height_;
|
||||
height_ = tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
T*& operator() (unsigned row) { return ptrs[row]; }
|
||||
T*& operator() (unsigned row) {
|
||||
#if CHECK_BOUNDS
|
||||
assert (row < height_);
|
||||
#endif
|
||||
return ptrs[row];
|
||||
}
|
||||
// Will send back the start of a row, starting with a red, green or blue value
|
||||
T* operator() (unsigned row) const { return ptrs[row]; }
|
||||
T* operator() (unsigned row) const {
|
||||
#if CHECK_BOUNDS
|
||||
assert (row < height_);
|
||||
#endif
|
||||
return ptrs[row];
|
||||
}
|
||||
// Will send back a value at a given row, col position
|
||||
T& operator() (unsigned row, unsigned col) { return ptrs[row][col]; }
|
||||
const T operator() (unsigned row, unsigned col) const { return ptrs[row][col]; }
|
||||
T& operator() (unsigned row, unsigned col) {
|
||||
#if CHECK_BOUNDS
|
||||
assert (row < height_ && col < width_);
|
||||
#endif
|
||||
return ptrs[row][col];
|
||||
}
|
||||
const T operator() (unsigned row, unsigned col) const {
|
||||
#if CHECK_BOUNDS
|
||||
assert (row < height_ && col < width_);
|
||||
#endif
|
||||
return ptrs[row][col];
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -180,6 +219,10 @@ namespace rtengine {
|
||||
int tmpHeight = other.height;
|
||||
other.height = height;
|
||||
height = tmpHeight;
|
||||
#if CHECK_BOUNDS
|
||||
v.width_ = width;
|
||||
v.height_ = height;
|
||||
#endif
|
||||
}
|
||||
|
||||
// use as pointer to data
|
||||
@@ -194,6 +237,10 @@ namespace rtengine {
|
||||
|
||||
width=W;
|
||||
height=H;
|
||||
#if CHECK_BOUNDS
|
||||
v.width_ = width;
|
||||
v.height_ = height;
|
||||
#endif
|
||||
|
||||
if (sizeof(T) > 1) {
|
||||
// 128 bits memory alignment for >8bits data
|
||||
@@ -222,6 +269,10 @@ namespace rtengine {
|
||||
data = NULL;
|
||||
v.resize(0);
|
||||
width = height = -1;
|
||||
#if CHECK_BOUNDS
|
||||
v.width_ = v.height_ = -1;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -491,6 +542,11 @@ namespace rtengine {
|
||||
int tmpHeight = other.height;
|
||||
other.height = height;
|
||||
height = tmpHeight;
|
||||
#if CHECK_BOUNDS
|
||||
r.width_ = width; r.height_ = height;
|
||||
g.width_ = width; g.height_ = height;
|
||||
b.width_ = width; b.height_ = height;
|
||||
#endif
|
||||
}
|
||||
|
||||
// use as pointer to data
|
||||
@@ -505,6 +561,11 @@ namespace rtengine {
|
||||
|
||||
width=W;
|
||||
height=H;
|
||||
#if CHECK_BOUNDS
|
||||
r.width_ = width; r.height_ = height;
|
||||
g.width_ = width; g.height_ = height;
|
||||
b.width_ = width; b.height_ = height;
|
||||
#endif
|
||||
|
||||
if (sizeof(T) > 1) {
|
||||
// 128 bits memory alignment for >8bits data
|
||||
@@ -539,6 +600,11 @@ namespace rtengine {
|
||||
g.resize(0);
|
||||
b.resize(0);
|
||||
width = height = -1;
|
||||
#if CHECK_BOUNDS
|
||||
r.width_ = r.height_ = -1;
|
||||
g.width_ = g.height_ = -1;
|
||||
b.width_ = b.height_ = -1;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -943,7 +1009,15 @@ namespace rtengine {
|
||||
T* ptr;
|
||||
int width;
|
||||
public:
|
||||
#if CHECK_BOUNDS
|
||||
int width_, height_;
|
||||
#endif
|
||||
|
||||
#if CHECK_BOUNDS
|
||||
ChunkyPtr() : ptr (NULL), width(-1), width_(0), height_(0) {}
|
||||
#else
|
||||
ChunkyPtr() : ptr (NULL), width(-1) {}
|
||||
#endif
|
||||
void init(T* base, int w=-1) { ptr = base; width=w; }
|
||||
void swap (ChunkyPtr<T> &other) {
|
||||
T* tmpsPtr = other.ptr;
|
||||
@@ -953,13 +1027,38 @@ namespace rtengine {
|
||||
int tmpWidth = other.width;
|
||||
other.width = width;
|
||||
width = tmpWidth;
|
||||
|
||||
#if CHECK_BOUNDS
|
||||
int tmp = other.width_;
|
||||
other.width_ = width_;
|
||||
width_ = tmp;
|
||||
tmp = other.height_;
|
||||
other.height_ = height_;
|
||||
height_ = tmp;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Will send back the start of a row, starting with a red, green or blue value
|
||||
T* operator() (unsigned row) const { return &ptr[3*(row*width)]; }
|
||||
T* operator() (unsigned row) const {
|
||||
#if CHECK_BOUNDS
|
||||
assert (row < height_);
|
||||
#endif
|
||||
return &ptr[3*(row*width)];
|
||||
}
|
||||
// Will send back a value at a given row, col position
|
||||
T& operator() (unsigned row, unsigned col) { return ptr[3*(row*width+col)]; }
|
||||
const T operator() (unsigned row, unsigned col) const { return ptr[3*(row*width+col)]; }
|
||||
T& operator() (unsigned row, unsigned col) {
|
||||
#if CHECK_BOUNDS
|
||||
assert (row < height_ && col < width_);
|
||||
#endif
|
||||
return ptr[3*(row*width+col)];
|
||||
}
|
||||
const T operator() (unsigned row, unsigned col) const {
|
||||
#if CHECK_BOUNDS
|
||||
assert (row < height_ && col < width_);
|
||||
#endif
|
||||
return ptr[3*(row*width+col)];
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -997,6 +1096,11 @@ namespace rtengine {
|
||||
int tmpHeight = other.height;
|
||||
other.height = height;
|
||||
height = tmpHeight;
|
||||
#if CHECK_BOUNDS
|
||||
r.width_ = width; r.height_ = height;
|
||||
g.width_ = width; g.height_ = height;
|
||||
b.width_ = width; b.height_ = height;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1010,6 +1114,11 @@ namespace rtengine {
|
||||
|
||||
width=W;
|
||||
height=H;
|
||||
#if CHECK_BOUNDS
|
||||
r.width_ = width; r.height_ = height;
|
||||
g.width_ = width; g.height_ = height;
|
||||
b.width_ = width; b.height_ = height;
|
||||
#endif
|
||||
|
||||
abData.resize(width*height*3);
|
||||
if (!abData.isEmpty()) {
|
||||
@@ -1024,6 +1133,11 @@ namespace rtengine {
|
||||
g.init(NULL);
|
||||
b.init(NULL);
|
||||
width = height = -1;
|
||||
#if CHECK_BOUNDS
|
||||
r.width_ = r.height_ = -1;
|
||||
g.width_ = g.height_ = -1;
|
||||
b.width_ = b.height_ = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -345,7 +345,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) {
|
||||
|
||||
EditSubscriber *editSubscriber = iarea->getCurrSubscriber();
|
||||
|
||||
if (button==1 && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && ( (editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK)) || (editSubscriber->getEditingType() == ET_OBJECTS && iarea->object)) ) {
|
||||
if (button==1 && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && ( (editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK)) || (editSubscriber->getEditingType() == ET_OBJECTS && iarea->object>-1)) ) {
|
||||
editSubscriber->button1Pressed(bstate);
|
||||
state=SEditDrag;
|
||||
}
|
||||
@@ -576,9 +576,9 @@ void CropWindow::pointerMoved (int bstate, int x, int y) {
|
||||
iarea->posImage.set(imgPos.x, imgPos.y);
|
||||
iarea->posScreen.set(x, y);
|
||||
|
||||
Coord cropPos;
|
||||
screenCoordToCropBuffer(x, y, cropPos.x, cropPos.y);
|
||||
if (editSubscriber->getEditingType()==ET_PIPETTE) {
|
||||
Coord cropPos;
|
||||
screenCoordToCropBuffer(x, y, cropPos.x, cropPos.y);
|
||||
iarea->object = onArea (CropImage, x, y) ? 1 : 0;
|
||||
//iarea->object = cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) ? 1 : 0;
|
||||
if (iarea->object) {
|
||||
@@ -589,22 +589,33 @@ 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;
|
||||
}
|
||||
|
||||
if (editSubscriber->mouseOver(bstate))
|
||||
iarea->redraw ();
|
||||
}
|
||||
else if (state==SEditDrag) {
|
||||
Coord oldPosImage = iarea->posImage;
|
||||
Coord oldPosScreen = iarea->posScreen;
|
||||
screenCoordToImage (x, y, action_x, action_y);
|
||||
|
||||
Coord currPos(action_x, action_y);
|
||||
iarea->deltaImage = currPos - iarea->posImage;
|
||||
Coord currPos;
|
||||
action_x = x;
|
||||
action_y = y;
|
||||
Coord oldPosImage = iarea->posImage+iarea->deltaImage;
|
||||
//printf(">>> IMG / ImgPrev(%d x %d) = (%d x %d) + (%d x %d)\n", oldPosImage.x, oldPosImage.y, iarea->posImage.x, iarea->posImage.y, iarea->deltaImage.x, iarea->deltaImage.y);
|
||||
screenCoordToImage (x, y, currPos.x, currPos.y);
|
||||
iarea->deltaImage = currPos - iarea->posImage;
|
||||
iarea->deltaPrevImage = currPos - oldPosImage;
|
||||
//printf(" action_ & xy (%d x %d) -> (%d x %d) = (%d x %d) + (%d x %d) / deltaPrev(%d x %d)\n", action_x, action_y, currPos.x, currPos.y, iarea->posImage.x, iarea->posImage.y, iarea->deltaImage.x, iarea->deltaImage.y, iarea->deltaPrevImage.x, iarea->deltaPrevImage.y);
|
||||
|
||||
currPos.set(x, y);
|
||||
iarea->deltaScreen = currPos - iarea->posScreen;
|
||||
Coord oldPosScreen = iarea->posScreen+iarea->deltaScreen;
|
||||
//printf(">>> SCR / ScrPrev(%d x %d) = (%d x %d) + (%d x %d)\n", oldPosScreen.x, oldPosScreen.y, iarea->posScreen.x, iarea->posScreen.y, iarea->deltaScreen.x, iarea->deltaScreen.y);
|
||||
screenCoordToPreview(x, y, currPos.x, currPos.y);
|
||||
iarea->deltaScreen = currPos - iarea->posScreen;
|
||||
iarea->deltaPrevScreen = currPos - oldPosScreen;
|
||||
//printf(" action_ & xy (%d x %d) -> (%d x %d) = (%d x %d) + (%d x %d) / deltaPrev(%d x %d)\n", action_x, action_y, currPos.x, currPos.y, iarea->posScreen.x, iarea->posScreen.y, iarea->deltaScreen.x, iarea->deltaScreen.y, iarea->deltaPrevScreen.x, iarea->deltaPrevScreen.y);
|
||||
|
||||
if (editSubscriber->drag(bstate))
|
||||
iarea->redraw ();
|
||||
@@ -786,7 +797,12 @@ void CropWindow::updateCursor (int x, int y) {
|
||||
else if (tm==TMHand && (onArea (CropLeft, x, y) || onArea (CropRight, x, y)))
|
||||
cursorManager.setCursor (iarea->get_window(), CSResizeWidth);
|
||||
else if (onArea (CropImage, x, y)) {
|
||||
if (tm==TMHand) {
|
||||
int objectID = -1;
|
||||
if (editSubscriber)
|
||||
objectID = static_cast<rtengine::Crop*>(cropHandler.getCrop())->getObjectID(iarea->posImage);
|
||||
if (objectID > -1)
|
||||
cursorManager.setCursor (iarea->get_window(), iarea->getCursor(objectID));
|
||||
else if (tm==TMHand) {
|
||||
if (onArea (CropObserved, x, y))
|
||||
cursorManager.setCursor (iarea->get_window(), CSMove);
|
||||
else
|
||||
@@ -799,9 +815,6 @@ void CropWindow::updateCursor (int x, int y) {
|
||||
else if (tm==TMStraighten)
|
||||
cursorManager.setCursor (iarea->get_window(), CSStraighten);
|
||||
}
|
||||
else if (tm==TMHand && editSubscriber) {
|
||||
cursorManager.setCursor (iarea->get_window(), iarea->getCursor( static_cast<rtengine::Crop*>(cropHandler.getCrop())->getObjectID(iarea->posImage )));
|
||||
}
|
||||
else
|
||||
cursorManager.setCursor (iarea->get_window(), CSArrow);
|
||||
}
|
||||
@@ -1106,30 +1119,46 @@ void CropWindow::expose (Cairo::RefPtr<Cairo::Context> cr) {
|
||||
rtengine::Crop* crop = static_cast<rtengine::Crop*>(cropHandler.getCrop());
|
||||
if (editSubscriber && crop->bufferCreated()) {
|
||||
|
||||
// drawing Subscriber's visible geometry
|
||||
// clip the region
|
||||
if (this != iarea->mainCropWindow) {
|
||||
cr->set_line_width (0.);
|
||||
cr->rectangle (x+imgX, y+imgY, imgW, imgH);
|
||||
cr->clip();
|
||||
}
|
||||
|
||||
// drawing Subscriber's visible geometry
|
||||
const std::vector<Geometry*> visibleGeom = editSubscriber->getVisibleGeometry();
|
||||
cr->set_antialias(Cairo::ANTIALIAS_DEFAULT); // ANTIALIAS_SUBPIXEL ?
|
||||
cr->set_line_cap(Cairo::LINE_CAP_SQUARE);
|
||||
cr->set_line_join(Cairo::LINE_JOIN_ROUND);
|
||||
|
||||
// drawing outer lines
|
||||
for (unsigned short currObject=0; currObject < visibleGeom.size(); ++currObject) {
|
||||
visibleGeom.at(currObject)->drawOuterGeometry(cr, crop, *this);
|
||||
}
|
||||
for (std::vector<Geometry*>::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i)
|
||||
(*i)->drawOuterGeometry(cr, crop, *this);
|
||||
|
||||
// drawing inner lines
|
||||
for (unsigned short currObject=0; currObject < visibleGeom.size(); ++currObject) {
|
||||
visibleGeom.at(currObject)->drawInnerGeometry(cr, crop, *this);
|
||||
}
|
||||
for (std::vector<Geometry*>::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i)
|
||||
(*i)->drawInnerGeometry(cr, crop, *this);
|
||||
|
||||
if (this != iarea->mainCropWindow)
|
||||
cr->reset_clip();
|
||||
|
||||
// drawing to the "mouse over" channel
|
||||
|
||||
if (editSubscriber->getEditingType() == ET_OBJECTS) {
|
||||
const std::vector<Geometry*> mouseOverGeom = editSubscriber->getMouseOverGeometry();
|
||||
if (mouseOverGeom.size()) {
|
||||
//printf("ObjectMap (%d x %d)\n", crop->getObjectMap()->get_width(), crop->getObjectMap()->get_height());
|
||||
Cairo::RefPtr<Cairo::Context> crMO = Cairo::Context::create(crop->getObjectMap());
|
||||
crMO->set_antialias(Cairo::ANTIALIAS_NONE);
|
||||
crMO->set_line_cap(Cairo::LINE_CAP_SQUARE);
|
||||
crMO->set_line_join(Cairo::LINE_JOIN_ROUND);
|
||||
crMO->set_operator(Cairo::OPERATOR_SOURCE);
|
||||
|
||||
// clear the bitmap
|
||||
crMO->set_source_rgba(0., 0., 0., 0.);
|
||||
crMO->rectangle(0., 0., crop->getObjectMap()->get_width(), crop->getObjectMap()->get_height());
|
||||
crMO->set_line_width(0.);
|
||||
crMO->fill();
|
||||
|
||||
Cairo::RefPtr<Cairo::Context> crMO2;
|
||||
if (crop->getObjectMode() > OM_255) {
|
||||
@@ -1137,12 +1166,44 @@ void CropWindow::expose (Cairo::RefPtr<Cairo::Context> cr) {
|
||||
crMO2->set_antialias(Cairo::ANTIALIAS_NONE);
|
||||
crMO2->set_line_cap(Cairo::LINE_CAP_SQUARE);
|
||||
crMO2->set_line_join(Cairo::LINE_JOIN_ROUND);
|
||||
}
|
||||
for (unsigned short currObject=0; currObject < mouseOverGeom.size(); ++currObject) {
|
||||
visibleGeom.at(currObject)->drawToMOChannel(crMO, crMO2, currObject, crop, *this);
|
||||
}
|
||||
}
|
||||
crMO2->set_operator(Cairo::OPERATOR_SOURCE);
|
||||
|
||||
// clear the bitmap
|
||||
crMO2->set_source_rgba(0., 0., 0., 0.);
|
||||
crMO2->rectangle(0., 0., crop->getObjectMap2()->get_width(), crop->getObjectMap2()->get_height());
|
||||
crMO2->set_line_width(0.);
|
||||
crMO2->fill();
|
||||
}
|
||||
std::vector<Geometry*>::const_iterator i;
|
||||
int a;
|
||||
for (a=0, i=mouseOverGeom.begin(); i != mouseOverGeom.end(); ++i, ++a) {
|
||||
(*i)->drawToMOChannel(crMO, crMO2, a, crop, *this);
|
||||
}
|
||||
|
||||
// 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();
|
||||
Glib::RefPtr<Gdk::Pixbuf> 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;
|
||||
memcpy(dst, src1, w*h);
|
||||
for (int n=0, n3=0; n<w*h;) {
|
||||
dst[n3++] = src1[n];
|
||||
if (src2)
|
||||
dst[n3++] = src2[n];
|
||||
else
|
||||
dst[n3++] = 0;
|
||||
dst[n3++] = 0;
|
||||
++n;
|
||||
}
|
||||
img->save(Glib::ustring::compose("mouseOverImage-%1.png", count++), "png");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1400,12 +1461,29 @@ 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) {
|
||||
|
||||
prevx = phyx - xpos - imgX;
|
||||
prevy = phyy - ypos - imgY;
|
||||
}
|
||||
|
||||
void CropWindow::imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) {
|
||||
|
||||
int cropX, cropY;
|
||||
rtengine::Crop* crop = static_cast<rtengine::Crop*>(cropHandler.getCrop());
|
||||
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);
|
||||
}
|
||||
|
||||
void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) {
|
||||
int cropX, cropY;
|
||||
rtengine::Crop* crop = static_cast<rtengine::Crop*>(cropHandler.getCrop());
|
||||
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) {
|
||||
|
@@ -64,7 +64,7 @@ class CropWindow : public LWButtonListener, public CropHandlerListener, public E
|
||||
// crop frame description
|
||||
int titleHeight, sideBorderWidth, lowerBorderWidth, upperBorderWidth, sepWidth, minWidth;
|
||||
// size & position of the crop relative to the top left corner
|
||||
// of the main preview area (to be confirmed)
|
||||
// of the main preview area
|
||||
int xpos, ypos, width, height;
|
||||
// size & pos of the drawable area relative to the top left corner of the crop
|
||||
int imgAreaX, imgAreaY, imgAreaW, imgAreaH;
|
||||
@@ -105,7 +105,9 @@ class CropWindow : public LWButtonListener, public CropHandlerListener, public E
|
||||
|
||||
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 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);
|
||||
|
@@ -129,7 +129,7 @@ std::vector<double> FlatCurveEditor::getCurve () {
|
||||
* ceGroup = NULL or the address of the Widget that will receive the CurveTypeToggleButton
|
||||
* text = (optional) label of the curve, displayed in the CurveTypeToggleButton, next to the image
|
||||
*/
|
||||
CurveEditor::CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) {
|
||||
CurveEditor::CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) : EditSubscriber(ET_PIPETTE) {
|
||||
|
||||
bgHistValid = false;
|
||||
remoteDrag = false;
|
||||
|
@@ -23,7 +23,6 @@
|
||||
#include <string>
|
||||
#include "guiutils.h"
|
||||
#include "multilangmgr.h"
|
||||
#include "guiutils.h"
|
||||
#include "mycurve.h"
|
||||
#include "shcselector.h"
|
||||
#include "adjuster.h"
|
||||
@@ -167,7 +166,7 @@ DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt,
|
||||
loadParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) );
|
||||
pasteParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) );
|
||||
copyParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) );
|
||||
editCustomConn = editParam->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editParam) );
|
||||
editParamConn = editParam->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editParam) );
|
||||
|
||||
saveParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
|
||||
loadParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
|
||||
|
175
rtgui/edit.cc
175
rtgui/edit.cc
@@ -20,6 +20,13 @@
|
||||
#include "edit.h"
|
||||
#include "../rtengine/editbuffer.h"
|
||||
|
||||
void Coord::setFromPolar(PolarCoord polar) {
|
||||
while (polar.angle < 0.f) polar.angle += 360.f;
|
||||
while (polar.angle > 360.f) polar.angle -= 360.f;
|
||||
x = polar.radius * cos(polar.angle/180.f*M_PI);
|
||||
y = polar.radius * sin(polar.angle/180.f*M_PI);
|
||||
}
|
||||
|
||||
RGBColor Geometry::getInnerLineColor () {
|
||||
RGBColor color;
|
||||
if (flags & AUTO_COLOR) {
|
||||
@@ -47,9 +54,17 @@ RGBColor Geometry::getOuterLineColor () {
|
||||
|
||||
void Circle::drawOuterGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) {
|
||||
if (flags & ACTIVE) {
|
||||
RGBColor color;
|
||||
if (flags & AUTO_COLOR)
|
||||
color = getOuterLineColor();
|
||||
else
|
||||
color = outerLineColor;
|
||||
|
||||
cr->set_source_rgb (color.getR(), color.getG(), color.getB());
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
|
||||
Coord center_ = center;
|
||||
double radius_ = radiusInImageSpace ? coordSystem.scaleValueToImage(double(radius)) : double(radius);
|
||||
double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius);
|
||||
if (datum == IMAGE) {
|
||||
coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y);
|
||||
}
|
||||
@@ -59,15 +74,24 @@ void Circle::drawOuterGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::Edit
|
||||
else if (datum == CURSOR) {
|
||||
center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
}
|
||||
cr->set_source_rgb (outerLineColor.getR(), outerLineColor.getG(), outerLineColor.getB());
|
||||
cr->arc(center_.x, center_.y, radius_, 0., 2.*M_PI);
|
||||
cr->arc(center_.x+0.5, center_.y+0.5, radius_, 0., 2.*M_PI);
|
||||
cr->stroke();
|
||||
}
|
||||
}
|
||||
|
||||
void Circle::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) {
|
||||
if (flags & ACTIVE) {
|
||||
RGBColor color;
|
||||
if (flags & AUTO_COLOR)
|
||||
color = getInnerLineColor();
|
||||
else
|
||||
color = innerLineColor;
|
||||
|
||||
cr->set_source_rgb (color.getR(), color.getG(), color.getB());
|
||||
cr->set_line_width( innerLineWidth );
|
||||
|
||||
Coord center_ = center;
|
||||
double radius_ = radiusInImageSpace ? coordSystem.scaleValueToImage(double(radius)) : double(radius);
|
||||
double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius);
|
||||
if (datum == IMAGE) {
|
||||
coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y);
|
||||
}
|
||||
@@ -77,10 +101,8 @@ void Circle::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::Edit
|
||||
else if (datum == CURSOR) {
|
||||
center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
}
|
||||
cr->set_source_rgb (innerLineColor.getR(), innerLineColor.getG(), innerLineColor.getB());
|
||||
if (filled) {
|
||||
cr->arc(center_.x, center_.y, radius_, 0., 2.*M_PI);
|
||||
cr->set_line_width( innerLineWidth );
|
||||
cr->arc(center_.x+0.5, center_.y+0.5, radius_, 0., 2.*M_PI);
|
||||
if (innerLineWidth > 0.) {
|
||||
cr->fill_preserve();
|
||||
cr->stroke();
|
||||
@@ -89,7 +111,7 @@ void Circle::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::Edit
|
||||
cr->fill();
|
||||
}
|
||||
else if (innerLineWidth > 0.) {
|
||||
cr->arc(center_.x, center_.y, radius_, 0., 2.*M_PI);
|
||||
cr->arc(center_.x+0.5, center_.y+0.5, radius_, 0., 2.*M_PI);
|
||||
cr->stroke();
|
||||
}
|
||||
}
|
||||
@@ -99,9 +121,9 @@ void Circle::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPtr<C
|
||||
if (flags & ACTIVE) {
|
||||
cr->set_line_width( getMouseOverLineWidth() );
|
||||
Coord center_ = center;
|
||||
double radius_ = radiusInImageSpace ? coordSystem.scaleValueToImage(double(radius)) : double(radius);
|
||||
double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius);
|
||||
if (datum == IMAGE) {
|
||||
coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y);
|
||||
coordSystem.imageCoordToCropBuffer(center.x, center.y, center_.x, center_.y);
|
||||
}
|
||||
else if (datum == CLICKED_POINT) {
|
||||
center_ += editBuffer->getDataProvider()->posScreen;
|
||||
@@ -113,7 +135,7 @@ void Circle::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPtr<C
|
||||
// drawing the lower byte's value
|
||||
unsigned short a = (id+1) & 0xFF;
|
||||
cr->set_source_rgba (0.,0., 0., double(a)/255.);
|
||||
cr->arc(center_.x, center_.y, radius_, 0, 2.*M_PI);
|
||||
cr->arc(center_.x+0.5, center_.y+0.5, radius_, 0, 2.*M_PI);
|
||||
if (filled) {
|
||||
if (innerLineWidth > 0.) {
|
||||
cr->fill_preserve();
|
||||
@@ -129,7 +151,7 @@ void Circle::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPtr<C
|
||||
if (editBuffer->getObjectMode() == OM_65535) {
|
||||
a = (id+1)>>8;
|
||||
cr2->set_source_rgba (0.,0., 0., double(a)/255.);
|
||||
cr2->arc(center_.x, center_.y, radius_, 0, 2.*M_PI);
|
||||
cr2->arc(center_.x+0.5, center_.y+0.5, radius_, 0, 2.*M_PI);
|
||||
if (filled) {
|
||||
if (innerLineWidth > 0.) {
|
||||
cr2->fill_preserve();
|
||||
@@ -146,7 +168,15 @@ void Circle::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPtr<C
|
||||
|
||||
void Line::drawOuterGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) {
|
||||
if (flags & ACTIVE) {
|
||||
RGBColor color;
|
||||
if (flags & AUTO_COLOR)
|
||||
color = getOuterLineColor();
|
||||
else
|
||||
color = outerLineColor;
|
||||
|
||||
cr->set_source_rgb (color.getR(), color.getG(), color.getB());
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
|
||||
Coord begin_ = begin;
|
||||
Coord end_ = end;
|
||||
if (datum == IMAGE) {
|
||||
@@ -161,15 +191,23 @@ void Line::drawOuterGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBu
|
||||
begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
}
|
||||
cr->set_source_rgb (outerLineColor.getR(), outerLineColor.getG(), outerLineColor.getB());
|
||||
cr->move_to(begin_.x, begin_.y);
|
||||
cr->line_to(end_.x, end_.y);
|
||||
cr->move_to(begin_.x+0.5, begin_.y+0.5);
|
||||
cr->line_to(end_.x+0.5, end_.y+0.5);
|
||||
cr->stroke();
|
||||
}
|
||||
}
|
||||
|
||||
void Line::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) {
|
||||
if ((flags & ACTIVE) && innerLineWidth > 0.) {
|
||||
RGBColor color;
|
||||
if (flags & AUTO_COLOR)
|
||||
color = getInnerLineColor();
|
||||
else
|
||||
color = innerLineColor;
|
||||
|
||||
cr->set_source_rgb (color.getR(), color.getG(), color.getB());
|
||||
cr->set_line_width(innerLineWidth);
|
||||
|
||||
Coord begin_ = begin;
|
||||
Coord end_ = end;
|
||||
if (datum == IMAGE) {
|
||||
@@ -184,10 +222,8 @@ void Line::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBu
|
||||
begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
}
|
||||
cr->set_line_width(innerLineWidth);
|
||||
cr->set_source_rgb (innerLineColor.getR(), innerLineColor.getG(), innerLineColor.getB());
|
||||
cr->move_to(begin_.x, begin_.y);
|
||||
cr->line_to(end_.x, end_.y);
|
||||
cr->move_to(begin_.x+0.5, begin_.y+0.5);
|
||||
cr->line_to(end_.x+0.5, end_.y+0.5);
|
||||
cr->stroke();
|
||||
}
|
||||
}
|
||||
@@ -198,8 +234,8 @@ void Line::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPtr<Cai
|
||||
Coord begin_ = begin;
|
||||
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.imageCoordToCropBuffer(begin.x, begin.y, begin_.x, begin_.y);
|
||||
coordSystem.imageCoordToCropBuffer(end.x, end.y, end_.x, end_.y);
|
||||
}
|
||||
else if (datum == CLICKED_POINT) {
|
||||
begin_ += editBuffer->getDataProvider()->posScreen;
|
||||
@@ -213,16 +249,16 @@ void Line::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPtr<Cai
|
||||
// drawing the lower byte's value
|
||||
unsigned short a = (id+1) & 0xFF;
|
||||
cr->set_source_rgba (0.,0., 0., double(a)/255.);
|
||||
cr->move_to(begin_.x, begin_.y);
|
||||
cr->line_to(end_.x, end_.y);
|
||||
cr->move_to(begin_.x+0.5, begin_.y+0.5);
|
||||
cr->line_to(end_.x+0.5, end_.y+0.5);
|
||||
cr->stroke();
|
||||
|
||||
// drawing the higher byte's value
|
||||
if (editBuffer->getObjectMode() == OM_65535) {
|
||||
a = (id+1)>>8;
|
||||
cr2->set_source_rgba (0.,0., 0., double(a)/255.);
|
||||
cr2->move_to(begin_.x, begin_.y);
|
||||
cr2->line_to(end_.x, end_.y);
|
||||
cr2->move_to(begin_.x+0.5, begin_.y+0.5);
|
||||
cr2->line_to(end_.x+0.5, end_.y+0.5);
|
||||
cr2->stroke();
|
||||
}
|
||||
}
|
||||
@@ -230,45 +266,57 @@ void Line::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPtr<Cai
|
||||
|
||||
void Polyline::drawOuterGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) {
|
||||
if ((flags & ACTIVE) && points.size()>1) {
|
||||
cr->set_source_rgb (outerLineColor.getR(), outerLineColor.getG(), outerLineColor.getB());
|
||||
RGBColor color;
|
||||
if (flags & AUTO_COLOR)
|
||||
color = getOuterLineColor();
|
||||
else
|
||||
color = outerLineColor;
|
||||
|
||||
cr->set_source_rgb (color.getR(), color.getG(), color.getB());
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
|
||||
Coord currPos;
|
||||
for (unsigned int i=0; i<points.size(); ++i) {
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
currPos = points.at(i);
|
||||
|
||||
if (datum == IMAGE) coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y);
|
||||
else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen;
|
||||
else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
|
||||
if (!i) cr->move_to(currPos.x, currPos.y);
|
||||
else cr->line_to(currPos.x, currPos.y);
|
||||
if (!i) cr->move_to(currPos.x+0.5, currPos.y+0.5);
|
||||
else cr->line_to(currPos.x+0.5, currPos.y+0.5);
|
||||
}
|
||||
if (filled) {
|
||||
cr->fill_preserve();
|
||||
cr->stroke();
|
||||
}
|
||||
else
|
||||
cr->fill();
|
||||
cr->stroke();
|
||||
}
|
||||
}
|
||||
|
||||
void Polyline::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) {
|
||||
if ((flags & ACTIVE) && points.size()>1) {
|
||||
cr->set_source_rgb (innerLineColor.getR(), innerLineColor.getG(), innerLineColor.getB());
|
||||
RGBColor color;
|
||||
if (flags & AUTO_COLOR)
|
||||
color = getInnerLineColor();
|
||||
else
|
||||
color = innerLineColor;
|
||||
|
||||
cr->set_source_rgb (color.getR(), color.getG(), color.getB());
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
|
||||
if (filled) {
|
||||
Coord currPos;
|
||||
for (unsigned int i=0; i<points.size(); ++i) {
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
currPos = points.at(i);
|
||||
|
||||
if (datum == IMAGE) coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y);
|
||||
else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen;
|
||||
else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
|
||||
if (!i) cr->move_to(currPos.x, currPos.y);
|
||||
else cr->line_to(currPos.x, currPos.y);
|
||||
if (!i) cr->move_to(currPos.x+0.5, currPos.y+0.5);
|
||||
else cr->line_to(currPos.x+0.5, currPos.y+0.5);
|
||||
}
|
||||
|
||||
if (innerLineWidth > 0.) {
|
||||
@@ -281,17 +329,16 @@ void Polyline::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, rtengine::Ed
|
||||
else if (innerLineWidth > 0.) {
|
||||
Coord currPos;
|
||||
for (unsigned int i=0; i<points.size(); ++i) {
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
currPos = points.at(i);
|
||||
|
||||
if (datum == IMAGE) coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y);
|
||||
else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen;
|
||||
else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
|
||||
if (!i) cr->move_to(currPos.x, currPos.y);
|
||||
else cr->line_to(currPos.x, currPos.y);
|
||||
if (!i) cr->move_to(currPos.x+0.5, currPos.y+0.5);
|
||||
else cr->line_to(currPos.x+0.5, currPos.y+0.5);
|
||||
}
|
||||
cr->fill();
|
||||
cr->stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -307,12 +354,12 @@ void Polyline::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPtr
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
currPos = points.at(i);
|
||||
|
||||
if (datum == IMAGE) coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y);
|
||||
if (datum == IMAGE) coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y);
|
||||
else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen;
|
||||
else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
|
||||
if (!i) cr->move_to(currPos.x, currPos.y);
|
||||
else cr->line_to(currPos.x, currPos.y);
|
||||
if (!i) cr->move_to(currPos.x+0.5, currPos.y+0.5);
|
||||
else cr->line_to(currPos.x+0.5, currPos.y+0.5);
|
||||
}
|
||||
if (filled) {
|
||||
if (innerLineWidth > 0.) {
|
||||
@@ -333,12 +380,12 @@ void Polyline::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPtr
|
||||
cr2->set_line_width( getOuterLineWidth() );
|
||||
currPos = points.at(i);
|
||||
|
||||
if (datum == IMAGE) coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y);
|
||||
if (datum == IMAGE) coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y);
|
||||
else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen;
|
||||
else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
|
||||
if (!i) cr2->move_to(currPos.x, currPos.y);
|
||||
else cr2->line_to(currPos.x, currPos.y);
|
||||
if (!i) cr2->move_to(currPos.x+0.5, currPos.y+0.5);
|
||||
else cr2->line_to(currPos.x+0.5, currPos.y+0.5);
|
||||
}
|
||||
if (filled) {
|
||||
if (innerLineWidth > 0.) {
|
||||
@@ -376,10 +423,16 @@ void Rectangle::setXYXY(Coord topLeft, Coord bottomRight) {
|
||||
|
||||
void Rectangle::drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) {
|
||||
if ((flags & ACTIVE)) {
|
||||
cr->set_source_rgb (outerLineColor.getR(), outerLineColor.getG(), outerLineColor.getB());
|
||||
RGBColor color;
|
||||
if (flags & AUTO_COLOR)
|
||||
color = getOuterLineColor();
|
||||
else
|
||||
color = outerLineColor;
|
||||
|
||||
cr->set_source_rgb (color.getR(), color.getG(), color.getB());
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
|
||||
Coord tl, br;
|
||||
cr->set_line_width( getOuterLineWidth() );
|
||||
|
||||
if (datum == IMAGE) coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y);
|
||||
else if (datum == CLICKED_POINT) tl = topLeft + editBuffer->getDataProvider()->posScreen;
|
||||
@@ -389,19 +442,28 @@ void Rectangle::drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, rtengine::
|
||||
else if (datum == CLICKED_POINT) br = bottomRight + editBuffer->getDataProvider()->posScreen;
|
||||
else if (datum == CURSOR) br = bottomRight +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
|
||||
cr->rectangle(tl.x, tl.y, br.x-tl.x, br.y-tl.y);
|
||||
cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y);
|
||||
|
||||
if (filled) {
|
||||
cr->fill_preserve();
|
||||
cr->stroke();
|
||||
}
|
||||
else
|
||||
cr->fill();
|
||||
cr->stroke();
|
||||
}
|
||||
}
|
||||
|
||||
void Rectangle::drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) {
|
||||
if (flags & ACTIVE) {
|
||||
RGBColor color;
|
||||
if (flags & AUTO_COLOR)
|
||||
color = getInnerLineColor();
|
||||
else
|
||||
color = innerLineColor;
|
||||
|
||||
cr->set_source_rgb (color.getR(), color.getG(), color.getB());
|
||||
cr->set_line_width( innerLineWidth );
|
||||
|
||||
Coord tl, br;
|
||||
if (datum == IMAGE) coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y);
|
||||
else if (datum == CLICKED_POINT) tl = topLeft + editBuffer->getDataProvider()->posScreen;
|
||||
@@ -411,11 +473,8 @@ void Rectangle::drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, rtengine::
|
||||
else if (datum == CLICKED_POINT) br = bottomRight + editBuffer->getDataProvider()->posScreen;
|
||||
else if (datum == CURSOR) br = bottomRight +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
|
||||
cr->set_source_rgb (innerLineColor.getR(), innerLineColor.getG(), innerLineColor.getB());
|
||||
|
||||
if (filled) {
|
||||
cr->set_line_width( innerLineWidth );
|
||||
cr->rectangle(tl.x, tl.y, br.x-tl.x, br.y-tl.y);
|
||||
cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y);
|
||||
if (innerLineWidth > 0.) {
|
||||
cr->fill_preserve();
|
||||
cr->stroke();
|
||||
@@ -424,7 +483,7 @@ void Rectangle::drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, rtengine::
|
||||
cr->fill();
|
||||
}
|
||||
else if (innerLineWidth > 0.) {
|
||||
cr->rectangle(tl.x, tl.y, br.x-tl.x, br.y-tl.y);
|
||||
cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y);
|
||||
cr->stroke();
|
||||
}
|
||||
}
|
||||
@@ -435,18 +494,18 @@ void Rectangle::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPt
|
||||
cr->set_line_width( getMouseOverLineWidth() );
|
||||
|
||||
Coord tl, br;
|
||||
if (datum == IMAGE) coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y);
|
||||
if (datum == IMAGE) coordSystem.imageCoordToCropBuffer(topLeft.x, topLeft.y, tl.x, tl.y);
|
||||
else if (datum == CLICKED_POINT) tl = topLeft + editBuffer->getDataProvider()->posScreen;
|
||||
else if (datum == CURSOR) tl = topLeft +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
|
||||
if (datum == IMAGE) coordSystem.imageCoordToScreen(bottomRight.x, bottomRight.y, br.x, br.y);
|
||||
if (datum == IMAGE) coordSystem.imageCoordToCropBuffer(bottomRight.x, bottomRight.y, br.x, br.y);
|
||||
else if (datum == CLICKED_POINT) br = bottomRight + editBuffer->getDataProvider()->posScreen;
|
||||
else if (datum == CURSOR) br = bottomRight +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen;
|
||||
|
||||
// drawing the lower byte's value
|
||||
unsigned short a = (id+1) & 0xFF;
|
||||
cr->set_source_rgba (0.,0., 0., double(a)/255.);
|
||||
cr->rectangle(tl.x, tl.y, br.x-tl.x, br.y-tl.y);
|
||||
cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y);
|
||||
if (filled) {
|
||||
if (innerLineWidth > 0.) {
|
||||
cr->fill_preserve();
|
||||
@@ -462,7 +521,7 @@ void Rectangle::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPt
|
||||
if (editBuffer->getObjectMode() == OM_65535) {
|
||||
a = (id+1)>>8;
|
||||
cr2->set_source_rgba (0.,0., 0., double(a)/255.);
|
||||
cr->rectangle(tl.x, tl.y, br.x-tl.x, br.y-tl.y);
|
||||
cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y);
|
||||
if (filled) {
|
||||
if (innerLineWidth > 0.) {
|
||||
cr2->fill_preserve();
|
||||
@@ -477,7 +536,7 @@ void Rectangle::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, Cairo::RefPt
|
||||
}
|
||||
}
|
||||
|
||||
EditSubscriber::EditSubscriber () : ID(EUID_None), editingType(ET_PIPETTE), bufferType(BT_SINGLEPLANE_FLOAT), provider(NULL) {}
|
||||
EditSubscriber::EditSubscriber (EditType editType) : ID(EUID_None), editingType(editType), bufferType(BT_SINGLEPLANE_FLOAT), provider(NULL) {}
|
||||
|
||||
void EditSubscriber::setEditProvider(EditDataProvider *provider) {
|
||||
this->provider = provider;
|
||||
|
122
rtgui/edit.h
122
rtgui/edit.h
@@ -23,6 +23,7 @@
|
||||
#include "../rtengine/imagefloat.h"
|
||||
#include "editid.h"
|
||||
#include "cursormanager.h"
|
||||
#include "../rtengine/rt_math.h"
|
||||
|
||||
class EditDataProvider;
|
||||
|
||||
@@ -59,6 +60,8 @@ class EditBuffer;
|
||||
*
|
||||
*/
|
||||
|
||||
class PolarCoord;
|
||||
|
||||
// Do not confuse with rtengine::Coord2D, this one is for the GUI
|
||||
class Coord {
|
||||
public:
|
||||
@@ -73,9 +76,17 @@ public:
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
void setFromPolar(float radius, float angle) {
|
||||
x = radius * cos(angle/(2*M_PI));
|
||||
y = radius * sin(angle/(2*M_PI));
|
||||
void setFromPolar(PolarCoord polar);
|
||||
|
||||
/// @brief Clip the coord to stay in the width x height bounds
|
||||
/// @return true if the x or y coordinate has changed
|
||||
bool clip(int width, int height) {
|
||||
int trimmedX = rtengine::LIM<int>(x, 0, width);
|
||||
int trimmedY = rtengine::LIM<int>(y, 0, height);
|
||||
bool retval = trimmedX!=x || trimmedY!=y;
|
||||
x = trimmedX;
|
||||
y = trimmedY;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void operator+=(const Coord & rhs) {
|
||||
@@ -104,6 +115,92 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class PolarCoord {
|
||||
public:
|
||||
double radius;
|
||||
double angle; // degree
|
||||
|
||||
PolarCoord() : radius(1.), angle(0.) {}
|
||||
PolarCoord(double radius, double angle) : radius(radius), angle(angle) {}
|
||||
|
||||
void set (double radius, double angle) {
|
||||
this->radius = radius;
|
||||
this->angle = angle;
|
||||
}
|
||||
|
||||
void setFromCartesian(Coord start, Coord end) {
|
||||
Coord delta(end.x-start.x, end.y-start.y);
|
||||
setFromCartesian(delta);
|
||||
}
|
||||
|
||||
void setFromCartesian(Coord delta) {
|
||||
if (!delta.x && !delta.y) {
|
||||
// null vector, we set to a default value
|
||||
radius = 1.;
|
||||
angle = 0.;
|
||||
return;
|
||||
}
|
||||
double x_ = double(delta.x);
|
||||
double y_ = double(delta.y);
|
||||
radius = sqrt(x_*x_+y_*y_);
|
||||
if (delta.x>0.) {
|
||||
if (delta.y>=0.)
|
||||
angle = atan(y_/x_)/(2*M_PI)*360.;
|
||||
else if (delta.y<0.)
|
||||
angle = (atan(y_/x_)+2*M_PI)/(2*M_PI)*360.;
|
||||
}
|
||||
else if (delta.x<0.)
|
||||
angle = (atan(y_/x_)+M_PI)/(2*M_PI)*360.;
|
||||
else if (delta.x==0.) {
|
||||
if (delta.y>0.)
|
||||
angle = 90.;
|
||||
else
|
||||
angle = 270.;
|
||||
}
|
||||
}
|
||||
|
||||
void operator+=(const PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord += rhsCoord;
|
||||
setFromCartesian(thisCoord);
|
||||
}
|
||||
void operator-=(const PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord -= rhsCoord;
|
||||
setFromCartesian(thisCoord);
|
||||
}
|
||||
void operator*=(double scale) {
|
||||
radius *= scale;
|
||||
}
|
||||
PolarCoord operator+(PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord += rhsCoord;
|
||||
PolarCoord result;
|
||||
result.setFromCartesian(thisCoord);
|
||||
return result;
|
||||
}
|
||||
PolarCoord operator-(PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord -= rhsCoord;
|
||||
PolarCoord result;
|
||||
result.setFromCartesian(thisCoord);
|
||||
return result;
|
||||
}
|
||||
Coord operator*(double scale) {
|
||||
Coord result(radius*scale, angle);
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** @brief Coordinate system where the widgets will be drawn
|
||||
*
|
||||
* The EditCoordSystem is used to define a screen and an image coordinate system.
|
||||
@@ -118,6 +215,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 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
|
||||
virtual int scaleValueToImage (int value) =0;
|
||||
/// Convert a size value from the preview's scale to the image's scale
|
||||
@@ -139,8 +238,8 @@ class RGBColor {
|
||||
|
||||
public:
|
||||
RGBColor () : r(0.), g(0.), b(0.) {}
|
||||
RGBColor (double r, double g, double b) : r(r), g(g), b(b) {}
|
||||
RGBColor (char r, char g, char b) : r(double(r)/255.), g(double(g)/255.), b(double(b)/255.) {}
|
||||
explicit RGBColor (double r, double g, double b) : r(r), g(g), b(b) {}
|
||||
explicit RGBColor (char r, char g, char b) : r(double(r)/255.), g(double(g)/255.), b(double(b)/255.) {}
|
||||
|
||||
void setColor(double r, double g, double b) {
|
||||
this->r = r;
|
||||
@@ -186,7 +285,7 @@ public:
|
||||
Datum datum;
|
||||
State state; // set by the Subscriber
|
||||
|
||||
Geometry () : innerLineColor(), outerLineColor(), flags(ACTIVE|AUTO_COLOR), innerLineWidth(1.f), datum(IMAGE), state(NORMAL) {}
|
||||
Geometry () : innerLineColor(char(255), char(255), char(255)), outerLineColor(char(0), char(0), char(0)), flags(ACTIVE|AUTO_COLOR), innerLineWidth(1.f), datum(IMAGE), state(NORMAL) {}
|
||||
virtual ~Geometry() {}
|
||||
|
||||
void setInnerLineColor (double r, double g, double b) { innerLineColor.setColor(r, g, b); flags &= ~AUTO_COLOR; }
|
||||
@@ -213,8 +312,8 @@ public:
|
||||
bool radiusInImageSpace; /// If true, the radius depend on the image scale; if false, it is a fixed 'screen' size
|
||||
|
||||
Circle () : center(100,100), radius(10), filled(false), radiusInImageSpace(false) {}
|
||||
Circle (Coord ¢er, int radius, bool filled=false) : center(center), radius(radius), filled(filled), radiusInImageSpace(false) {}
|
||||
Circle (int centerX, int centerY, int radius, bool filled=false) : center(centerX, centerY), radius(radius), filled(filled), radiusInImageSpace(false) {}
|
||||
Circle (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<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem);
|
||||
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem);
|
||||
@@ -280,7 +379,7 @@ protected:
|
||||
std::vector<Geometry*> mouseOverGeometry;
|
||||
|
||||
public:
|
||||
EditSubscriber ();
|
||||
EditSubscriber (EditType editType);
|
||||
virtual ~EditSubscriber () {}
|
||||
|
||||
void setEditProvider(EditDataProvider *provider);
|
||||
@@ -293,7 +392,10 @@ public:
|
||||
EditUniqueID getEditID();
|
||||
EditType getEditingType();
|
||||
BufferType getEditBufferType();
|
||||
CursorShape getCursor(int objectID) { return CSOpenHand; }
|
||||
|
||||
/** @brief Get the cursor to be displayed when above handles
|
||||
@param objectID object currently "hovered" */
|
||||
virtual CursorShape getCursor(int objectID) { return CSOpenHand; }
|
||||
|
||||
/** @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
|
||||
|
@@ -2,12 +2,14 @@
|
||||
* This file is part of RawTherapee.
|
||||
*/
|
||||
#include "gradient.h"
|
||||
#include "rtimage.h"
|
||||
#include <iomanip>
|
||||
#include "../rtengine/rt_math.h"
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this)
|
||||
Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this), EditSubscriber(ET_OBJECTS), lastObject(-1), draggedPointOldAngle(-1000.)
|
||||
{
|
||||
set_border_width(4);
|
||||
|
||||
@@ -15,6 +17,10 @@ Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this)
|
||||
enabled->set_active (false);
|
||||
enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &Gradient::enabledChanged) );
|
||||
|
||||
edit = Gtk::manage (new Gtk::ToggleButton());
|
||||
edit->add (*Gtk::manage (new RTImage ("editmodehand.png")));
|
||||
editConn = edit->signal_toggled().connect( sigc::mem_fun(*this, &Gradient::editToggled) );
|
||||
|
||||
strength = Gtk::manage (new Adjuster (M("TP_GRADIENT_STRENGTH"), -5, 5, 0.01, 0));
|
||||
strength->set_tooltip_text (M("TP_GRADIENT_STRENGTH_TOOLTIP"));
|
||||
strength->setAdjusterListener (this);
|
||||
@@ -35,7 +41,10 @@ Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this)
|
||||
centerY->set_tooltip_text (M("TP_GRADIENT_CENTER_Y_TOOLTIP"));
|
||||
centerY->setAdjusterListener (this);
|
||||
|
||||
pack_start(*enabled);
|
||||
Gtk::HBox* enaBox = Gtk::manage (new Gtk::HBox());
|
||||
enaBox->pack_start(*enabled);
|
||||
enaBox->pack_end(*edit, false, false, 0);
|
||||
pack_start(*enaBox);
|
||||
pack_start(*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4);
|
||||
pack_start (*strength);
|
||||
pack_start (*degree);
|
||||
@@ -43,9 +52,52 @@ Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this)
|
||||
pack_start (*centerX);
|
||||
pack_start (*centerY);
|
||||
|
||||
// Instantiating the Editing geometry; positions will be initialized later
|
||||
Line *hLine, *vLine;
|
||||
Circle *centerCircle;
|
||||
|
||||
// Visible geometry
|
||||
hLine = new Line(); hLine->innerLineWidth=2;
|
||||
vLine = new Line();
|
||||
hLine->datum = vLine->datum = Geometry::IMAGE;
|
||||
|
||||
centerCircle = new Circle();
|
||||
centerCircle->datum = Geometry::IMAGE;
|
||||
centerCircle->radiusInImageSpace = false;
|
||||
centerCircle->radius = 6;
|
||||
centerCircle->filled = true;
|
||||
|
||||
EditSubscriber::visibleGeometry.push_back( hLine );
|
||||
EditSubscriber::visibleGeometry.push_back( vLine );
|
||||
EditSubscriber::visibleGeometry.push_back( centerCircle );
|
||||
|
||||
// MouseOver geometry
|
||||
hLine = new Line(); hLine->innerLineWidth=2;
|
||||
vLine = new Line();
|
||||
hLine->datum = vLine->datum = Geometry::IMAGE;
|
||||
|
||||
centerCircle = new Circle();
|
||||
centerCircle->datum = Geometry::IMAGE;
|
||||
centerCircle->radiusInImageSpace = false;
|
||||
centerCircle->radius = 30;
|
||||
centerCircle->filled = true;
|
||||
|
||||
EditSubscriber::mouseOverGeometry.push_back( hLine );
|
||||
EditSubscriber::mouseOverGeometry.push_back( vLine );
|
||||
EditSubscriber::mouseOverGeometry.push_back( centerCircle );
|
||||
|
||||
show_all();
|
||||
}
|
||||
|
||||
Gradient::~Gradient() {
|
||||
for (std::vector<Geometry*>::const_iterator i = visibleGeometry.begin(); i != visibleGeometry.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
for (std::vector<Geometry*>::const_iterator i = mouseOverGeometry.begin(); i != mouseOverGeometry.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
||||
void Gradient::read (const ProcParams* pp, const ParamsEdited* pedited)
|
||||
{
|
||||
disableListener ();
|
||||
@@ -70,9 +122,43 @@ void Gradient::read (const ProcParams* pp, const ParamsEdited* pedited)
|
||||
|
||||
lastEnabled = pp->gradient.enabled;
|
||||
|
||||
updateGeometry (pp->gradient.centerX, pp->gradient.centerY, pp->gradient.strength, pp->gradient.degree);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void Gradient::updateGeometry(int centerX_, int centerY_, double strength_, double degree_) {
|
||||
EditDataProvider* dataProvider = getEditProvider();
|
||||
if (dataProvider) {
|
||||
int imW, imH;
|
||||
dataProvider->getImageSize(imW, imH);
|
||||
|
||||
Coord origin(imW/2+centerX_*imW/200.f, imH/2+centerY_*imH/200.f);
|
||||
|
||||
Line *currLine;
|
||||
Circle *currCircle;
|
||||
// update left line
|
||||
currLine = static_cast<Line*>(visibleGeometry.at(0));
|
||||
currLine->begin.setFromPolar(PolarCoord(1500.f, float(-degree_+180))); currLine->begin += origin;
|
||||
currLine->end.setFromPolar (PolarCoord(1500.f, float(-degree_ ))); currLine->end += origin;
|
||||
currLine = static_cast<Line*>(mouseOverGeometry.at(0));
|
||||
currLine->begin.setFromPolar(PolarCoord(1500.f, float(-degree_+180))); currLine->begin += origin;
|
||||
currLine->end.setFromPolar (PolarCoord(1500.f, float(-degree_ ))); currLine->end += origin;
|
||||
// update right line
|
||||
currLine = static_cast<Line*>(visibleGeometry.at(1));
|
||||
currLine->begin.setFromPolar(PolarCoord( 700.f, float(-degree_+90 ))); currLine->begin += origin;
|
||||
currLine->end.setFromPolar (PolarCoord( 700.f, float(-degree_+270))); currLine->end += origin;
|
||||
currLine = static_cast<Line*>(mouseOverGeometry.at(1));
|
||||
currLine->begin.setFromPolar(PolarCoord( 700.f, float(-degree_+90 ))); currLine->begin += origin;
|
||||
currLine->end.setFromPolar (PolarCoord( 700.f, float(-degree_+270))); currLine->end += origin;
|
||||
// update circle's position
|
||||
currCircle = static_cast<Circle*>(visibleGeometry.at(2));
|
||||
currCircle->center = origin;
|
||||
currCircle = static_cast<Circle*>(mouseOverGeometry.at(2));
|
||||
currCircle->center = origin;
|
||||
}
|
||||
}
|
||||
|
||||
void Gradient::write (ProcParams* pp, ParamsEdited* pedited)
|
||||
{
|
||||
pp->gradient.degree = degree->getValue ();
|
||||
@@ -118,6 +204,8 @@ void Gradient::setDefaults (const ProcParams* defParams, const ParamsEdited* ped
|
||||
void Gradient::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
if (listener && enabled->get_active()) {
|
||||
updateGeometry (int(centerX->getValue()), int(centerY->getValue()), strength->getValue(), degree->getValue());
|
||||
|
||||
if (a == degree)
|
||||
listener->panelChanged (EvGradientDegree, degree->getTextValue());
|
||||
else if (a == feather)
|
||||
@@ -178,3 +266,146 @@ void Gradient::setBatchMode (bool batchMode)
|
||||
centerX->showEditedCB ();
|
||||
centerY->showEditedCB ();
|
||||
}
|
||||
|
||||
void Gradient::setEditProvider (EditDataProvider* provider) {
|
||||
EditSubscriber::setEditProvider(provider);
|
||||
}
|
||||
|
||||
void Gradient::editToggled () {
|
||||
if (edit->get_active()) {
|
||||
subscribe();
|
||||
}
|
||||
else
|
||||
unsubscribe();
|
||||
}
|
||||
|
||||
// TODO
|
||||
CursorShape Gradient::getCursor(int objectID) {
|
||||
return CSOpenHand;
|
||||
}
|
||||
|
||||
bool Gradient::mouseOver(int modifierKey) {
|
||||
EditDataProvider* editProvider = getEditProvider();
|
||||
if (editProvider && editProvider->object!=lastObject) {
|
||||
if (lastObject > -1)
|
||||
EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL;
|
||||
if (editProvider->object > -1)
|
||||
EditSubscriber::visibleGeometry.at(editProvider->object)->state = Geometry::PRELIGHT;
|
||||
lastObject = editProvider->object;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Gradient::button1Pressed(int modifierKey) {
|
||||
if (!(modifierKey & (GDK_CONTROL_MASK | GDK_CONTROL_MASK))) {
|
||||
// button press is valid (no modifier key)
|
||||
PolarCoord pCoord;
|
||||
EditDataProvider *provider = getEditProvider();
|
||||
int imW, imH;
|
||||
provider->getImageSize(imW, imH);
|
||||
double halfSizeW = imW/2.;
|
||||
double halfSizeH = imH/2.;
|
||||
draggedCenter.set(int(halfSizeW+halfSizeW*(centerX->getValue()/100.)), int(halfSizeH+halfSizeH*(centerY->getValue()/100.)));
|
||||
|
||||
// trick to get the correct angle (clockwise/counter-clockwise)
|
||||
Coord p1 = draggedCenter;
|
||||
Coord p2 = provider->posImage;
|
||||
int p = p1.y;
|
||||
p1.y = p2.y;
|
||||
p2.y = p;
|
||||
|
||||
pCoord.setFromCartesian(p1, p2);
|
||||
draggedPointOldAngle = pCoord.angle;
|
||||
draggedPointAdjusterAngle = degree->getValue();
|
||||
//printf("\ndraggedPointOldAngle=%.3f\n\n", draggedPointOldAngle);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// this will let this class ignore further drag events
|
||||
if (lastObject > -1) // should theoretically always be true
|
||||
EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL;
|
||||
lastObject = -1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Gradient::button1Released() {
|
||||
draggedPointOldAngle = -1000.;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Gradient::drag(int modifierKey) {
|
||||
// compute the polar coordinate of the mouse position
|
||||
EditDataProvider *provider = getEditProvider();
|
||||
int imW, imH;
|
||||
provider->getImageSize(imW, imH);
|
||||
double halfSizeW = imW/2.;
|
||||
double halfSizeH = imH/2.;
|
||||
|
||||
if (lastObject==0 || lastObject==1) {
|
||||
|
||||
// Dragging a line to change the angle
|
||||
PolarCoord draggedPoint;
|
||||
Coord currPos;
|
||||
currPos = provider->posImage+provider->deltaImage;
|
||||
Coord centerPos = draggedCenter;
|
||||
|
||||
// trick to get the correct angle (clockwise/counter-clockwise)
|
||||
int p = centerPos.y;
|
||||
centerPos.y = currPos.y;
|
||||
currPos.y = p;
|
||||
|
||||
draggedPoint.setFromCartesian(centerPos, currPos);
|
||||
double deltaAngle = draggedPoint.angle - draggedPointOldAngle;
|
||||
if (deltaAngle>180.) // crossing the boundary (0->360)
|
||||
deltaAngle -= 360.;
|
||||
else if (deltaAngle<-180.) // crossing the boundary (360->0)
|
||||
deltaAngle += 360.;
|
||||
draggedPointOldAngle = draggedPoint.angle;
|
||||
|
||||
draggedPointAdjusterAngle += deltaAngle;
|
||||
if (draggedPointAdjusterAngle > 180.)
|
||||
draggedPointAdjusterAngle = -360. + draggedPointAdjusterAngle;
|
||||
else if (draggedPointAdjusterAngle < -180.)
|
||||
draggedPointAdjusterAngle = 360. - draggedPointAdjusterAngle;
|
||||
//printf("draggedPointOldAngle: %.3f / From %d,%d to %d,%d -> angle = %.3f / ", draggedPointAdjusterAngle, centerPos.x, centerPos.y, currPos.x, currPos.y, draggedPoint.angle);
|
||||
//printf("currAngle: %.3f = degree: %.3f + deltaAngle: %.3f %s / draggedPointOldAngle: %.3f\n", draggedPointAdjusterAngle, degree->getValue(), deltaAngle, degree->getValue()>180.?">180":degree->getValue()<180.?"<180":"", draggedPointOldAngle);
|
||||
if (int(draggedPointAdjusterAngle) != degree->getIntValue()) {
|
||||
degree->setValue(draggedPointAdjusterAngle);
|
||||
updateGeometry (int(centerX->getValue()), int(centerY->getValue()), strength->getValue(), degree->getValue());
|
||||
if (listener)
|
||||
listener->panelChanged (EvGradientDegree, degree->getTextValue());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (lastObject==2) {
|
||||
// Dragging the circle to change the center
|
||||
Coord currPos;
|
||||
draggedCenter += provider->deltaPrevImage;
|
||||
currPos = draggedCenter;
|
||||
currPos.clip(imW, imH);
|
||||
int newCenterX = int((double(currPos.x)-halfSizeW)/halfSizeW*100.);
|
||||
int newCenterY = int((double(currPos.y)-halfSizeH)/halfSizeH*100.);
|
||||
if (newCenterX!=centerX->getIntValue() || newCenterY!=centerY->getIntValue()) {
|
||||
centerX->setValue(newCenterX);
|
||||
centerY->setValue(newCenterY);
|
||||
updateGeometry (newCenterX, newCenterY, strength->getValue(), degree->getValue());
|
||||
if (listener)
|
||||
listener->panelChanged (EvGradientCenter, Glib::ustring::compose ("X=%1\nY=%2", centerX->getTextValue(), centerY->getTextValue()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Gradient::switchOffEditMode () {
|
||||
if (edit->get_active()) {
|
||||
// switching off the toggle button
|
||||
bool wasBlocked = editConn.block(true);
|
||||
edit->set_active(false);
|
||||
if (!wasBlocked) editConn.block(false);
|
||||
}
|
||||
EditSubscriber::switchOffEditMode(); // disconnect
|
||||
}
|
||||
|
||||
|
@@ -7,32 +7,55 @@
|
||||
#include <gtkmm.h>
|
||||
#include "adjuster.h"
|
||||
#include "toolpanel.h"
|
||||
#include "edit.h"
|
||||
|
||||
class Gradient : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel {
|
||||
class Gradient : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public EditSubscriber {
|
||||
|
||||
private:
|
||||
int lastObject;
|
||||
|
||||
protected:
|
||||
Gtk::CheckButton* enabled;
|
||||
Gtk::ToggleButton* edit;
|
||||
Adjuster* degree;
|
||||
Adjuster* feather;
|
||||
Adjuster* strength;
|
||||
Adjuster* centerX;
|
||||
Adjuster* centerY;
|
||||
double draggedPointOldAngle;
|
||||
double draggedPointAdjusterAngle;
|
||||
Coord draggedCenter;
|
||||
bool lastEnabled;
|
||||
sigc::connection enaConn;
|
||||
sigc::connection enaConn, editConn;
|
||||
|
||||
void editToggled ();
|
||||
|
||||
public:
|
||||
|
||||
Gradient ();
|
||||
~Gradient ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void updateGeometry (int centerX_, int centerY_, double strength_, 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 setEditProvider (EditDataProvider* provider);
|
||||
|
||||
// EditSubscriber interface
|
||||
CursorShape getCursor(int objectID);
|
||||
bool mouseOver(int modifierKey);
|
||||
bool button1Pressed(int modifierKey);
|
||||
bool button1Released();
|
||||
bool drag(int modifierKey);
|
||||
void switchOffEditMode ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -181,8 +181,10 @@ bool ImageArea::on_expose_event(GdkEventExpose* event) {
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
|
||||
|
||||
if (mainCropWindow)
|
||||
if (mainCropWindow) {
|
||||
//printf("MainCropWindow (%d x %d)\n", window->get_width(), window->get_height());
|
||||
mainCropWindow->expose (cr);
|
||||
}
|
||||
|
||||
if (options.showInfo==true && infotext!="") {
|
||||
int fnw, fnh;
|
||||
@@ -279,10 +281,19 @@ void ImageArea::subscribe(EditSubscriber *subscriber) {
|
||||
|
||||
if (listener && listener->getToolBar())
|
||||
listener->getToolBar()->startEditMode ();
|
||||
|
||||
if (subscriber->getEditingType() == ET_OBJECTS) {
|
||||
// In this case, no need to reprocess the image, so we redraw the image to display the geometry
|
||||
queue_draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ImageArea::unsubscribe() {
|
||||
bool wasObjectType = false;
|
||||
EditSubscriber* oldSubscriber = EditDataProvider::getCurrSubscriber();
|
||||
if (oldSubscriber && oldSubscriber->getEditingType()==ET_OBJECTS)
|
||||
wasObjectType = true;
|
||||
|
||||
EditDataProvider::unsubscribe();
|
||||
// Ask the Crops to free-up edit mode buffers
|
||||
mainCropWindow->cropHandler.setEditSubscriber(NULL);
|
||||
@@ -292,6 +303,9 @@ void ImageArea::unsubscribe() {
|
||||
|
||||
if (listener && listener->getToolBar())
|
||||
listener->getToolBar()->stopEditMode ();
|
||||
|
||||
if (wasObjectType)
|
||||
queue_draw();
|
||||
}
|
||||
|
||||
void ImageArea::getImageSize (int &w, int&h) {
|
||||
|
525
tools/coordinate_system.svg
Normal file
525
tools/coordinate_system.svg
Normal file
@@ -0,0 +1,525 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="coordinate_system.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3822"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
|
||||
transform="scale(0.8) translate(12.5,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3825"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
|
||||
transform="scale(0.8) rotate(180) translate(12.5,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3825-0"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.70710678"
|
||||
inkscape:cx="299.66147"
|
||||
inkscape:cy="714.81018"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="991"
|
||||
inkscape:window-height="915"
|
||||
inkscape:window-x="738"
|
||||
inkscape:window-y="60"
|
||||
inkscape:window-maximized="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="opacity:1;fill:#aaaaaa;fill-opacity:1;stroke:none"
|
||||
id="rect2993"
|
||||
width="745.49261"
|
||||
height="529.31982"
|
||||
x="-7.3357637e-06"
|
||||
y="270.50415" />
|
||||
<rect
|
||||
style="fill:none;stroke:#ff0000;stroke-width:1.99999976;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3765-5"
|
||||
width="789.93921"
|
||||
height="571.79712"
|
||||
x="-20.708122"
|
||||
y="248.76044" />
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3765"
|
||||
width="788.92926"
|
||||
height="527.3504"
|
||||
x="-21.213203"
|
||||
y="271.4635" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="724.4317"
|
||||
y="1097.9205"
|
||||
id="text3804"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3806"
|
||||
x="724.4317"
|
||||
y="1097.9205">imgAreaW</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="-969.88525"
|
||||
y="783.78394"
|
||||
id="text3808"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(0,-1,1,0,0,0)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3810"
|
||||
x="-969.88525"
|
||||
y="783.78394">imgAreaH</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
|
||||
d="m 630.33519,1073.6769 c 81.82235,0 117.17769,0 117.17769,0"
|
||||
id="path3812"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
|
||||
d="m 760.64487,954.37739 0,97.98481"
|
||||
id="path3814"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 780.84792,1052.3622 -35.35534,0 0,35.3553"
|
||||
id="path3816"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="3.2830606"
|
||||
y="200.49203"
|
||||
id="text3804-1"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="3.2830606"
|
||||
y="200.49203"
|
||||
id="tspan5224"
|
||||
style="font-size:14px">leftBorder</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lend-0);marker-end:url(#Arrow1Lstart)"
|
||||
d="m -20.712438,227.69388 c 15.3477121,0 21.9794413,0 21.9794413,0"
|
||||
id="path3812-2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -20.960665,247.01806 c -0.252538,-1.13443 0,-33.33502 0,-33.33502"
|
||||
id="path5216"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5218"
|
||||
d="m 0.28172058,247.01806 c -0.252538,-1.13443 0,-33.33502 0,-33.33502"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lend-0);marker-end:url(#Arrow1Lstart)"
|
||||
d="m -57.142858,276.75164 0,-5.20748"
|
||||
id="path5228"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -21.428571,270.93361 -48.571429,0"
|
||||
id="path5602"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="-239.34459"
|
||||
y="-85.32505"
|
||||
id="text5604"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(0,-1,1,0,0,0)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5606"
|
||||
x="-239.34459"
|
||||
y="-85.32505"
|
||||
style="font-size:14px">upperBorder</tspan></text>
|
||||
<rect
|
||||
y="182.76044"
|
||||
x="1010.2919"
|
||||
height="43.797119"
|
||||
width="82.939209"
|
||||
id="rect5608"
|
||||
style="fill:none;stroke:#ff0000;stroke-width:1.99999976;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="250.4635"
|
||||
x="1010.7867"
|
||||
height="44.350399"
|
||||
width="82.92926"
|
||||
id="rect5610"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="1113"
|
||||
y="209.36218"
|
||||
id="text5612"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5614"
|
||||
x="1113"
|
||||
y="209.36218">Requested processing image size (including processing borders)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="1114"
|
||||
y="277.36218"
|
||||
id="text5616"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5618"
|
||||
x="1114"
|
||||
y="277.36218">Allocated processing image size (including possible processing border)</tspan></text>
|
||||
<rect
|
||||
y="321.50415"
|
||||
x="1009"
|
||||
height="56.319824"
|
||||
width="84.492615"
|
||||
id="rect5620"
|
||||
style="opacity:1;fill:#aaaaaa;fill-opacity:1;stroke:none" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="1115"
|
||||
y="351.36218"
|
||||
id="text5622"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5624"
|
||||
x="1115"
|
||||
y="351.36218">Allocated pixbuf size for display (no extra border here!)</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#00ff00;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect5626"
|
||||
width="123.03658"
|
||||
height="115.96552"
|
||||
x="96.166527"
|
||||
y="621.02704" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:none"
|
||||
id="path5628"
|
||||
sodipodi:cx="15.25"
|
||||
sodipodi:cy="287.11218"
|
||||
sodipodi:rx="16.25"
|
||||
sodipodi:ry="16.25"
|
||||
d="m 31.5,287.11218 a 16.25,16.25 0 1 1 -32.5,0 16.25,16.25 0 1 1 32.5,0 z"
|
||||
transform="matrix(0.26153846,0,0,0.26153846,-3.2384615,197.0213)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5630"
|
||||
d="m -151.14286,272.55957 0,-271.4238"
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lend-0);marker-end:url(#Arrow1Lstart);fill-opacity:1"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5632"
|
||||
d="m -107.42857,270.93361 -48.57143,0"
|
||||
style="fill:none;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -3.9596642,1.2452264 -156.5142958,0"
|
||||
id="path5634"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5636"
|
||||
d="m -1.7638416,-40.209531 5.20748,0"
|
||||
style="fill:none;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lend-0);marker-end:url(#Arrow1Lstart)" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:#0000ff;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
d="m 0.85714,-5.5882963 0,-46.0540437"
|
||||
id="path5638"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="-26.162951"
|
||||
y="-67.694962"
|
||||
id="text6012"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6014"
|
||||
x="-26.162951"
|
||||
y="-67.694962" /></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#0000ff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="-23.334524"
|
||||
y="-64.159424"
|
||||
id="text6016"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6018"
|
||||
x="-23.334524"
|
||||
y="-64.159424"
|
||||
style="font-size:14px">imgX</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#0000ff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="-134.76872"
|
||||
y="-163.5605"
|
||||
id="text6020"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(0,-1,1,0,0,0)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6022"
|
||||
x="-134.76872"
|
||||
y="-163.5605"
|
||||
style="font-size:14px">imgY</tspan></text>
|
||||
<rect
|
||||
y="108.29912"
|
||||
x="344.66907"
|
||||
height="288.49957"
|
||||
width="292.74222"
|
||||
id="rect6024"
|
||||
style="fill:#00d500;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="155.95285"
|
||||
x="353.55338"
|
||||
height="230.92076"
|
||||
width="273.14529"
|
||||
id="rect6028"
|
||||
style="fill:#aaaaaa;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
style="fill:none;stroke:#00d500;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lend-0);marker-end:url(#Arrow1Lstart)"
|
||||
d="m -1.7638416,-138.20953 348.7074816,0"
|
||||
id="path6030"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path6032"
|
||||
d="m 0.85714,-103.5883 0,-46.05404"
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:#00d500;stroke-width:0.99999987999999995px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6034"
|
||||
y="-156.65942"
|
||||
x="144.66548"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#00d500;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="-156.65942"
|
||||
x="144.66548"
|
||||
id="tspan6036"
|
||||
sodipodi:role="line"
|
||||
style="font-size:14px">xpos</tspan></text>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="fill:#0101ff;fill-opacity:1;stroke:#00d500;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
d="m 345.91779,42.117984 0,-189.631354"
|
||||
id="path6038"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:#00d500;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lend-0);marker-end:url(#Arrow1Lstart)"
|
||||
d="m -43.14286,115.27439 0,-121.8534376"
|
||||
id="path6040"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#00d500;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 279.23572,108.93361 -341.400037,0"
|
||||
id="path6042"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#00d500;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="-71.767334"
|
||||
y="-61.683151"
|
||||
id="text6044"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
inkscape:transform-center-x="11.5"
|
||||
inkscape:transform-center-y="-11"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6046"
|
||||
x="-71.767334"
|
||||
y="-61.683151"
|
||||
style="font-size:14px">ypos</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lend-0);marker-end:url(#Arrow1Lstart)"
|
||||
d="m 343.23616,54.290469 13.70748,0"
|
||||
id="path6048"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path6050"
|
||||
d="m 345.85714,103.75231 0,-60.735258"
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:#0000ff;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6052"
|
||||
y="34.583218"
|
||||
x="349.59616"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#0000ff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="34.583218"
|
||||
x="349.59616"
|
||||
id="tspan6054"
|
||||
sodipodi:role="line">imgX</tspan></text>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:#0101ff;stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
d="m 353.85714,146.29539 0,-102.821417"
|
||||
id="path6056"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:#0000ff;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lend-0);marker-end:url(#Arrow1Lstart)"
|
||||
d="m 294.39329,156.93092 0,-59.258382"
|
||||
id="path6058"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 345.95545,156.93361 -59.83945,0"
|
||||
id="path6060"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
transform="matrix(0.23076923,0,0,0.23076923,350.23077,90.355525)"
|
||||
d="m 31.5,287.11218 a 16.25,16.25 0 1 1 -32.5,0 16.25,16.25 0 1 1 32.5,0 z"
|
||||
sodipodi:ry="16.25"
|
||||
sodipodi:rx="16.25"
|
||||
sodipodi:cy="287.11218"
|
||||
sodipodi:cx="15.25"
|
||||
id="path6062"
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6064"
|
||||
y="280.43951"
|
||||
x="-147.26872"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#0000ff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="280.43951"
|
||||
x="-147.26872"
|
||||
id="tspan6066"
|
||||
sodipodi:role="line">imgY</tspan></text>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path6068"
|
||||
d="m 337.95545,108.93361 -59.83945,0"
|
||||
style="fill:none;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<rect
|
||||
y="132.46352"
|
||||
x="330.78668"
|
||||
height="285.3504"
|
||||
width="320.92926"
|
||||
id="rect6072"
|
||||
style="fill:none;stroke:#ff0000;stroke-width:1.99999988000000006;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:1.99999988;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect6070"
|
||||
width="320.92926"
|
||||
height="285.3504"
|
||||
x="328.78668"
|
||||
y="130.46352" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="22"
|
||||
y="31.362183"
|
||||
id="text6078"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6080"
|
||||
x="22"
|
||||
y="31.362183" /></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="479.60809"
|
||||
y="-14.880458"
|
||||
id="text6082"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6084"
|
||||
x="479.60809"
|
||||
y="-14.880458">CropWindow (mainCropWindow)</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6086"
|
||||
y="100.36218"
|
||||
x="532"
|
||||
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="100.36218"
|
||||
x="532"
|
||||
id="tspan6088"
|
||||
sodipodi:role="line">CropWindow</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 23 KiB |
Reference in New Issue
Block a user