Logo Search packages:      
Sourcecode: kdewebdev version File versions

kimearea.cpp

/***************************************************************************
                          kimearea.cpp  -  description
                             -------------------
    begin                : Thu Jun 14 2001
    copyright            : (C) 2001 by Jan Schäfer
    email                : janschaefer@users.sourceforge.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <qbitmap.h>
#include <qpointarray.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <qimage.h>
#include <qpen.h>
#include <qbrush.h>
#include <qpalette.h>
#include <qcolor.h>
#include <qlistview.h>

#include <kdebug.h>

#include "kimearea.h"
#include "kimecommon.h"


#define SELSIZE 7


bool Area::highlightArea;
bool Area::showAlt;


Area::Area()
{
      _coords=new QPointArray();
      _selectionPoints= new SelectionPointList();
      _selectionPoints->setAutoDelete(true);
      _finished=false;
      _isSelected=false;
      _name=i18n("noname");
      _listViewItem=0L;
      currentHighlighted=-1;
      _type=Area::None;
      _highlightedPixmap=0L;
      
}

Area* Area::clone() const
{
      Area* areaClone = new Area();
      areaClone->setArea( *this );
      return areaClone;
}

QPointArray* Area::coords() const {
      return _coords;
}

QString Area::getHTMLAttributes() const
{
      QString retStr="";
      
      for (AttributeIterator it = firstAttribute();it!=lastAttribute();++it)
      {
    retStr+=it.key()+"=\""+it.data()+"\" ";     
      }
      
  return retStr;
}


Area::~Area() {
  delete _coords;
  delete _selectionPoints;
  delete _highlightedPixmap;

}

bool Area::contains(const QPoint &) const {
  return false;
}

QString Area::getHTMLCode() const {
  return "";
}

QString Area::attribute(const QString & name) const
{
  return _attributes[name.lower()];
}

void Area::setAttribute(const QString & name, const QString & value)
{
  _attributes.replace(name.lower(),value);
  if (value.isEmpty())
     _attributes.remove(name.lower());
}

AttributeIterator Area::firstAttribute() const
{
  return _attributes.begin();
}

AttributeIterator Area::lastAttribute() const
{
  return _attributes.end();
}


bool Area::setCoords(const QString &) {
  return true;
}

void Area::moveSelectionPoint(QRect*, const QPoint &)
{}


      // Default implementation; is specified by subclasses
QString Area::coordsToString() const
{
  return "";
}


Area::ShapeType Area::type() const {
      return _type;
}

void Area::setArea(const Area & copy)
{
      delete _coords;
      delete _selectionPoints;
      _coords=new QPointArray(copy.coords()->copy());
      _selectionPoints= new SelectionPointList();
      currentHighlighted=-1;
      
      // Need a deep copy of the list
      for (QRect *r=copy.selectionPoints()->first();r!=0L;r=copy.selectionPoints()->next())
                  _selectionPoints->append(new QRect( r->topLeft(),r->bottomRight() ) );
                  
      _finished=copy.finished();
      _isSelected=copy.isSelected();
  _rect = copy.rect();
      
      for (AttributeIterator it = copy.firstAttribute();it!=copy.lastAttribute();++it)
      {
    setAttribute(it.key(),it.data());     
      }
      
      setMoving(copy.isMoving());

//    _listViewItem=0L;
      
}

void Area::setListViewItem(QListViewItem* item) {
      _listViewItem=item;
}

void Area::deleteListViewItem()
{
      delete _listViewItem;
      _listViewItem = 0L;
}


void Area::setRect(const QRect & r)
{
  _rect=r;
      updateSelectionPoints();
}

QRect Area::rect() const {
      return _rect;
}

void Area::setMoving(bool b) {
  _isMoving=b;
}


void Area::moveBy(int dx, int dy) {
      _rect.moveBy(dx,dy);
      for (uint i=0;i<_coords->size();i++) {
            int newX=_coords->point(i).x()+dx;
            int newY=_coords->point(i).y()+dy;
            _coords->setPoint(i,newX,newY);
      }
      
      for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {
            r->moveBy(dx,dy);
      }
}


void Area::moveTo(int x, int y) {
      int dx=x-rect().left();
      int dy=y-rect().top();
      moveBy(dx,dy);
}

uint Area::countSelectionPoints() const
{
  return (uint) selectionPoints()->count();
}

int Area::addCoord(const QPoint & p)
{
      _coords->resize(_coords->size()+1);
      _coords->setPoint(_coords->size()-1,p);
      
      QRect *r= new QRect(0,0,SELSIZE,SELSIZE);
      r->moveCenter(p);
      _selectionPoints->append(r);
      setRect(_coords->boundingRect());

  return _coords->size()-1;
}

void Area::insertCoord(int pos, const QPoint & p)
{

/*
  kdDebug() << p.x() << "," << p.y() << endl;

  if ( _coords->size()>0 )
  {
    for (int i=0; i<_coords->size(); i++)
    {
      if (p==_coords->point(i))
      {
        kdDebug() << "same Point already exists" << endl;
        return;
      }

    }
  }
*/
      _coords->resize(_coords->size()+1);
      

      for (int i=_coords->size()-1;i>pos;i--) {
            _coords->setPoint(i,_coords->point(i-1));
      }
      _coords->setPoint(pos, p);
      
      QRect *r= new QRect(0,0,SELSIZE,SELSIZE);
      r->moveCenter(p);
      _selectionPoints->insert(pos,r);
      setRect(_coords->boundingRect());
}

void Area::removeCoord(int pos) {

      int count=_coords->size();    

      if (count<4)
      {
         kdDebug() << "Danger : trying to remove coordinate from Area with less then 4 coordinates !" << endl;
         return;
      }
      
      for (int i=pos;i<(count-1);i++)
            _coords->setPoint(i, _coords->point(i+1));
      
      _coords->resize(count-1);
      _selectionPoints->remove(pos);
      setRect(_coords->boundingRect());
}

bool Area::removeSelectionPoint(QRect * r)
{
  if (_selectionPoints->contains(r))
  {
    removeCoord(_selectionPoints->find(r));
    return true;
  }

  return false;
}


void Area::moveCoord(int pos, const QPoint & p) {
      _coords->setPoint(pos,p);
      _selectionPoints->at(pos)->moveCenter(p);
      setRect(_coords->boundingRect());
}

void Area::setSelected(bool b)
{
      _isSelected=b;
      if (_listViewItem) {
            _listViewItem->setSelected(b);
      }
}

void Area::highlightSelectionPoint(int number){
      currentHighlighted=number;
}

QRect Area::selectionRect() const {
      QRect r = rect();
      r.moveBy(-SELSIZE*2,-SELSIZE*2);
      r.setSize(r.size()+QSize(SELSIZE*4,SELSIZE*4));
      
      return r;
}

void Area::drawHighlighting(QPainter & p)
{
      if (Area::highlightArea && !isMoving() && _highlightedPixmap)
      {
      p.setRasterOp(Qt::CopyROP);
      
      QPoint point = QPoint(rect().x(),rect().y());
    if (point.x()<0)
        point.setX(0);
     if (point.y()<0)
        point.setY(0);
      
        p.drawPixmap( point, *_highlightedPixmap);
      
      }
}

void Area::drawAlt(QPainter & p)
{
  double x,y;

  double scalex = p.worldMatrix().m11();
//  double scaley = p.worldMatrix().m12();

  QWMatrix oldMatrix = p.worldMatrix();

  p.setWorldMatrix(QWMatrix(1,oldMatrix.m12(), oldMatrix.m21(), 1, oldMatrix.dx(), oldMatrix.dy() ));

  x = (rect().x()+rect().width()/2)*scalex;
  y = (rect().y()+rect().height()/2)*scalex;

  QFontMetrics metrics = p.fontMetrics();

  int w = metrics.width(attribute("alt"));
  x -= w/2;
  y += metrics.height()/4;



  if (highlightArea)
  {
    p.setRasterOp(Qt::CopyROP);
    p.setPen(Qt::black);
  }
  else
  {
    p.setRasterOp(Qt::XorROP);
      p.setPen(QPen(QColor("white"),1));
      }

  p.drawText(myround(x),myround(y),attribute("alt"));

  p.setWorldMatrix(oldMatrix);
}

void Area::draw(QPainter & p)
{

  // Only draw the selection points at base class
  // the rest is done in the derived classes
      if (_isSelected)
  {
            int i=0;

    double scalex = p.worldMatrix().m11();
//    double scaley = p.worldMatrix().m12();

    QWMatrix oldMatrix = p.worldMatrix();

    p.setWorldMatrix(QWMatrix(1,oldMatrix.m12(), oldMatrix.m21(), 1, oldMatrix.dx(), oldMatrix.dy() ));

            for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {

      // Draw a green circle around the selected point ( only when editing a polygon )
                  if (i==currentHighlighted) {
                        QRect r2(0,0,15,15);
                        r2.moveCenter(r->center()*scalex);
                        p.setRasterOp(Qt::CopyROP);
                        p.setPen(QPen(QColor("lightgreen"),2));
                        p.drawEllipse(r2);
                        p.setRasterOp(Qt::XorROP);
                        p.setPen(QPen(QColor("white"),1));
                  }

                  // Draw the selection point
                  p.setRasterOp(Qt::XorROP);

                  QRect r3(*r);
      int d = 1;
      if (scalex > 2) d=0;

      r3.moveCenter( QPoint((int)(r3.center().x()*scalex),(int)(r3.center().y()*scalex)) );

                  p.fillRect(r3,QBrush("white"));
/*
                  QRect r3(*r);
      r3.moveTopLeft( QPoint(r3.left()*scalex+2*(scalex-1), r3.top()*scalex+2*(scalex-1)) );

                  r3.setSize(r3.size()+QSize(2,2));
//+               r3.moveBy(-1,-1); 
                  p.setRasterOp(Qt::CopyROP);
                  p.setPen(QPen(QColor("lightgreen"),1));
                  p.setBrush(QColor("lightgreen"));
                  p.drawPie(r3,0,5760);
                  p.setPen(QPen(QColor("black"),1));
                  r3.setSize(r3.size()+QSize(2,2));
                  r3.moveBy(-1,-1);             
                  p.drawEllipse(r3);
*/                
            i++;
            }
    p.setWorldMatrix(oldMatrix);


      }

  if (showAlt)
  {
     drawAlt(p);
   }
  p.setRasterOp(Qt::XorROP);
      
}

QRect* Area::onSelectionPoint(const QPoint & p, double zoom) const
{
      for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next())
  {
    QRect r2(r->topLeft(),r->bottomRight());

    r2.moveCenter(r2.center()*zoom);

    if (r2.contains(p))
    {

                  return r;
    }
      }
      
      return 0L;
}




/**
 * returns only the part of the image which is
 * covered by the area
 */
QPixmap Area::cutOut(const QImage & image)
{
      if ( 0>=rect().width()  ||
                   0>=rect().height() ||
       !rect().intersects(image.rect())   )
      {     
            QPixmap dummyPix(10,10);
            dummyPix.fill();  
    delete _highlightedPixmap;
    _highlightedPixmap = 0L;
            return dummyPix;
      }

      // Get the mask from the subclasses
      QBitmap mask=getMask();
                  
      // The rectangle which is part of the image
      QRect partOfImage=rect();
      QRect partOfMask(0,0,mask.width(),mask.height());
      
      
      // If the area is outside of the image make the
      // preview smaller
      if ( (rect().x()+rect().width()) > image.width() ) {
            partOfImage.setWidth( image.width()-rect().x() );
            partOfMask.setWidth(  image.width()-rect().x() );
      }
            
      if ( (rect().x() < 0) ) {
            partOfImage.setX(0);
            partOfMask.setX(myabs(rect().x()));
      }
      
      if ( (rect().y()+rect().height()) > image.height() ) {
            partOfImage.setHeight( image.height()-rect().y() );
            partOfMask.setHeight ( image.height()-rect().y() );
      }
      
      if ( (rect().y() < 0) ) {
            partOfImage.setY(0);
            partOfMask.setY(myabs(rect().y()));
      }
            
  QImage tempImage=mask.convertToImage().copy(partOfMask);
      mask.convertFromImage(tempImage);

//  partOfImage = partOfImage.normalize();
      QImage cut=image.copy(partOfImage);
      
      QPixmap pix;
      
//  partOfMask = partOfMask.normalize();  
      if (!partOfMask.isValid())
         kdDebug() << "PartofMask not valid : " << partOfMask.x() << "," << partOfMask.y() << ","
                  << partOfMask.width() << "," << partOfMask.height() << "," << endl;

/*                      
      QBitmap mask2(partOfMask.width(), partOfMask.height());
      QPainter p4(&mask2);
      p4.drawPixmap( QPoint(0,0) ,mask,partOfMask);
      p4.flush();
      p4.end();
*/
      
      pix.convertFromImage(cut);

      setHighlightedPixmap(cut, mask);
            
      QPixmap retPix(pix.width(),pix.height());
  QPainter p3(&retPix);
      
      // if transparent image fill the background
      // with gimp-like rectangles
      if (pix.mask()) {
      QPixmap backPix(32,32);
      
      // Gimp like transparent rectangle
      QPainter p2(&backPix);
      p2.fillRect(0,0,32,32,QColor(156,149,156));
      p2.fillRect(0,16,16,16,QColor(98,105,98));
      p2.fillRect(16,0,16,16,QColor(98,105,98));
      p2.flush();
      
      p3.setPen(QPen());
      p3.fillRect(0,0,pix.width(),pix.height(),QBrush(QColor("black"),backPix));
      }
      
      
      p3.drawPixmap(QPoint(0,0),pix);
      p3.flush();
      p3.end();
      retPix.setMask(mask);

      return retPix;
}

QBitmap Area::getMask() const
{
      QBitmap b;
      return b;
}

void Area::setHighlightedPixmap( QImage & im, QBitmap & mask )
{
  if (!Area::highlightArea)
     return;

  delete _highlightedPixmap;

  QImage image = im.convertDepth( 32 );
  QSize size = image.size();
  QColor pixel;
  double r,g,b;


  // highlight every pixel
  for (int y=0; y < size.height(); y++)
  {
    for (int x=0; x < size.width(); x++)
    {
      r = qRed(image.pixel(x,y));
      g = qGreen(image.pixel(x,y));
      b = qBlue(image.pixel(x,y));
      r = (r *123 / 255)+132;
      g = (g *123 / 255)+132;
      b = (b *123 / 255)+132;

      pixel.setRgb( (int) r, (int) g, (int) b);
      image.setPixel(x,y, pixel.rgb());
    }
  }

  _highlightedPixmap = new QPixmap();
  _highlightedPixmap->convertFromImage( image );
  _highlightedPixmap->setMask( mask );

  if (_highlightedPixmap->isNull())
     kdDebug() << "HighlightedPixmap is null" << endl;

}

/********************************************************************
 * RECTANGLE
 *******************************************************************/


RectArea::RectArea()
      : Area()
{
      QRect *p = new QRect(0,0,SELSIZE,SELSIZE);
      _selectionPoints->append(p);
      p = new QRect(0,0,SELSIZE,SELSIZE);
      _selectionPoints->append(p);
      p = new QRect(0,0,SELSIZE,SELSIZE);
      _selectionPoints->append(p);
      p = new QRect(0,0,SELSIZE,SELSIZE);
      _selectionPoints->append(p);
      _type=Area::Rectangle;
      
}

RectArea::~RectArea() {
}

Area* RectArea::clone() const
{
      Area* areaClone = new RectArea();
      areaClone->setArea( *this );
      return areaClone;
}

void RectArea::draw(QPainter & p)
{

  drawHighlighting(p);
//  p.setRasterOp(Qt::CopyROP);
//  p.setRasterOp(Qt:: OrROP);
//  QBrush b(QBrush::SolidPattern);
//  QBrush b(QBrush::Dense4Pattern);
//  QBrush b(QBrush::BDiagPattern);
//    b.setColor(QColor(32,32,32));
//    p.fillRect(rect(), b);
      
      p.setRasterOp(Qt::XorROP);
      p.setPen(QPen(QColor("white"),1));
  QRect r(rect());
  r.setWidth(r.width()+1);
  r.setHeight(r.height()+1);
      p.drawRect(r);
      
      Area::draw(p);
}

QBitmap RectArea::getMask() const
{
      QBitmap mask(rect().width(),rect().height());
      
      mask.fill(Qt::color0);
      QPainter p(&mask);
      p.setBackgroundColor(Qt::color0);
      p.setPen(Qt::color1);
      p.setBrush(Qt::color1);
      mask.fill(Qt::color1);
      p.end();
      
      return mask;
}

QString RectArea::coordsToString() const
{
      QString retStr=QString("%1,%2,%3,%4")
                              .arg(rect().left())
                              .arg(rect().top())
                              .arg(rect().right())
                              .arg(rect().bottom());

      return retStr;                            
}

bool RectArea::contains(const QPoint & p) const{
      return rect().contains(p);
}

void RectArea::moveSelectionPoint(QRect* selectionPoint, const QPoint & p)
{
      selectionPoint->moveCenter(p);
      int i=0;
      for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {
            if (r==selectionPoint)
                  break;
            i++;
      }
      QRect r2(_rect);
      switch (i) {
            case 0 : _rect.setLeft(p.x());
                                     _rect.setTop(p.y());
                  break;
            case 1 : _rect.setRight(p.x());
                                     _rect.setTop(p.y());
                  break;
            case 2 : _rect.setLeft(p.x());
                                     _rect.setBottom(p.y());
                  break;
            case 3 : _rect.setRight(p.x());
                                     _rect.setBottom(p.y());
                  break;
      }                 
      if ( ! _rect.isValid())
            _rect=r2;
                        
      updateSelectionPoints();
}

void RectArea::updateSelectionPoints()
{
      _selectionPoints->first()->moveCenter(_rect.topLeft());
      _selectionPoints->next()->moveCenter(_rect.topRight()+QPoint(1,0));
      _selectionPoints->next()->moveCenter(_rect.bottomLeft()+QPoint(0,1));
      _selectionPoints->next()->moveCenter(_rect.bottomRight()+QPoint(1,1));
}

bool RectArea::setCoords(const QString & s)
{
      _finished=true;
      
      QStringList list=QStringList::split(",",s);
      QRect r;
      bool ok=true;
      QStringList::Iterator it = list.begin();
      r.setLeft((*it).toInt(&ok,10));it++;
      r.setTop((*it).toInt(&ok,10));it++;
      r.setRight((*it).toInt(&ok,10));it++;
      r.setBottom((*it).toInt(&ok,10));
      if (ok) {
            setRect(r);
            return true;
      } else
            return false;
}

QString RectArea::getHTMLCode() const {
      QString retStr;
      retStr+="<area ";
      retStr+="shape=\"rect\" ";
      
      retStr+=getHTMLAttributes();
      
      retStr+="coords=\""+coordsToString()+"\" ";
      retStr+="/>";
      return retStr;

}
      
/********************************************************************
 * CIRCLE
 *******************************************************************/


CircleArea::CircleArea()
      : Area()
{
      _type=Area::Circle;
      QRect *p = new QRect(0,0,SELSIZE,SELSIZE);
      _selectionPoints->append(p);
      p = new QRect(0,0,SELSIZE,SELSIZE);
      _selectionPoints->append(p);
      p = new QRect(0,0,SELSIZE,SELSIZE);
      _selectionPoints->append(p);
      p = new QRect(0,0,SELSIZE,SELSIZE);
      _selectionPoints->append(p);
}

CircleArea::~CircleArea() {
}

Area* CircleArea::clone() const
{
      Area* areaClone = new CircleArea();
      areaClone->setArea( *this );
      return areaClone;
}

void CircleArea::draw(QPainter & p)
{
  drawHighlighting(p);

/*
  p.setRasterOp(Qt::CopyROP);
      QBrush bold = p.brush();
      QBrush b(QBrush::Dense5Pattern);
      b.setColor(QColor("green"));
      p.setBrush(b);
      QRect r = _rect;
      r.moveBy(1,1);
      r.setSize( r.size()-QSize(2,2) );
      p.drawChord(r,0,5760);
      p.setBrush(bold);
*/    
  p.setRasterOp(Qt::XorROP);
  p.setPen(QPen(QColor("white"),1));

  QRect r(_rect);
  r.setWidth(r.width()+1);
  r.setHeight(r.height()+1);
      p.drawEllipse(r);
      
      Area::draw(p);
}

QBitmap CircleArea::getMask() const
{
      QBitmap mask(_rect.width(),_rect.height());
      
      mask.fill(Qt::color0);
      QPainter p(&mask);
      p.setBackgroundColor(Qt::color0);
      p.setPen(Qt::color1);
      p.setBrush(Qt::color1);
      p.drawPie(QRect(0,0,_rect.width(),_rect.height()),0,5760);
      p.flush();
      p.end();
      
      
      return mask;

}

QString CircleArea::coordsToString() const
{
      QString retStr=QString("%1,%2,%3")
                              .arg(_rect.center().x())
                              .arg(_rect.center().y())
                              .arg(_rect.width()/2);
      
      return retStr;
}

bool CircleArea::contains(const QPoint & p) const
{
      QRegion r(_rect,QRegion::Ellipse);
      return r.contains(p);
}

void CircleArea::moveSelectionPoint(QRect* selectionPoint, const QPoint & p)
{
      selectionPoint->moveCenter(p);

      int i=0;
      for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {
            if (r==selectionPoint)
                  break;
            i++;
      }
                  
      // The code below really sucks, but I have no better idea.
      // it only makes sure that the circle is perfektly round
      QPoint newPoint;
      int diff=myabs(p.x()-_rect.center().x());
   if (myabs(p.y()-_rect.center().y())>diff)
             diff=myabs(p.y()-_rect.center().y());
                                                
      newPoint.setX( p.x()-_rect.center().x()<0
                                                ? _rect.center().x()-diff
                                                :     _rect.center().x()+diff);
                  
      newPoint.setY( p.y()-_rect.center().y()<0
                                                ? _rect.center().y()-diff
                                                :     _rect.center().y()+diff);
                  
      switch (i) {
            case 0 : if (newPoint.x() < _rect.center().x() &&
                                                 newPoint.y() < _rect.center().y())
                                     {
                                           _rect.setLeft(newPoint.x());
                                           _rect.setTop(newPoint.y());
                                     }
                  break;
            case 1 : if (newPoint.x() > _rect.center().x() &&
                                                 newPoint.y() < _rect.center().y())
                                     {
                                           _rect.setRight(newPoint.x());
                                       _rect.setTop(newPoint.y());
                                     }
                  break;
            case 2 : if (newPoint.x() < _rect.center().x() &&
                                                 newPoint.y() > _rect.center().y())
                                     {
                                           _rect.setLeft(newPoint.x());
                                           _rect.setBottom(newPoint.y());
                                     }
                  break;
            case 3 : if (newPoint.x() > _rect.center().x() &&
                                                 newPoint.y() > _rect.center().y())
                                     {
                                           _rect.setRight(newPoint.x());
                                           _rect.setBottom(newPoint.y());
                                     }
                  break;
      }                 
                  
            
      
      updateSelectionPoints();

}

void CircleArea::setRect(const QRect & r)
{
      QRect r2 = r;
      if ( r2.height() != r2.width() )
         r2.setHeight( r2.width() );
      
      Area::setRect(r2);
}


void CircleArea::updateSelectionPoints()
{
      _selectionPoints->first()->moveCenter(_rect.topLeft());
      _selectionPoints->next()->moveCenter(_rect.topRight());
      _selectionPoints->next()->moveCenter(_rect.bottomLeft());
      _selectionPoints->next()->moveCenter(_rect.bottomRight());
}

bool CircleArea::setCoords(const QString & s)
{
      _finished=true;
      QStringList list=QStringList::split(",",s);
      bool ok=true;
      QStringList::Iterator it = list.begin();
      int x=(*it).toInt(&ok,10);it++;
      int y=(*it).toInt(&ok,10);it++;
      int rad=(*it).toInt(&ok,10);
      if (!ok) return false;
      QRect r;
      r.setWidth(rad*2);
      r.setHeight(rad*2);
      r.moveCenter(QPoint(x,y));
      setRect(r);
      return true;
}

QString CircleArea::getHTMLCode() const {
      QString retStr;
      retStr+="<area ";
      retStr+="shape=\"circle\" ";
      
      retStr+=getHTMLAttributes();
      
      retStr+="coords=\""+coordsToString()+"\" ";
      retStr+="/>";
      return retStr;

}


/********************************************************************
 * POLYGON
 *******************************************************************/


PolyArea::PolyArea()
      : Area()
{
      _type=Area::Polygon;
}

PolyArea::~PolyArea() {
}

Area* PolyArea::clone() const
{
      Area* areaClone = new PolyArea();
      areaClone->setArea( *this );
      return areaClone;
}

void PolyArea::draw(QPainter & p)
{
  drawHighlighting(p);
      
      p.setRasterOp(Qt::XorROP);
      p.setPen(QPen(QColor("white"),1));
      if (_coords->count()==0) return;



      if (_finished)
    p.drawPolygon ( *_coords,false,0,_coords->count());
  else
    p.drawPolyline ( *_coords,0,_coords->count());

/*
      p.moveTo(_coords->point(0));
      for (int i=1;i<_coords->count();i++)
            p.lineTo(_coords->point(i));
                                                      
      if (_finished)
            p.lineTo(_coords->point(0));
*/          
      Area::draw(p);
}

QBitmap PolyArea::getMask() const
{
      QBitmap mask(_rect.width(),_rect.height());
      
      mask.fill(Qt::color0);
      QPainter p(&mask);
      p.setBackgroundColor(Qt::color0);
      p.setPen(Qt::color1);
      p.setBrush(Qt::color1);
      p.setClipping(true);
      QRegion r(*_coords);
      r.translate(-_rect.left(),-_rect.top());
      p.setClipRegion(r);
      p.fillRect(QRect(0,0,_rect.width(),_rect.height()),Qt::color1);
      p.flush();
      p.end();
      
      return mask;
}

QString PolyArea::coordsToString() const
{
      QString retStr;                     
      
      for (uint i=0;i<_coords->count();i++) {
            retStr.append(QString("%1,%2,")
                  .arg(_coords->point(i).x())
                  .arg(_coords->point(i).y()));
      }
      
      retStr.remove(retStr.length()-1,1);

      return retStr;
}

int PolyArea::distance(const QPoint &p1, const QPoint &p2)
{
  QPoint temp = p1-p2;
  return temp.manhattanLength();
}

bool PolyArea::isBetween(const QPoint &p, const QPoint &p1, const QPoint &p2)
{
  int dist = distance(p,p1)+distance(p,p2)-distance(p1,p2);

  if (myabs(dist)<1)
     return true;
  else
     return false;
}

void PolyArea::simplifyCoords()
{
  if (_coords->size()<4)
     return;

  QPoint p = _coords->point(0) - _coords->point(1);

  uint i = 1;


  while( (i<_coords->size()) && (_coords->size() > 3) )
  {
    p = _coords->point(i-1) - _coords->point(i);

    if (p.manhattanLength() < 3)
      removeCoord(i);
    else
      i++;
  }

  p = _coords->point(0) - _coords->point(1);

  double angle2;
  double angle1;

  if (p.y()==0)
     angle1 = 1000000000;
  else
    angle1 = (double) p.x() / (double) p.y();

  i=2;

  while( (i<_coords->size()) && (_coords->size() > 3) )
  {
    p = _coords->point(i-1) - _coords->point(i);

    if (p.y()==0)
        angle2 = 1000000000;
    else
      angle2 = (double) p.x() / (double) p.y();

    if ( angle2==angle1 )
    {
      kdDebug() << "removing " << i-1 << endl;
      removeCoord(i-1);
    }
    else
    {
      i++;
      kdDebug() << "skipping " << i-1 << " cause " << angle1 << "!= " << angle2 << endl;
      angle1 = angle2;

    }

  }



}


int PolyArea::addCoord(const QPoint & p)
{
  if (_coords->size()<3)
  {
     return Area::addCoord(p);
  }

  if (_coords->point(_coords->size()-1) == p)
  {
     kdDebug() << "equal Point added" << endl;
     return -1;

  }

  int n=_coords->size();

//  QPoint temp = p-_coords->point(0);
  int nearest = 0;
  int olddist = distance(p,_coords->point(0));
  int mindiff = 999999999;

  // find the two points, which are the nearest one to the new point
  for (int i=1; i <= n; i++)
  {
    int dist = distance(p,_coords->point(i%n));
    int dist2 = distance(_coords->point(i-1),_coords->point(i%n));
    int diff = myabs(dist+olddist-dist2);
    if ( diff<mindiff )
    {
      mindiff = diff;
      nearest = i%n;
    }
    olddist=dist;
  }

  insertCoord(nearest, p);

  return nearest;

}           

bool PolyArea::contains(const QPoint & p) const
{
      // A line can't contain a point
      if (_coords->count() >2 ) {
            QRegion r(*_coords);
            return r.contains(p);
      }
      else
            return false;
}

void PolyArea::moveSelectionPoint(QRect* selectionPoint, const QPoint & p)
{
      selectionPoint->moveCenter(p);

      int i=0;
      for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {
            if (r==selectionPoint)
                  break;
            i++;
      }
      _coords->setPoint(i,p);
      _rect=_coords->boundingRect();
}

void PolyArea::updateSelectionPoints()
{
      QRect *r;
      r=_selectionPoints->first();
      
      for (uint i=0;i<_coords->size();i++)      
      {
            r->moveCenter(_coords->point(i));                     
            r=_selectionPoints->next();
      }

}

bool PolyArea::setCoords(const QString & s)
{
      _finished=true;
      QStringList list=QStringList::split(",",s);
      _coords=new QPointArray();
      _selectionPoints= new SelectionPointList();
      
      for (QStringList::Iterator it = list.begin(); it !=list.end(); it++)
      {
            bool ok=true;
            int newXCoord=(*it).toInt(&ok,10);
            if (!ok) return false;
            it++;
            if (it==list.end())     break;
            int newYCoord=(*it).toInt(&ok,10);
            if (!ok) return false;
            insertCoord(_coords->size(), QPoint(newXCoord,newYCoord));
      }
      
      return true;

}

QString PolyArea::getHTMLCode() const {
      QString retStr;
      retStr+="<area ";
      retStr+="shape=\"poly\" ";

      retStr+=getHTMLAttributes();
            
      retStr+="coords=\""+coordsToString()+"\" ";
      retStr+="/>";
      return retStr;

}

void PolyArea::setFinished(bool b)
{
      // The last Point is the same as the first
      // so delete it
      _coords->resize(_coords->size()-1);
      _selectionPoints->removeLast();
      _finished=b;
}

QRect PolyArea::selectionRect() const
{
      QRect r = _rect;
      
      r.moveBy(-10,-10);
      r.setSize(r.size()+QSize(21,21));
      
      return r;
}



/********************************************************************
 * DEFAULT
 *******************************************************************/


DefaultArea::DefaultArea()
      : Area()
{
      _type=Area::Default;
}

DefaultArea::~DefaultArea() {
}

Area* DefaultArea::clone() const
{
      Area* areaClone = new DefaultArea();
      areaClone->setArea( *this );
      return areaClone;
}

void DefaultArea::draw(QPainter &)
{}


QString DefaultArea::getHTMLCode() const {
      QString retStr;
      retStr+="<area ";
      retStr+="shape=\"default\" ";

      retStr+=getHTMLAttributes();
            
      retStr+="/>";
      return retStr;

}


/********************************************************************
 * AreaSelection
 *******************************************************************/

AreaSelection::AreaSelection()
      : Area()
{
      _areas = new AreaList();
      _name = "Selection";
      invalidate();
}

AreaSelection::~AreaSelection() {
      delete _areas;
}

01312 Area* AreaSelection::clone() const
{
      AreaSelection* areaClone = new AreaSelection();
      
      // we want a deep copy of the Areas
  AreaListIterator it=getAreaListIterator();

  for ( ; it.current() != 0L; ++it )
  {
            areaClone->add( it.current()->clone() );
      }
      
//    areaClone->setArea( *this );
      
      return areaClone;
}


01330 void AreaSelection::add(Area *a)
{

      // if a selection of areas was added get the areas of it
      AreaSelection *selection=0L;
      if ( (selection = dynamic_cast <AreaSelection*> ( a ) ) )
      {
            AreaList list = selection->getAreaList();
            
            for (Area* area = list.first(); area != 0L; area = list.next() )
            {
                  if ( _areas->find( area ) == -1 ) {
                        _areas->append( area );  // Must come before area->setSelected
                        area->setSelected( true );
                  }
            }
      }
      else
      {
            if ( _areas->find( a ) == -1 ) {
            _areas->append( a );  // Must come before a->setSelected
            a->setSelected( true );
      }
  }

      invalidate();
}

void AreaSelection::remove(Area *a)
{
      if (_areas->find(a) == -1)
            return;
            
      a->setSelected( false );      
      _areas->remove( a );
      invalidate();
}

void AreaSelection::reset()
{
  AreaListIterator it=getAreaListIterator();

  for ( ; it.current() != 0L; ++it )
  {
      it.current()->setSelected( false );
  }
      
      _areas->clear();
      invalidate();
}

01381 bool AreaSelection::contains(const QPoint & p) const
{
      bool b=false;
  AreaListIterator it=getAreaListIterator();

  for ( ; it.current() != 0L; ++it )
  {
      if ( it.current()->contains( p ) )
      {
            b=true;
            break;
      }
  }

  return b;
}

QRect* AreaSelection::onSelectionPoint(const QPoint & p, double zoom) const
{
  AreaListIterator it=getAreaListIterator();
      
      if (it.count() != 1)
            return 0L;

      QRect* retRect=0L;            
            
  for ( ; it.current() != 0L; ++it )
  {
      if ( (retRect = it.current()->onSelectionPoint( p , zoom) ) )
            {           
            break;
      }
  }

  return retRect;
}

01418 void AreaSelection::moveSelectionPoint(QRect* selectionPoint, const QPoint & p)
{
      // It's only possible to move a SelectionPoint if only one Area is selected
      if (_areas->count() != 1)
            return;
            
      _areas->getFirst()->moveSelectionPoint(selectionPoint,p);         

      invalidate();
}


01430 void AreaSelection::moveBy(int dx, int dy)
{
  AreaListIterator it=getAreaListIterator();

  for ( ; it.current() != 0L; ++it )
      it.current()->moveBy(dx,dy);

      Area::moveBy( dx, dy );       

      invalidate();
}

QString AreaSelection::typeString() const
{
      // if there is only one Area selected
      // show the name of that Area
      if ( _areas->count()==0 )
            return "";
      else if ( _areas->count()==1 )
            return _areas->getFirst()->typeString();
      else
            return i18n("Number of Areas");
      
}

Area::ShapeType AreaSelection::type() const
{
      // if there is only one Area selected
      // take the type of that Area
      if ( _areas->count()==0 )
            return Area::None;
      else if ( _areas->count()==1 )
            return _areas->getFirst()->type();
      else
            return Area::Selection;
}

void AreaSelection::updateSelectionPoints()
{

  AreaListIterator it=getAreaListIterator();
      
  for ( ; it.current() != 0L; ++it )
  {
            it.current()->updateSelectionPoints();
  }

      invalidate();

}



QRect AreaSelection::selectionRect() const
{
      if (!_selectionCacheValid)
      {
            _selectionCacheValid=true;
      QRect r;
    AreaListIterator it=getAreaListIterator();

    for ( ; it.current() != 0L; ++it )
      r = r | it.current()->selectionRect();

      _cachedSelectionRect=r;
  }

  return _cachedSelectionRect;
}

uint AreaSelection::count() const {
      return _areas->count();
}

bool AreaSelection::isEmpty() const
{
      return _areas->isEmpty();
}


AreaList AreaSelection::getAreaList() const {
      AreaList list(*_areas);
      return list;
}

AreaListIterator AreaSelection::getAreaListIterator() const {
      AreaListIterator it(*_areas);
      return it;
}

01520 void AreaSelection::setArea(const Area & copy)
{
      Area *area = copy.clone();
      AreaSelection *selection = dynamic_cast<AreaSelection*>(area);
      if (selection)
            setAreaSelection(*selection);
      else {      
    Area::setArea(copy);
      invalidate();
  }
}

void AreaSelection::setAreaSelection(const AreaSelection & copy)
{
  AreaListIterator it=getAreaListIterator();
      AreaListIterator it2=copy.getAreaListIterator();
            
      if (it.count() != it2.count())
            return;

  for ( ; it.current() != 0L; ++it, ++it2 )
      it.current()->setArea(*it2.current());

  Area::setArea(copy);
      invalidate();
}

void AreaSelection::setAreaList( const AreaList & areas )
{
      delete _areas;
      _areas = new AreaList(areas);
      invalidate();
}

01554 void AreaSelection::setRect(const QRect & r)
{
      if ( _areas->count()==1 )
      {
            _areas->getFirst()->setRect(r);
      }

      invalidate();
      _rect=rect();
      updateSelectionPoints();
}

QRect AreaSelection::rect() const
{
      if (!_rectCacheValid)
      {
            _rectCacheValid=true;
      QRect r;
    AreaListIterator it=getAreaListIterator();

    for ( ; it.current() != 0L; ++it )
      r = r | it.current()->rect();

    _cachedRect=r;
  }

  return _cachedRect;
}


int AreaSelection::addCoord(const QPoint & p)
{
      if ( _areas->count()==1 )
      {
            return _areas->getFirst()->addCoord(p);
            invalidate();
      }

  return 0; 
}

void AreaSelection::insertCoord(int pos, const QPoint & p)
{
      if ( _areas->count()==1 )
      {
            _areas->getFirst()->insertCoord(pos, p);
            invalidate();
      }     
}

void AreaSelection::removeCoord(int pos)
{
      if ( _areas->count()==1 )
      {
            _areas->getFirst()->removeCoord(pos);
            invalidate();
      }     
}

bool AreaSelection::removeSelectionPoint(QRect * r)
{
  bool result=false;

      if ( _areas->count()==1 )
      {
            result = _areas->getFirst()->removeSelectionPoint(r);
            invalidate();
      }     
      
      return result;
}

SelectionPointList* AreaSelection::selectionPoints() const
{
      if ( _areas->count()==1 )
      {
            return _areas->getFirst()->selectionPoints();
      }     
      
      return _selectionPoints;
}


void AreaSelection::moveCoord(int pos,const QPoint & p)
{
      if ( _areas->count()==1 )
      {
            _areas->getFirst()->moveCoord(pos,p);
            invalidate();
      }     
}

void AreaSelection::highlightSelectionPoint(int i)
{
      if ( _areas->count()==1 )
      {
            _areas->getFirst()->highlightSelectionPoint(i);
            invalidate();
      }     
}


QPointArray* AreaSelection::coords() const
{
      if ( _areas->count()==1 )
      {
            return _areas->getFirst()->coords();
      }     
      
      return Area::coords();
}

QString AreaSelection::attribute(const QString & name) const
{
      if ( _areas->count()==1 )
      {
            return _areas->getFirst()->attribute(name);
      }     
      
      return Area::attribute(name);
}

void AreaSelection::setAttribute(const QString & name, const QString & value)
{
  AreaListIterator it=getAreaListIterator();

  for ( ; it.current() != 0L; ++it )
      it.current()->setAttribute(name,value);
      
      Area::setAttribute(name,value);
}

AttributeIterator AreaSelection::firstAttribute() const
{
      if ( _areas->count()==1 )
      {
            return _areas->getFirst()->firstAttribute();
      }     

  return _attributes.begin();
}

AttributeIterator AreaSelection::lastAttribute() const
{
      if ( _areas->count()==1 )
      {
            return _areas->getFirst()->lastAttribute();
      }     

  return _attributes.end();
}

void AreaSelection::setMoving(bool b)
{
  AreaListIterator it=getAreaListIterator();

  for ( ; it.current() != 0L; ++it )
      it.current()->setMoving(b);
      
      Area::setMoving(b);
}

bool AreaSelection::isMoving() const
{
      if ( _areas->count()==1 )
      {
            return _areas->getFirst()->isMoving();
      }     
      
      return Area::isMoving();
}


/**
 * Checks if an area is outside the rectangle parameter
 * returns false if an area has no pixel in common with the rectangle parameter
 **/
01731 bool AreaSelection::allAreasWithin(const QRect & r) const
{
  if ( ! r.contains(rect()) )
  {
    AreaListIterator it=getAreaListIterator();

    for ( ; it.current() != 0L; ++it )
      if (!it.current()->rect().intersects(r))
          return false;
  }

  return true;
}


void AreaSelection::draw(QPainter &)
{}



Generated by  Doxygen 1.6.0   Back to index