You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegraphics/libkscan/img_canvas.cpp

1116 lines
27 KiB

/* This file is part of the KDE Project
Copyright (C) 1999 Klaas Freitag <freitag@suse.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <tqapplication.h>
#include <tqfiledialog.h>
#include <tqstring.h>
#include <tqmessagebox.h>
#include <tqscrollview.h>
#include <kpopupmenu.h>
#include <tqlabel.h>
#include <tqdict.h>
#include <tqimage.h>
#include <tqpainter.h>
#include <klocale.h>
#include <kstyle.h>
#include <kapplication.h>
#include <kpixmapio.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kcmenumngr.h>
#include <tqpixmap.h>
#define __IMG_CANVAS_CPP__
#include "imgscaledialog.h"
#include "img_canvas.h"
#define MIN(x,y) (x<y?x:y)
inline void debug_rect( const char *name, TQRect *r )
{
kdDebug(29000) << (name ? name: "NONAME") << ": " << r->x() << ", " << r->y() << ", " << r->width() << ", " << r->height() << endl;
}
class ImageCanvas::ImageCanvasPrivate
{
public:
ImageCanvasPrivate()
: keepZoom(false),
readOnly(false),
scaleKind( UNSPEC ),
defaultScaleKind( FIT_ORIG )
{}
bool keepZoom; /* keep the zoom settings if images change */
bool readOnly;
ScaleKinds scaleKind;
ScaleKinds defaultScaleKind;
TQValueList<TQRect> highlightRects;
};
ImageCanvas::ImageCanvas(TQWidget *tqparent,
const TQImage *start_image,
const char *name ):
TQScrollView( tqparent, name ),
m_contextMenu(0)
{
d = new ImageCanvasPrivate();
scale_factor = 100; // means original size
maintain_aspect = true;
selected = new TQRect;
selected->setWidth(0);
selected->setHeight(0);
timer_id = 0;
pmScaled = 0;
image = start_image;
moving = MOVE_NONE;
TQSize img_size;
if( image && ! image->isNull() )
{
img_size = image->size();
pmScaled = new TQPixmap( img_size );
#ifdef USE_KPIXMAPIO
*pmScaled = pixIO.convertToPixmap(*image);
#else
pmScaled->convertFromImage( *image );
#endif
acquired = true;
} else {
img_size = size();
}
update_scaled_pixmap();
// timer-Start and stop
connect( this, TQT_SIGNAL( newRect()), TQT_SLOT( newRectSlot()));
connect( this, TQT_SIGNAL( noRect()), TQT_SLOT( noRectSlot()));
//zoomOut();scrollview/scrollview
viewport()->setCursor( crossCursor );
cr1 = 0;
cr2 = 0;
viewport()->setMouseTracking(TRUE);
viewport()->setBackgroundMode(PaletteBackground);
show();
}
ImageCanvas::~ImageCanvas()
{
kdDebug(29000) << "Destructor of ImageCanvas" << endl;
noRectSlot();
if( selected ) delete selected;
selected = 0;
if( pmScaled ) delete pmScaled;
pmScaled = 0;
delete d;
}
void ImageCanvas::deleteView( TQImage *delimage )
{
const TQImage *img = rootImage();
if( delimage == img )
{
kdDebug(29000) << "ImageCanvas -> emiting newImage(0L)" << endl;
newImage( 0L );
noRectSlot();
}
}
void ImageCanvas::newImageHoldZoom( TQImage *new_image )
{
bool holdZ = d->keepZoom;
d->keepZoom = true;
newImage( new_image );
d->keepZoom = holdZ;
}
void ImageCanvas::newImage( TQImage *new_image )
{
/** do cleanups **/
// dont free old image -> not yours
image = new_image;
if( ! image || image->isNull())
{
kdDebug(29000) << "newImage: Got Empty image !" << endl;
}
if( pmScaled )
{
delete pmScaled;
pmScaled = 0L;
}
if( selected )
{
noRectSlot();
}
/* throw away all highlights */
d->highlightRects.clear();
/** handle the new image **/
if( image )
{
if( image->depth() == 1 ) {
pmScaled = new TQPixmap( image->size(), 1 );
} else {
int i = TQPixmap::defaultDepth();
pmScaled = new TQPixmap( image->size(), i);
}
// image->convertDepth(32);
#ifdef USE_KPIXMAPIO
*pmScaled = pixIO.convertToPixmap(*image);
#else
pmScaled->convertFromImage( *image );
// *pmScaled = image->convertToPixmap( );
#endif
acquired = true;
if( d->keepZoom )
{
kdDebug(29000) << "Preserving Zoom settings!" << endl;
}
else
{
kdDebug(29000) << "Resetting Zoom to original size!" << endl;
setScaleKind( defaultScaleKind() );
}
update_scaled_pixmap();
setContentsPos(0,0);
} else {
kdDebug(29000) << "New image called without image => deleting!" << endl;
acquired = false;
resizeContents( 0,0 );
}
kdDebug(29000) << "going to tqrepaint!" << endl;
tqrepaint( true );
kdDebug(29000) << "tqrepaint ok" << endl;
}
TQSize ImageCanvas::tqsizeHint() const
{
return( TQSize( 2, 2 ));
}
void ImageCanvas::enableContextMenu( bool wantContextMenu )
{
if( wantContextMenu )
{
if( ! m_contextMenu )
{
m_contextMenu = new KPopupMenu(this, "IMG_CANVAS");
KContextMenuManager::insert( viewport(), m_contextMenu );
}
}
else
{
/* remove all items */
if( m_contextMenu ) m_contextMenu->clear();
/* contextMenu is not deleted because there is no way to remove
* it from the contextMenuManager
*/
}
}
void ImageCanvas::handle_popup( int item )
{
if( item < ID_POP_ZOOM || item > ID_ORIG_SIZE ) return;
if( ! image ) return;
ImgScaleDialog *zoomDia = 0;
switch( item )
{
case ID_POP_ZOOM:
zoomDia = new ImgScaleDialog( this, getScaleFactor() );
if( zoomDia->exec() )
{
int sf = zoomDia->getSelected();
setScaleKind(ZOOM);
setScaleFactor( sf );
}
delete zoomDia;
zoomDia = 0;
break;
case ID_ORIG_SIZE:
setScaleKind( FIT_ORIG );
break;
case ID_FIT_WIDTH:
setScaleKind( FIT_WIDTH );
break;
case ID_FIT_HEIGHT:
setScaleKind( FIT_HEIGHT );
break;
case ID_POP_CLOSE:
emit( closingRequested());
break;
default: break;
}
update_scaled_pixmap();
tqrepaint();
}
/**
* Returns the selected rect in tenth of percent, not in absolute
* sizes, eg. 500 means 50.0 % of original width/height.
* That makes it easier to work with different scales and units
*/
TQRect ImageCanvas::sel( void )
{
TQRect retval;
retval.setCoords(0, 0, 0, 0);
if( selected && image && selected->width()>MIN_AREA_WIDTH
&& selected->height()>MIN_AREA_HEIGHT )
{
/* Get the size in real image pixels */
// debug_rect( "PRE map", selected );
TQRect mapped = inv_scale_matrix.map( (const TQRect) *selected );
// debug_rect( "Postmap", &mapped );
if( mapped.x() > 0 )
retval.setLeft((int) (1000.0/( (double)image->width() / (double)mapped.x())));
if( mapped.y() > 0 )
retval.setTop((int) (1000.0/( (double)image->height() / (double)mapped.y())));
if( mapped.width() > 0 )
retval.setWidth((int) (1000.0/( (double)image->width() / (double)mapped.width())));
if( mapped.height() > 0 )
retval.setHeight((int)(1000.0/( (double)image->height() / (double)mapped.height())));
}
// debug_rect( "sel() return", &retval );
return( retval );
}
bool ImageCanvas::selectedImage( TQImage *retImg )
{
TQRect r = sel();
bool result = false;
const TQImage* entireImg = this->rootImage();
if( entireImg )
{
TQSize s = entireImg->size();
int x = (s.width() * r.x())/1000;
int y = (s.height() * r.y())/1000;
int w = (s.width() * r.width())/1000;
int h = (s.height() * r.height())/1000;
if( w > 0 && h > 0 ) {
*retImg = entireImg->copy( x, y, w, h );
result = true;
}
}
return(result);
}
void ImageCanvas::drawContents( TQPainter * p, int clipx, int clipy, int clipw, int cliph )
{
if( !pmScaled ) return;
int x1 = 0;
int y1 = 0;
int x2 = pmScaled->width();
int y2 = pmScaled->height();
if (x1 < clipx) x1=clipx;
if (y1 < clipy) y1=clipy;
if (x2 > clipx+clipw-1) x2=clipx+clipw-1;
if (y2 > clipy+cliph-1) y2=clipy+cliph-1;
// Paint using the small coordinates...
// p->scale( used_xscaler, used_yscaler );
// p->scale( used_xscaler, used_yscaler );
if ( x2 >= x1 && y2 >= y1 ) {
p->tqdrawPixmap( x1, y1, *pmScaled, x1, y1 ); //, clipw, cliph);
// p->setBrush( red );
// p->drawRect( x1, y1, clipw, cliph );
}
// p->fillRect(x1, y1, x2-x1+1, y2-y1+1, red);
}
void ImageCanvas::timerEvent(TQTimerEvent *)
{
if(moving!=MOVE_NONE || !acquired ) return;
cr1++;
TQPainter p(viewport());
// p.setWindow( contentsX(), contentsY(), contentsWidth(), contentsHeight());
drawAreaBorder(&p);
}
void ImageCanvas::newRectSlot( TQRect newSel )
{
TQRect to_map;
TQPainter p(viewport());
drawAreaBorder(&p,TRUE);
selected->setWidth(0);
selected->setHeight(0);
emit( noRect() );
if ( image )
{
int rx, ry, rw, rh;
int w = image->width();
int h = image->height();
kdDebug(29000) << "ImageCanvas: Image size is " << w << "x" << h << endl;
kdDebug(29000) << "ImageCanvas got selection Rect: W=" << newSel.width() << ", H=" << newSel.height() << endl;
// to_map.setWidth(static_cast<int>(w * newSel.width() / 1000.0));
rw = static_cast<int>(w * newSel.width() / 1000.0);
rx = static_cast<int>(w * newSel.x() / 1000.0);
ry = static_cast<int>(h * newSel.y() / 1000.0);
rh = static_cast<int>(h * newSel.height() / 1000.0);
kdDebug(29000) << "ImageCanvas: scaled Height is " << rh << endl;
to_map.setRect( rx, ry, rw, rh );
kdDebug(29000) << "ImageCanvas Selection: W=" << to_map.width() << " H=" << to_map.height() << endl;
*selected = scale_matrix.map( to_map );
kdDebug(29000) << "ImageCanvas Selection: W=" << selected->width() << " H=" << selected->height() << endl;
emit( newRect( sel() ));
newRectSlot();
}
}
void ImageCanvas::newRectSlot( )
{
// printf( "Timer switched on !\n" );
if( timer_id == 0 )
timer_id = startTimer( 100 );
}
void ImageCanvas::noRectSlot( void )
{
// printf( "Timer switched off !\n" );
if( timer_id ) {
killTimer( timer_id );
timer_id = 0;
}
if( selected )
selected->setCoords( 0,0,0,0 );
}
void ImageCanvas::viewportMousePressEvent(TQMouseEvent *ev)
{
if( ! acquired || ! image ) return;
if(ev->button()==Qt::LeftButton )
{
int cx = contentsX(), cy = contentsY();
int x = lx = ev->x(),y = ly = ev->y();
int ix, iy;
scale_matrix.map( image->width(), image->height(), &ix, &iy );
if( x > ix-cx || y > iy-cy ) return;
if( moving == MOVE_NONE )
{
TQPainter p( viewport());
drawAreaBorder(&p,TRUE);
moving = classifyPoint( x+cx ,y+cy);
if(moving == MOVE_NONE)
{ //Create new area
selected->setCoords( x+cx, y+cy, x+cx, y+cy );
moving = MOVE_BOTTOM_RIGHT;
}
drawAreaBorder(&p);
}
}
}
void ImageCanvas::viewportMouseReleaseEvent(TQMouseEvent *ev)
{
if(ev->button()!=Qt::LeftButton || !acquired ) return;
//// debug( "Mouse Release at %d/%d", ev->x(), ev->y());
if(moving!=MOVE_NONE) {
TQPainter p(viewport());
drawAreaBorder(&p,TRUE);
moving = MOVE_NONE;
*selected = selected->normalize();
if(selected->width () < MIN_AREA_WIDTH ||
selected->height() < MIN_AREA_HEIGHT)
{
selected->setWidth(0);
selected->setHeight(0);
emit noRect();
return;
}
drawAreaBorder(&p);
emit newRect( sel() );
emit newRect( );
}
}
void ImageCanvas::viewportMouseMoveEvent(TQMouseEvent *ev)
{
if( ! acquired || !image) return;
static cursor_type ps = HREN;
int x = ev->x(), y = ev->y();
int cx = contentsX(), cy = contentsY();
// debug("Mouse Coord x: %d, y: %d | cx: %d, cy: %d", x,y, cx, cy );
// dont draw out of the scaled Pixmap
if( x < 0 ) x = 0;
int ix, iy;
scale_matrix.map( image->width(), image->height(), &ix, &iy );
if( x >= ix ) return;
if( y < 0 ) y = 0;
if( y >= iy ) return;
// debug( "cx, cy: %dx%d, x,y: %d, %d",
// cx, cy, x, y );
#if 0
if( moving == MOVE_NONE )
moving = classifyPoint(x, y);
#endif
switch( moving!=MOVE_NONE ? moving:classifyPoint(x+cx,y+cy) ) {
case MOVE_NONE:
if(ps!=CROSS) {
viewport()->setCursor(crossCursor);
ps = CROSS;
}
break;
case MOVE_LEFT:
case MOVE_RIGHT:
if(ps!=HSIZE) {
viewport()->setCursor(sizeHorCursor);
ps = HSIZE;
}
break;
case MOVE_TOP:
case MOVE_BOTTOM:
if(ps!=VSIZE) {
viewport()->setCursor(sizeVerCursor);
ps = VSIZE;
}
break;
case MOVE_TOP_LEFT:
case MOVE_BOTTOM_RIGHT:
if(ps!=FDIAG) {
viewport()->setCursor(sizeFDiagCursor);
ps = FDIAG;
}
break;
case MOVE_TOP_RIGHT:
case MOVE_BOTTOM_LEFT:
if(ps!=BDIAG) {
viewport()->setCursor(sizeBDiagCursor);
ps = BDIAG;
}
break;
case MOVE_WHOLE:
if(ps!=ALL) {
viewport()->setCursor(sizeAllCursor);
ps = ALL;
}
}
//At ButtonRelease : normalize + clip
if( moving!=MOVE_NONE ) {
int mx, my;
TQPainter p(viewport());
drawAreaBorder(&p,TRUE);
switch(moving) {
case MOVE_NONE: //Just to make compiler happy
break;
case MOVE_TOP_LEFT:
selected->setLeft( x + cx );
case MOVE_TOP: // fall through
selected->setTop( y + cy );
break;
case MOVE_TOP_RIGHT:
selected->setTop( y + cy );
case MOVE_RIGHT: // fall through
selected->setRight( x + cx );
break;
case MOVE_BOTTOM_LEFT:
selected->setBottom( y + cy );
case MOVE_LEFT: // fall through
selected->setLeft( x + cx );
break;
case MOVE_BOTTOM_RIGHT:
selected->setRight( x + cx );
case MOVE_BOTTOM: // fall through
selected->setBottom( y + cy );
break;
case MOVE_WHOLE:
if( selected )
{
// lx is the Last x-Koord from the run before (global)
mx = x-lx; my = y-ly;
/* Check if rectangle would run out of the image on right and bottom */
if( selected->x()+ selected->width()+mx >= ix-cx )
{
mx = ix -cx - selected->width() - selected->x();
kdDebug(29000) << "runs out !" << endl;
}
if( selected->y()+ selected->height()+my >= iy-cy )
{
my = iy -cy - selected->height() - selected->y();
kdDebug(29000) << "runs out !" << endl;
}
/* Check if rectangle would run out of the image on left and top */
if( selected->x() +mx < 0 )
mx = -selected->x();
if( selected->y()+ +my < 0 )
my = -selected->y();
x = mx+lx; y = my+ly;
selected->moveBy( mx, my );
}
}
drawAreaBorder(&p);
lx = x;
ly = y;
}
}
void ImageCanvas::setScaleFactor( int i )
{
kdDebug(29000) << "Setting Scalefactor to " << i << endl;
scale_factor = i;
if( i == 0 ){
kdDebug(29000) << "Setting Dynamic Scaling!" << endl;
setScaleKind(DYNAMIC);
}
update_scaled_pixmap();
}
void ImageCanvas::resizeEvent( TQResizeEvent * event )
{
TQScrollView::resizeEvent( event );
update_scaled_pixmap();
}
void ImageCanvas::update_scaled_pixmap( void )
{
resizeContents( 0,0 );
updateScrollBars();
if( !pmScaled || !image)
{ // debug( "Pixmap px is null in Update_scaled" );
return;
}
TQApplication::setOverrideCursor(waitCursor);
kdDebug(28000) << "Updating scaled_pixmap" << endl;
if( scaleKind() == DYNAMIC )
kdDebug(28000) << "Scaling DYNAMIC" << endl;
TQSize noSBSize( visibleWidth(), visibleHeight());
const int sbWidth = kapp->tqstyle().tqpixelMetric( TQStyle::PM_ScrollBarExtent );
// if( verticalScrollBar()->visible() ) noSBSize.width()+=sbWidth;
// if( horizontalScrollBar()->visible() ) noSBSize.height()+=sbWidth;
switch( scaleKind() )
{
case DYNAMIC:
// do scaling to window-size
used_yscaler = ((double)viewport()-> height()) / ((double)image->height());
used_xscaler = ((double)viewport()-> width()) / ((double)image->width());
scale_factor = 0;
break;
case FIT_ORIG:
used_yscaler = used_xscaler = 1.0;
scale_factor = 100;
break;
case FIT_WIDTH:
used_xscaler = used_yscaler = double(noSBSize.width()) / double(image->width());
if( used_xscaler * image->height() >= noSBSize.height() )
{
/* substract for scrollbar */
used_xscaler = used_yscaler = double(noSBSize.width() - sbWidth) /
double(image->width());
kdDebug(29000) << "FIT WIDTH scrollbar to substract: " << sbWidth << endl;
}
scale_factor = 100*used_xscaler;
break;
case FIT_HEIGHT:
used_yscaler = used_xscaler = double(noSBSize.height())/double(image->height());
// scale = int(100.0 * noSBSize.height() / image->height());
if( used_xscaler * image->width() >= noSBSize.width() )
{
/* substract for scrollbar */
used_xscaler = used_yscaler = double(noSBSize.height() - sbWidth) /
double(image->height());
kdDebug(29000) << "FIT HEIGHT scrollbar to substract: " << sbWidth << endl;
// scale = int(100.0*(noSBSize.height() -sbWidth) / image->height());
}
scale_factor = 100*used_xscaler;
break;
case ZOOM:
used_xscaler = used_yscaler = double(getScaleFactor())/100.0;
scale_factor = 100*used_xscaler;
break;
default:
break;
}
// reconvert the selection to orig size
if( selected ) {
*selected = inv_scale_matrix.map( (const TQRect) *selected );
}
scale_matrix.reset(); // transformation matrix
inv_scale_matrix.reset();
if( scaleKind() == DYNAMIC && maintain_aspect ) {
// printf( "Skaler: x: %f, y: %f\n", x_scaler, y_scaler );
used_xscaler = used_yscaler < used_xscaler ?
used_yscaler : used_xscaler;
used_yscaler = used_xscaler;
}
scale_matrix.scale( used_xscaler, used_yscaler ); // define scale factors
inv_scale_matrix = scale_matrix.invert(); // for redraw of selection
if( selected ) {
*selected = scale_matrix.map( (const TQRect )*selected );
}
#ifdef USE_KPIXMAPIO
*pmScaled = pixIO.convertToPixmap(*image);
#else
pmScaled->convertFromImage( *image );
#endif
*pmScaled = pmScaled->xForm( scale_matrix ); // create scaled pixmap
/* Resizing to 0,0 never may be dropped, otherwise there are problems
* with redrawing of new images.
*/
resizeContents( static_cast<int>(image->width() * used_xscaler),
static_cast<int>(image->height() * used_yscaler ) );
TQApplication::restoreOverrideCursor();
}
void ImageCanvas::drawHAreaBorder(TQPainter &p,int x1,int x2,int y,int r)
{
if( ! acquired || !image ) return;
if(moving!=MOVE_NONE) cr2 = 0;
int inc = 1;
int cx = contentsX(), cy = contentsY();
if(x2 < x1) inc = -1;
if(!r) {
if(cr2 & 4) p.setPen(black);
else p.setPen(white);
} else if(!acquired) p.setPen(TQPen(TQColor(150,150,150)));
for(;;) {
if(TQT_TQRECT_OBJECT(rect()).tqcontains(TQPoint(x1,y))) {
if( r && acquired ) {
int re_x1, re_y;
inv_scale_matrix.map( x1+cx, y+cy, &re_x1, &re_y );
re_x1 = MIN( image->width()-1, re_x1 );
re_y = MIN( image->height()-1, re_y );
p.setPen( TQPen( TQColor( image->pixel(re_x1, re_y))));
}
p.drawPoint(x1,y);
}
if(!r) {
cr2++;
cr2 &= 7;
if(!(cr2&3)) {
if(cr2&4) p.setPen(black);
else p.setPen(white);
}
}
if(x1==x2) break;
x1 += inc;
}
}
void ImageCanvas::drawVAreaBorder(TQPainter &p, int x, int y1, int y2, int r )
{
if( ! acquired || !image ) return;
if( moving!=MOVE_NONE ) cr2 = 0;
int inc = 1;
if( y2 < y1 ) inc = -1;
int cx = contentsX(), cy = contentsY();
if( !r ) {
if( cr2 & 4 ) p.setPen(black);
else
p.setPen(white);
} else
if( !acquired ) p.setPen( TQPen( TQColor(150,150,150) ) );
for(;;) {
if(TQT_TQRECT_OBJECT(rect()).tqcontains( TQPoint(x,y1) )) {
if( r && acquired ) {
int re_y1, re_x;
inv_scale_matrix.map( x+cx, y1+cy, &re_x, &re_y1 );
re_x = MIN( image->width()-1, re_x );
re_y1 = MIN( image->height()-1, re_y1 );
p.setPen( TQPen( TQColor( image->pixel( re_x, re_y1) )));
}
p.drawPoint(x,y1);
}
if(!r) {
cr2++;
cr2 &= 7;
if(!(cr2&3)) {
if(cr2&4) p.setPen(black);
else p.setPen(white);
}
}
if(y1==y2) break;
y1 += inc;
}
}
void ImageCanvas::drawAreaBorder(TQPainter *p,int r )
{
if(selected->isNull()) return;
cr2 = cr1;
int xinc = 1;
if( selected->right() < selected->left()) xinc = -1;
int yinc = 1;
if( selected->bottom() < selected->top()) yinc = -1;
if( selected->width() )
drawHAreaBorder(*p,
selected->left() - contentsX(),
selected->right()- contentsX(),
selected->top() - contentsY(), r );
if( selected->height() ) {
drawVAreaBorder(*p,
selected->right() - contentsX(),
selected->top()- contentsY()+yinc,
selected->bottom()- contentsY(),r);
if(selected->width()) {
drawHAreaBorder(*p,
selected->right()-xinc- contentsX(),
selected->left()- contentsX(),
selected->bottom()- contentsY(),r);
drawVAreaBorder(*p,
selected->left()- contentsX(),
selected->bottom()-yinc- contentsY(),
selected->top()- contentsY()+yinc,r);
}
}
}
// x and y come as real pixmap-coords, not contents-coords
preview_state ImageCanvas::classifyPoint(int x,int y)
{
if(selected->isEmpty()) return MOVE_NONE;
TQRect a = selected->normalize();
int top = 0,left = 0,right = 0,bottom = 0;
int lx = a.left()-x, rx = x-a.right();
int ty = a.top()-y, by = y-a.bottom();
if( a.width() > delta*2+2 )
lx = abs(lx), rx = abs(rx);
if(a.height()>delta*2+2)
ty = abs(ty), by = abs(by);
if( lx>=0 && lx<=delta ) left++;
if( rx>=0 && rx<=delta ) right++;
if( ty>=0 && ty<=delta ) top++;
if( by>=0 && by<=delta ) bottom++;
if( y>=a.top() &&y<=a.bottom() ) {
if(left) {
if(top) return MOVE_TOP_LEFT;
if(bottom) return MOVE_BOTTOM_LEFT;
return MOVE_LEFT;
}
if(right) {
if(top) return MOVE_TOP_RIGHT;
if(bottom) return MOVE_BOTTOM_RIGHT;
return MOVE_RIGHT;
}
}
if(x>=a.left()&&x<=a.right()) {
if(top) return MOVE_TOP;
if(bottom) return MOVE_BOTTOM;
if(selected->tqcontains(TQPoint(x,y))) return MOVE_WHOLE;
}
return MOVE_NONE;
}
int ImageCanvas::getBrightness() const
{
return brightness;
}
int ImageCanvas::getContrast() const
{
return contrast;
}
int ImageCanvas::getGamma() const
{
return gamma;
}
int ImageCanvas::getScaleFactor() const
{
return( scale_factor );
}
const TQImage *ImageCanvas::rootImage( )
{
return( image );
}
void ImageCanvas::setReadOnly( bool ro )
{
d->readOnly = ro;
emit( imageReadOnly(ro) );
}
bool ImageCanvas::readOnly()
{
return d->readOnly;
}
void ImageCanvas::setBrightness(int b)
{
brightness = b;
}
void ImageCanvas::setContrast(int c)
{
contrast = c;
}
void ImageCanvas::setGamma(int c)
{
gamma = c;
}
void ImageCanvas::setKeepZoom( bool k )
{
d->keepZoom = k;
}
ImageCanvas::ScaleKinds ImageCanvas::scaleKind()
{
if( d->scaleKind == UNSPEC )
return defaultScaleKind();
else
return d->scaleKind;
}
ImageCanvas::ScaleKinds ImageCanvas::defaultScaleKind()
{
return d->defaultScaleKind;
}
void ImageCanvas::setScaleKind( ScaleKinds k )
{
if( k == d->scaleKind ) return; // no change, return
d->scaleKind = k;
emit scalingChanged(scaleKindString());
}
void ImageCanvas::setDefaultScaleKind( ScaleKinds k )
{
d->defaultScaleKind = k;
}
const TQString ImageCanvas::imageInfoString( int w, int h, int d )
{
if( w == 0 && h == 0 && d == 0 )
{
if( image )
{
w = image->width();
h = image->height();
d = image->depth();
}
else
return TQString("-");
}
return i18n("%1x%2 pixel, %3 bit").tqarg(w).tqarg(h).tqarg(d);
}
const TQString ImageCanvas::scaleKindString()
{
switch( scaleKind() )
{
case DYNAMIC:
return i18n("Fit window best");
break;
case FIT_ORIG:
return i18n("Original size");
break;
case FIT_WIDTH:
return i18n("Fit Width");
break;
case FIT_HEIGHT:
return i18n("Fit Height");
break;
case ZOOM:
return i18n("Zoom to %1 %%").tqarg( TQString::number(getScaleFactor()));
break;
default:
return i18n("Unknown scaling!");
break;
}
}
int ImageCanvas::highlight( const TQRect& rect, const TQPen& pen, const TQBrush&, bool ensureVis )
{
TQRect saveRect;
saveRect.setRect( rect.x()-2, rect.y()-2, rect.width()+4, rect.height()+4 );
d->highlightRects.append( saveRect );
int idx = d->highlightRects.tqfindIndex(saveRect);
TQRect targetRect = scale_matrix.map( rect );
TQPainter p( pmScaled );
p.setPen(pen);
p.drawLine( targetRect.x(), targetRect.y()+targetRect.height(),
targetRect.x()+targetRect.width(), targetRect.y()+targetRect.height() );
p.flush();
updateContents(targetRect.x()-1, targetRect.y()-1,
targetRect.width()+2, targetRect.height()+2 );
if( ensureVis )
{
TQPoint p = targetRect.center();
ensureVisible( p.x(), p.y(), 10+targetRect.width()/2, 10+targetRect.height()/2 );
}
return idx;
}
void ImageCanvas::removeHighlight( int idx )
{
if( (unsigned) idx >= d->highlightRects.count() )
{
kdDebug(28000) << "removeHighlight: Not a valid index" << endl;
return;
}
/* take the rectangle from the stored highlight rects and map it to the viewer scaling */
TQRect r = d->highlightRects[idx];
d->highlightRects.remove(r);
TQRect targetRect = scale_matrix.map( r );
/* create a small pixmap with a copy of the region in question of the original image */
TQPixmap origPix;
origPix.convertFromImage( image->copy(r) );
/* and scale it */
TQPixmap scaledPix = origPix.xForm( scale_matrix );
/* and finally draw it */
TQPainter p( pmScaled );
p.drawPixmap( targetRect, scaledPix );
p.flush();
/* update the viewers contents */
updateContents(targetRect.x()-1, targetRect.y()-1,
targetRect.width()+2, targetRect.height()+2 );
}
#include "img_canvas.moc"