00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef _OKULAR_AREA_H_
00011 #define _OKULAR_AREA_H_
00012
00013 #include <QtCore/QList>
00014 #include <QtGui/QColor>
00015 #include <QtGui/QPainterPath>
00016 #include <kdebug.h>
00017
00018 #include <okular/core/global.h>
00019 #include <okular/core/okular_export.h>
00020
00021 class QPolygonF;
00022 class QRect;
00023
00024 namespace Okular {
00025
00026 class Annotation;
00027 class Action;
00028 class NormalizedShape;
00029
00045 class OKULAR_EXPORT NormalizedPoint
00046 {
00047 public:
00051 NormalizedPoint();
00052
00056 NormalizedPoint( double x, double y );
00057
00062 NormalizedPoint( int x, int y, int xScale, int yScale );
00063
00067 NormalizedPoint& operator=( const NormalizedPoint& );
00068
00072 void transform( const QMatrix &matrix );
00073
00077 double x;
00078
00082 double y;
00083 };
00084
00089 class OKULAR_EXPORT NormalizedRect
00090 {
00091 public:
00096 NormalizedRect();
00097
00110 NormalizedRect( double left, double top, double right, double bottom );
00111
00116 NormalizedRect( const QRect &rectangle, double xScale, double yScale );
00117
00121 NormalizedRect( const NormalizedRect& );
00122
00126 NormalizedRect& operator=( const NormalizedRect &other );
00127
00131 static NormalizedRect fromQRectF( const QRectF &rect );
00132
00136 bool isNull() const;
00137
00142 bool contains( double x, double y ) const;
00143
00148 bool intersects( const NormalizedRect &other ) const;
00149
00154 bool intersects( const NormalizedRect *other ) const;
00155
00160 bool intersects( double left, double top, double right, double bottom ) const;
00161
00166 QRect geometry( int xScale, int yScale ) const;
00167
00172 NormalizedRect operator|( const NormalizedRect &other ) const;
00173
00178 NormalizedRect& operator|=( const NormalizedRect &other );
00179
00184 bool operator==( const NormalizedRect &other ) const;
00185
00189 void transform( const QMatrix &matrix );
00190
00194 double left;
00195
00199 double top;
00200
00204 double right;
00205
00209 double bottom;
00210 };
00211 KDE_DUMMY_QHASH_FUNCTION(NormalizedRect)
00212
00213
00226 class OKULAR_EXPORT ObjectRect
00227 {
00228 public:
00232 enum ObjectType
00233 {
00234 Action,
00235 Image,
00236 OAnnotation,
00237 SourceRef
00238 };
00239
00251 ObjectRect( double left, double top, double right, double bottom, bool ellipse, ObjectType type, void *object );
00252
00256 ObjectRect( const NormalizedRect &rect, bool ellipse, ObjectType type, void *object );
00257
00261 ObjectRect( const QPolygonF &poly, ObjectType type, void *object );
00262
00266 virtual ~ObjectRect();
00267
00272 ObjectType objectType() const;
00273
00277 const void *object() const;
00278
00282 const QPainterPath ®ion() const;
00283
00288 virtual QRect boundingRect( double xScale, double yScale ) const;
00289
00294 virtual bool contains( double x, double y, double xScale, double yScale ) const;
00295
00299 virtual void transform( const QMatrix &matrix );
00300
00301 protected:
00302 ObjectType m_objectType;
00303 void * m_object;
00304 QPainterPath m_path;
00305 QPainterPath m_transformedPath;
00306 };
00307
00311 class OKULAR_EXPORT AnnotationObjectRect : public ObjectRect
00312 {
00313 public:
00318 AnnotationObjectRect( Annotation *annotation );
00319
00323 virtual ~AnnotationObjectRect();
00324
00328 Annotation *annotation() const;
00329
00334 virtual QRect boundingRect( double xScale, double yScale ) const;
00335
00340 virtual bool contains( double x, double y, double xScale, double yScale ) const;
00341
00345 virtual void transform( const QMatrix &matrix );
00346
00347 private:
00348 Annotation * m_annotation;
00349 };
00350
00354 class OKULAR_EXPORT SourceRefObjectRect : public ObjectRect
00355 {
00356 public:
00363 SourceRefObjectRect( const NormalizedPoint& point, void *reference );
00364
00369 virtual QRect boundingRect( double xScale, double yScale ) const;
00370
00375 virtual bool contains( double x, double y, double xScale, double yScale ) const;
00376
00377 private:
00378 NormalizedPoint m_point;
00379 };
00380
00382
00383 template <typename T>
00384 void doDelete( T& t )
00385 {
00386 (void)t;
00387 }
00388
00390 template <typename T>
00391 T* givePtr( T& t )
00392 {
00393 return &t;
00394 }
00395
00397 template <typename T>
00398 T& deref( T& t )
00399 {
00400 return t;
00401 }
00402
00404 template <typename T>
00405 static void doDelete( T* t )
00406 {
00407 delete t;
00408 }
00409
00411 template <typename T>
00412 static T* givePtr( T* t )
00413 {
00414 return t;
00415 }
00416
00418 template <typename T>
00419 static T& deref( T* t )
00420 {
00421 return *t;
00422 }
00424
00435 template <class NormalizedShape, class Shape> class RegularArea : public QList<NormalizedShape>
00436 {
00437 public:
00441 ~RegularArea();
00442
00447 bool contains( double x, double y ) const;
00448
00453 bool contains( const NormalizedShape& shape ) const;
00454
00458 bool intersects( const RegularArea<NormalizedShape,Shape> *area ) const;
00459
00463 bool intersects( const NormalizedShape& shape ) const;
00464
00468 void appendArea( const RegularArea<NormalizedShape,Shape> *area );
00469
00473 void appendShape( const NormalizedShape& shape, MergeSide side = MergeAll );
00474
00478 void simplify();
00479
00483 bool isNull() const;
00484
00489 QList<Shape> geometry( int xScale, int yScale, int dx = 0, int dy = 0 ) const;
00490
00494 void transform( const QMatrix &matrix );
00495 };
00496
00497 template <class NormalizedShape, class Shape>
00498 RegularArea<NormalizedShape, Shape>::~RegularArea()
00499 {
00500 int size = this->count();
00501 for ( int i = 0; i < size; ++i )
00502 doDelete( (*this)[i] );
00503 }
00504
00505 template <class NormalizedShape, class Shape>
00506 void RegularArea<NormalizedShape, Shape>::simplify()
00507 {
00508 #ifdef DEBUG_REGULARAREA
00509 int prev_end = this->count();
00510 #endif
00511 int end = this->count() - 1, x = 0;
00512 for ( int i = 0; i < end; ++i )
00513 {
00514 if ( givePtr( (*this)[x] )->intersects( deref( (*this)[i+1] ) ) )
00515 {
00516 deref((*this)[x]) |= deref((*this)[i+1]);
00517 NormalizedShape& tobedeleted = (*this)[i+1];
00518 this->removeAt( i + 1 );
00519 doDelete( tobedeleted );
00520 --end;
00521 --i;
00522 }
00523 else
00524 {
00525 x=i+1;
00526 }
00527 }
00528 #ifdef DEBUG_REGULARAREA
00529 kDebug() << "from" << prev_end << "to" << this->count();
00530 #endif
00531 }
00532
00533 template <class NormalizedShape, class Shape>
00534 bool RegularArea<NormalizedShape, Shape>::isNull() const
00535 {
00536 if ( !this )
00537 return false;
00538
00539 if ( this->isEmpty() )
00540 return false;
00541
00542 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
00543 for ( ; it != itEnd; ++it )
00544 if ( !givePtr( *it )->isNull() )
00545 return false;
00546
00547 return true;
00548 }
00549
00550 template <class NormalizedShape, class Shape>
00551 bool RegularArea<NormalizedShape, Shape>::intersects( const NormalizedShape& rect ) const
00552 {
00553 if ( !this )
00554 return false;
00555
00556 if ( this->isEmpty() )
00557 return false;
00558
00559 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
00560 for ( ; it != itEnd; ++it )
00561 if ( !givePtr( *it )->isNull() && givePtr( *it )->intersects( rect ) )
00562 return true;
00563
00564 return false;
00565 }
00566
00567 template <class NormalizedShape, class Shape>
00568 bool RegularArea<NormalizedShape, Shape>::intersects( const RegularArea<NormalizedShape,Shape> *area ) const
00569 {
00570 if ( !this )
00571 return false;
00572
00573 if ( this->isEmpty() )
00574 return false;
00575
00576 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
00577 for ( ; it != itEnd; ++it )
00578 {
00579 typename QList<NormalizedShape>::const_iterator areaIt = area->begin(), areaItEnd = area->end();
00580 for ( ; areaIt != areaItEnd; ++areaIt )
00581 {
00582 if ( !( *it ).isNull() && ( *it ).intersects( *areaIt ) )
00583 return true;
00584 }
00585 }
00586
00587 return false;
00588 }
00589
00590 template <class NormalizedShape, class Shape>
00591 void RegularArea<NormalizedShape, Shape>::appendArea( const RegularArea<NormalizedShape, Shape> *area )
00592 {
00593 if ( !this )
00594 return;
00595
00596 typename QList<NormalizedShape>::const_iterator areaIt = area->begin(), areaItEnd = area->end();
00597 for ( ; areaIt != areaItEnd; ++areaIt )
00598 this->append( *areaIt );
00599 }
00600
00601
00602 template <class NormalizedShape, class Shape>
00603 void RegularArea<NormalizedShape, Shape>::appendShape( const NormalizedShape& shape, MergeSide side )
00604 {
00605 if ( !this )
00606 return;
00607
00608 int size = this->count();
00609
00610 if ( size == 0 )
00611 {
00612 this->append( shape );
00613 }
00614 else
00615 {
00616 bool intersection = false;
00617 NormalizedShape& last = (*this)[size - 1];
00618 #define O_LAST givePtr( last )
00619 # define O_LAST_R O_LAST->right
00620 # define O_LAST_L O_LAST->left
00621 # define O_LAST_T O_LAST->top
00622 # define O_LAST_B O_LAST->bottom
00623 #define O_NEW givePtr( shape )
00624 # define O_NEW_R O_NEW->right
00625 # define O_NEW_L O_NEW->left
00626 # define O_NEW_T O_NEW->top
00627 # define O_NEW_B O_NEW->bottom
00628 switch ( side )
00629 {
00630 case MergeRight:
00631 intersection = ( O_LAST_R >= O_NEW_L ) && ( O_LAST_L <= O_NEW_R )
00632 && ( ( O_LAST_T <= O_NEW_T && O_LAST_B >= O_NEW_B )
00633 || ( O_LAST_T >= O_NEW_T && O_LAST_B <= O_NEW_B ) );
00634 break;
00635 case MergeBottom:
00636 intersection = ( O_LAST_B >= O_NEW_T ) && ( O_LAST_T <= O_NEW_B )
00637 && ( ( O_LAST_R <= O_NEW_R && O_LAST_L >= O_NEW_L )
00638 || ( O_LAST_R >= O_NEW_R && O_LAST_L <= O_NEW_L ) );
00639 break;
00640 case MergeLeft:
00641 intersection = ( O_LAST_L <= O_NEW_R ) && ( O_LAST_R >= O_NEW_L )
00642 && ( ( O_LAST_T <= O_NEW_T && O_LAST_B >= O_NEW_B )
00643 || ( O_LAST_T >= O_NEW_T && O_LAST_B <= O_NEW_B ) );
00644 break;
00645 case MergeTop:
00646 intersection = ( O_LAST_T <= O_NEW_B ) && ( O_LAST_B >= O_NEW_T )
00647 && ( ( O_LAST_R <= O_NEW_R && O_LAST_L >= O_NEW_L )
00648 || ( O_LAST_R >= O_NEW_R && O_LAST_L <= O_NEW_L ) );
00649 break;
00650 case MergeAll:
00651 intersection = O_LAST->intersects( shape );
00652 break;
00653 }
00654 #undef O_LAST
00655 # undef O_LAST_R
00656 # undef O_LAST_L
00657 # undef O_LAST_T
00658 # undef O_LAST_B
00659 #undef O_NEW
00660 # undef O_NEW_R
00661 # undef O_NEW_L
00662 # undef O_NEW_T
00663 # undef O_NEW_B
00664
00665
00666 if ( intersection )
00667 {
00668 deref((*this)[size - 1]) |= deref( shape );
00669 doDelete( const_cast<NormalizedShape&>( shape ) );
00670 }
00671 else
00672 this->append( shape );
00673 }
00674 }
00675
00676
00677 template <class NormalizedShape, class Shape>
00678 bool RegularArea<NormalizedShape, Shape>::contains( double x, double y ) const
00679 {
00680 if ( !this )
00681 return false;
00682
00683 if ( this->isEmpty() )
00684 return false;
00685
00686 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
00687 for ( ; it != itEnd; ++it )
00688 if ( ( *it ).contains( x, y ) )
00689 return true;
00690
00691 return false;
00692 }
00693
00694 template <class NormalizedShape, class Shape>
00695 bool RegularArea<NormalizedShape, Shape>::contains( const NormalizedShape& shape ) const
00696 {
00697 if ( !this )
00698 return false;
00699
00700 if ( this->isEmpty() )
00701 return false;
00702
00703 return QList<NormalizedShape>::contains( shape );
00704 }
00705
00706 template <class NormalizedShape, class Shape>
00707 QList<Shape> RegularArea<NormalizedShape, Shape>::geometry( int xScale, int yScale, int dx, int dy ) const
00708 {
00709 if ( !this || this->isEmpty() )
00710 return QList<Shape>();
00711
00712 QList<Shape> ret;
00713 Shape t;
00714 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
00715 for ( ; it != itEnd; ++it )
00716 {
00717 t = givePtr( *it )->geometry( xScale, yScale );
00718 t.translate( dx, dy );
00719 ret.append( t );
00720 }
00721
00722 return ret;
00723 }
00724
00725 template <class NormalizedShape, class Shape>
00726 void RegularArea<NormalizedShape, Shape>::transform( const QMatrix &matrix )
00727 {
00728 if ( !this )
00729 return;
00730
00731 if ( this->isEmpty() )
00732 return;
00733
00734 for ( int i = 0; i < this->count(); ++i )
00735 givePtr( (*this)[i] )->transform( matrix );
00736 }
00737
00738 class OKULAR_EXPORT RegularAreaRect : public RegularArea< NormalizedRect, QRect >
00739 {
00740 public:
00741 RegularAreaRect();
00742 RegularAreaRect( const RegularAreaRect& rar );
00743 ~RegularAreaRect();
00744
00745 RegularAreaRect& operator=( const RegularAreaRect& rar );
00746
00747 private:
00748 class Private;
00749 Private * const d;
00750 };
00751
00756 class HighlightAreaRect : public RegularAreaRect
00757 {
00758 public:
00763 HighlightAreaRect( const RegularAreaRect *area = 0 );
00764
00768 int s_id;
00769
00773 QColor color;
00774 };
00775
00776 }
00777
00778 #ifndef QT_NO_DEBUG_STREAM
00779
00782 OKULAR_EXPORT QDebug operator<<( QDebug str, const Okular::NormalizedPoint &point );
00783
00787 OKULAR_EXPORT QDebug operator<<( QDebug str, const Okular::NormalizedRect &rect );
00788 #endif
00789
00790 #endif