compile
[kdegraphics.git] / okular / core / area.h
blobd13c3cdf28adf5fae003ba7f101c87162a3e9e5a
1 /***************************************************************************
2 * Copyright (C) 2004-05 by Enrico Ros <eros.kde@email.it> *
3 * Copyright (C) 2005 by Piotr Szymanski <niedakh@gmail.com> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 ***************************************************************************/
10 #ifndef _OKULAR_AREA_H_
11 #define _OKULAR_AREA_H_
13 #include <QtCore/QList>
14 #include <QtGui/QColor>
15 #include <QtGui/QPainterPath>
16 #include <kdebug.h>
18 #include <okular/core/global.h>
19 #include <okular/core/okular_export.h>
21 class QPolygonF;
22 class QRect;
24 namespace Okular {
26 class Annotation;
27 class Action;
28 class NormalizedShape;
30 /**
31 * NormalizedPoint is a helper class which stores the coordinates
32 * of a normalized point. Normalized means that the coordinates are
33 * between 0 and 1 so that it is page size independent.
35 * Example:
36 * The normalized point is (0.5, 0.3)
38 * If you want to draw it on a 800x600 page, just multiply the x coordinate (0.5) with
39 * the page width (800) and the y coordinate (0.3) with the page height (600), so
40 * the point will be drawn on the page at (400, 180).
42 * That allows you to zoom the page by just multiplying the normalized points with the
43 * zoomed page size.
45 class OKULAR_EXPORT NormalizedPoint
47 public:
48 /**
49 * Creates a new empty normalized point.
51 NormalizedPoint();
53 /**
54 * Creates a new normalized point with the normalized coordinates (@p x, @p y ).
56 NormalizedPoint( double x, double y );
58 /**
59 * Creates a new normalized point with the coordinates (@p x, @p y) which are normalized
60 * by the scaling factors @p xScale and @p yScale.
62 NormalizedPoint( int x, int y, int xScale, int yScale );
64 /**
65 * @internal
67 NormalizedPoint& operator=( const NormalizedPoint& );
69 /**
70 * Transforms the normalized point with the operations defined by @p matrix.
72 void transform( const QMatrix &matrix );
74 /**
75 * The normalized x coordinate.
77 double x;
79 /**
80 * The normalized y coordinate.
82 double y;
85 /**
86 * NormalizedRect is a helper class which stores the coordinates
87 * of a normalized rect, which is a rectangle of @see NormalizedPoints.
89 class OKULAR_EXPORT NormalizedRect
91 public:
92 /**
93 * Creates a null normalized rectangle.
94 * @see isNull()
96 NormalizedRect();
98 /**
99 * Creates a normalized rectangle with the normalized coordinates
100 * @p left, @p top, @p right, @p bottom.
102 * If you need the x, y, width and height coordinates use the
103 * following formulas:
105 * @li x = left
106 * @li y = top
107 * @li width = right - left
108 * @li height = bottom - top
110 NormalizedRect( double left, double top, double right, double bottom );
113 * Creates a normalized rectangle of the given @p rectangle which is normalized
114 * by the scaling factors @p xScale and @p yScale.
116 NormalizedRect( const QRect &rectangle, double xScale, double yScale );
119 * @internal
121 NormalizedRect( const NormalizedRect& );
124 * @internal
126 NormalizedRect& operator=( const NormalizedRect &other );
129 * Build a normalized rect from a QRectF.
131 static NormalizedRect fromQRectF( const QRectF &rect );
134 * Returns whether this normalized rectangle is a null normalized rect.
136 bool isNull() const;
139 * Returns whether the normalized rectangle contains the normalized coordinates
140 * @p x and @p y.
142 bool contains( double x, double y ) const;
145 * Returns whether the normalized rectangle intersects the @p other normalized
146 * rectangle.
148 bool intersects( const NormalizedRect &other ) const;
151 * This is an overloaded member function, provided for convenience. It behaves essentially
152 * like the above function.
154 bool intersects( const NormalizedRect *other ) const;
157 * Returns whether the normalized rectangle intersects an other normalized
158 * rectangle, which is defined by @p left, @p top, @p right and @p bottom.
160 bool intersects( double left, double top, double right, double bottom ) const;
163 * Returns the rectangle that accrues when the normalized rectangle is multiplyed
164 * with the scaling @p xScale and @p yScale.
166 QRect geometry( int xScale, int yScale ) const;
169 * Returns the normalized bounding rectangle of the normalized rectangle
170 * combined with the @p other normalized rectangle.
172 NormalizedRect operator|( const NormalizedRect &other ) const;
175 * Sets the normalized rectangle to the normalized bounding rectangle
176 * of itself combined with the @p other normalized rectangle.
178 NormalizedRect& operator|=( const NormalizedRect &other );
181 * Returns the intersection of this normalized rectangle with the specified
182 * @p other. If the rects do not intersect then the result is null.
184 * @since 0.7 (KDE 4.1)
186 NormalizedRect operator&( const NormalizedRect &other ) const;
189 * Returns whether the normalized rectangle is equal to the @p other
190 * normalized rectangle.
192 bool operator==( const NormalizedRect &other ) const;
195 * Transforms the normalized rectangle with the operations defined by @p matrix.
197 void transform( const QMatrix &matrix );
200 * The normalized left coordinate.
202 double left;
205 * The normalized top coordinate.
207 double top;
210 * The normalized right coordinate.
212 double right;
215 * The normalized bottom coordinate.
217 double bottom;
219 KDE_DUMMY_QHASH_FUNCTION(NormalizedRect)
222 * @short NormalizedRect that contains a reference to an object.
224 * These rects contains a pointer to a okular object (such as an action or something
225 * like that). The pointer is read and stored as 'void pointer' so cast is
226 * performed by accessors based on the value returned by objectType(). Objects
227 * are reparented to this class.
229 * Type / Class correspondency tab:
230 * - Action : class Action: description of an action
231 * - Image : class Image : description of an image (n/a)
232 * - Annotation: class Annotation: description of an annotation
234 class OKULAR_EXPORT ObjectRect
236 public:
238 * Describes the type of storable object.
240 enum ObjectType
242 Action, ///< An action
243 Image, ///< An image
244 OAnnotation, ///< An annotation
245 SourceRef ///< A source reference
249 * Creates a new object rectangle.
251 * @param left The left coordinate of the rectangle.
252 * @param top The top coordinate of the rectangle.
253 * @param right The right coordinate of the rectangle.
254 * @param bottom The bottom coordinate of the rectangle.
255 * @param ellipse If true the rectangle describes an ellipse.
256 * @param type The type of the storable object @see ObjectType.
257 * @param object The pointer to the storable object.
259 ObjectRect( double left, double top, double right, double bottom, bool ellipse, ObjectType type, void *object );
262 * This is an overloaded member function, provided for convenience.
264 ObjectRect( const NormalizedRect &rect, bool ellipse, ObjectType type, void *object );
267 * This is an overloaded member function, provided for convenience.
269 ObjectRect( const QPolygonF &poly, ObjectType type, void *object );
272 * Destroys the object rectangle.
274 virtual ~ObjectRect();
277 * Returns the object type of the object rectangle.
278 * @see ObjectType
280 ObjectType objectType() const;
283 * Returns the storable object of the object rectangle.
285 const void *object() const;
288 * Returns the region that is covered by the object rectangle.
290 const QPainterPath &region() const;
293 * Returns the bounding rect of the object rectangle for the
294 * scaling factor @p xScale and @p yScale.
296 virtual QRect boundingRect( double xScale, double yScale ) const;
299 * Returns whether the object rectangle contains the point @p x, @p y for the
300 * scaling factor @p xScale and @p yScale.
302 virtual bool contains( double x, double y, double xScale, double yScale ) const;
305 * Transforms the object rectangle with the operations defined by @p matrix.
307 virtual void transform( const QMatrix &matrix );
309 protected:
310 ObjectType m_objectType;
311 void * m_object;
312 QPainterPath m_path;
313 QPainterPath m_transformedPath;
317 * This class describes the object rectangle for an annotation.
319 class OKULAR_EXPORT AnnotationObjectRect : public ObjectRect
321 public:
323 * Creates a new annotation object rectangle with the
324 * given @p annotation.
326 AnnotationObjectRect( Annotation *annotation );
329 * Destroys the annotation object rectangle.
331 virtual ~AnnotationObjectRect();
334 * Returns the annotation object of the annotation object rectangle.
336 Annotation *annotation() const;
339 * Returns the bounding rect of the annotation object rectangle for the
340 * scaling factor @p xScale and @p yScale.
342 virtual QRect boundingRect( double xScale, double yScale ) const;
345 * Returns whether the annotation object rectangle contains the point @p x, @p y for the
346 * scaling factor @p xScale and @p yScale.
348 virtual bool contains( double x, double y, double xScale, double yScale ) const;
351 * Transforms the annotation object rectangle with the operations defined by @p matrix.
353 virtual void transform( const QMatrix &matrix );
355 private:
356 Annotation * m_annotation;
360 * This class describes the object rectangle for a source reference.
362 class OKULAR_EXPORT SourceRefObjectRect : public ObjectRect
364 public:
366 * Creates a new source reference object rectangle.
368 * @param point The point of the source reference.
369 * @param reference The storable source reference object.
371 SourceRefObjectRect( const NormalizedPoint& point, void *reference );
374 * Returns the bounding rect of the source reference object rectangle for the
375 * scaling factor @p xScale and @p yScale.
377 virtual QRect boundingRect( double xScale, double yScale ) const;
380 * Returns whether the source reference object rectangle contains the point @p x, @p y for the
381 * scaling factor @p xScale and @p yScale.
383 virtual bool contains( double x, double y, double xScale, double yScale ) const;
385 private:
386 NormalizedPoint m_point;
389 /// @cond PRIVATE
390 /** @internal */
391 template <typename T>
392 void doDelete( T& t )
394 (void)t;
397 /** @internal */
398 template <typename T>
399 T* givePtr( T& t )
401 return &t;
404 /** @internal */
405 template <typename T>
406 T& deref( T& t )
408 return t;
411 /** @internal */
412 template <typename T>
413 static void doDelete( T* t )
415 delete t;
418 /** @internal */
419 template <typename T>
420 static T* givePtr( T* t )
422 return t;
425 /** @internal */
426 template <typename T>
427 static T& deref( T* t )
429 return *t;
431 /// @endcond
434 * @short A regular area of NormalizedShape which normalizes a Shape
436 * Class NormalizedShape \b must have the following functions/operators defined:
437 * - bool contains( double, double )
438 * - bool intersects( NormalizedShape )
439 * - bool isNull()
440 * - Shape geometry( int, int )
441 * - operator|=( NormalizedShape ) which unite two NormalizedShape's
443 template <class NormalizedShape, class Shape> class RegularArea : public QList<NormalizedShape>
445 public:
447 * Destroys a regular area.
449 ~RegularArea();
452 * Returns whether the regular area contains the
453 * normalized point @p x, @p y.
455 bool contains( double x, double y ) const;
458 * Returns whether the regular area contains the
459 * given @p shape.
461 bool contains( const NormalizedShape& shape ) const;
464 * Returns whether the regular area intersects with the given @p area.
466 bool intersects( const RegularArea<NormalizedShape,Shape> *area ) const;
469 * Returns whether the regular area intersects with the given @p shape.
471 bool intersects( const NormalizedShape& shape ) const;
474 * Appends the given @p area to the regular area.
476 void appendArea( const RegularArea<NormalizedShape,Shape> *area );
479 * Appends the given @p shape to the regular area.
481 void appendShape( const NormalizedShape& shape, MergeSide side = MergeAll );
484 * Simplifies the regular area by merging its intersecting subareas.
486 void simplify();
489 * Returns whether the regular area is a null area.
491 bool isNull() const;
494 * Returns the subareas of the regular areas as shapes for the given scaling factor
495 * @p xScale and @p yScale, translated by @p dx and @p dy.
497 QList<Shape> geometry( int xScale, int yScale, int dx = 0, int dy = 0 ) const;
500 * Transforms the regular area with the operations defined by @p matrix.
502 void transform( const QMatrix &matrix );
505 template <class NormalizedShape, class Shape>
506 RegularArea<NormalizedShape, Shape>::~RegularArea()
508 int size = this->count();
509 for ( int i = 0; i < size; ++i )
510 doDelete( (*this)[i] );
513 template <class NormalizedShape, class Shape>
514 void RegularArea<NormalizedShape, Shape>::simplify()
516 #ifdef DEBUG_REGULARAREA
517 int prev_end = this->count();
518 #endif
519 int end = this->count() - 1, x = 0;
520 for ( int i = 0; i < end; ++i )
522 if ( givePtr( (*this)[x] )->intersects( deref( (*this)[i+1] ) ) )
524 deref((*this)[x]) |= deref((*this)[i+1]);
525 NormalizedShape& tobedeleted = (*this)[i+1];
526 this->removeAt( i + 1 );
527 doDelete( tobedeleted );
528 --end;
529 --i;
531 else
533 x=i+1;
536 #ifdef DEBUG_REGULARAREA
537 kDebug() << "from" << prev_end << "to" << this->count();
538 #endif
541 template <class NormalizedShape, class Shape>
542 bool RegularArea<NormalizedShape, Shape>::isNull() const
544 if ( !this )
545 return false;
547 if ( this->isEmpty() )
548 return false;
550 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
551 for ( ; it != itEnd; ++it )
552 if ( !givePtr( *it )->isNull() )
553 return false;
555 return true;
558 template <class NormalizedShape, class Shape>
559 bool RegularArea<NormalizedShape, Shape>::intersects( const NormalizedShape& rect ) const
561 if ( !this )
562 return false;
564 if ( this->isEmpty() )
565 return false;
567 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
568 for ( ; it != itEnd; ++it )
569 if ( !givePtr( *it )->isNull() && givePtr( *it )->intersects( rect ) )
570 return true;
572 return false;
575 template <class NormalizedShape, class Shape>
576 bool RegularArea<NormalizedShape, Shape>::intersects( const RegularArea<NormalizedShape,Shape> *area ) const
578 if ( !this )
579 return false;
581 if ( this->isEmpty() )
582 return false;
584 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
585 for ( ; it != itEnd; ++it )
587 typename QList<NormalizedShape>::const_iterator areaIt = area->begin(), areaItEnd = area->end();
588 for ( ; areaIt != areaItEnd; ++areaIt )
590 if ( !( *it ).isNull() && ( *it ).intersects( *areaIt ) )
591 return true;
595 return false;
598 template <class NormalizedShape, class Shape>
599 void RegularArea<NormalizedShape, Shape>::appendArea( const RegularArea<NormalizedShape, Shape> *area )
601 if ( !this )
602 return;
604 typename QList<NormalizedShape>::const_iterator areaIt = area->begin(), areaItEnd = area->end();
605 for ( ; areaIt != areaItEnd; ++areaIt )
606 this->append( *areaIt );
610 template <class NormalizedShape, class Shape>
611 void RegularArea<NormalizedShape, Shape>::appendShape( const NormalizedShape& shape, MergeSide side )
613 if ( !this )
614 return;
616 int size = this->count();
617 // if the list is empty, adds the shape normally
618 if ( size == 0 )
620 this->append( shape );
622 else
624 bool intersection = false;
625 NormalizedShape& last = (*this)[size - 1];
626 #define O_LAST givePtr( last )
627 # define O_LAST_R O_LAST->right
628 # define O_LAST_L O_LAST->left
629 # define O_LAST_T O_LAST->top
630 # define O_LAST_B O_LAST->bottom
631 #define O_NEW givePtr( shape )
632 # define O_NEW_R O_NEW->right
633 # define O_NEW_L O_NEW->left
634 # define O_NEW_T O_NEW->top
635 # define O_NEW_B O_NEW->bottom
636 switch ( side )
638 case MergeRight:
639 intersection = ( O_LAST_R >= O_NEW_L ) && ( O_LAST_L <= O_NEW_R )
640 && ( ( O_LAST_T <= O_NEW_T && O_LAST_B >= O_NEW_B )
641 || ( O_LAST_T >= O_NEW_T && O_LAST_B <= O_NEW_B ) );
642 break;
643 case MergeBottom:
644 intersection = ( O_LAST_B >= O_NEW_T ) && ( O_LAST_T <= O_NEW_B )
645 && ( ( O_LAST_R <= O_NEW_R && O_LAST_L >= O_NEW_L )
646 || ( O_LAST_R >= O_NEW_R && O_LAST_L <= O_NEW_L ) );
647 break;
648 case MergeLeft:
649 intersection = ( O_LAST_L <= O_NEW_R ) && ( O_LAST_R >= O_NEW_L )
650 && ( ( O_LAST_T <= O_NEW_T && O_LAST_B >= O_NEW_B )
651 || ( O_LAST_T >= O_NEW_T && O_LAST_B <= O_NEW_B ) );
652 break;
653 case MergeTop:
654 intersection = ( O_LAST_T <= O_NEW_B ) && ( O_LAST_B >= O_NEW_T )
655 && ( ( O_LAST_R <= O_NEW_R && O_LAST_L >= O_NEW_L )
656 || ( O_LAST_R >= O_NEW_R && O_LAST_L <= O_NEW_L ) );
657 break;
658 case MergeAll:
659 intersection = O_LAST->intersects( shape );
660 break;
662 #undef O_LAST
663 # undef O_LAST_R
664 # undef O_LAST_L
665 # undef O_LAST_T
666 # undef O_LAST_B
667 #undef O_NEW
668 # undef O_NEW_R
669 # undef O_NEW_L
670 # undef O_NEW_T
671 # undef O_NEW_B
672 // if the new shape intersects with the last shape in the list, then
673 // merge it with that and delete the shape
674 if ( intersection )
676 deref((*this)[size - 1]) |= deref( shape );
677 doDelete( const_cast<NormalizedShape&>( shape ) );
679 else
680 this->append( shape );
685 template <class NormalizedShape, class Shape>
686 bool RegularArea<NormalizedShape, Shape>::contains( double x, double y ) const
688 if ( !this )
689 return false;
691 if ( this->isEmpty() )
692 return false;
694 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
695 for ( ; it != itEnd; ++it )
696 if ( ( *it ).contains( x, y ) )
697 return true;
699 return false;
702 template <class NormalizedShape, class Shape>
703 bool RegularArea<NormalizedShape, Shape>::contains( const NormalizedShape& shape ) const
705 if ( !this )
706 return false;
708 if ( this->isEmpty() )
709 return false;
711 return QList<NormalizedShape>::contains( shape );
714 template <class NormalizedShape, class Shape>
715 QList<Shape> RegularArea<NormalizedShape, Shape>::geometry( int xScale, int yScale, int dx, int dy ) const
717 if ( !this || this->isEmpty() )
718 return QList<Shape>();
720 QList<Shape> ret;
721 Shape t;
722 typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
723 for ( ; it != itEnd; ++it )
725 t = givePtr( *it )->geometry( xScale, yScale );
726 t.translate( dx, dy );
727 ret.append( t );
730 return ret;
733 template <class NormalizedShape, class Shape>
734 void RegularArea<NormalizedShape, Shape>::transform( const QMatrix &matrix )
736 if ( !this )
737 return;
739 if ( this->isEmpty() )
740 return;
742 for ( int i = 0; i < this->count(); ++i )
743 givePtr( (*this)[i] )->transform( matrix );
746 class OKULAR_EXPORT RegularAreaRect : public RegularArea< NormalizedRect, QRect >
748 public:
749 RegularAreaRect();
750 RegularAreaRect( const RegularAreaRect& rar );
751 ~RegularAreaRect();
753 RegularAreaRect& operator=( const RegularAreaRect& rar );
755 private:
756 class Private;
757 Private * const d;
761 * This class stores the coordinates of a highlighting area
762 * together with the id of the highlight owner and the color.
764 class HighlightAreaRect : public RegularAreaRect
766 public:
768 * Creates a new highlight area rect with the coordinates of
769 * the given @p area.
771 HighlightAreaRect( const RegularAreaRect *area = 0 );
774 * The search ID of the highlight owner.
776 int s_id;
779 * The color of the highlight.
781 QColor color;
786 #ifndef QT_NO_DEBUG_STREAM
788 * Debug operator for normalized @p point.
790 OKULAR_EXPORT QDebug operator<<( QDebug str, const Okular::NormalizedPoint &point );
793 * Debug operator for normalized @p rect.
795 OKULAR_EXPORT QDebug operator<<( QDebug str, const Okular::NormalizedRect &rect );
796 #endif
798 #endif