Okular

area.h
1 /*
2  SPDX-FileCopyrightText: 2004-05 Enrico Ros <[email protected]>
3  SPDX-FileCopyrightText: 2005 Piotr Szymanski <[email protected]>
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #ifndef _OKULAR_AREA_H_
8 #define _OKULAR_AREA_H_
9 
10 #include <math.h>
11 
12 #include <QColor>
13 #include <QDebug>
14 #include <QList>
15 #include <QPainterPath>
16 #include <QTransform>
17 
18 #include "global.h"
19 #include "okularcore_export.h"
20 
21 class QPolygonF;
22 class QRect;
23 
24 namespace Okular
25 {
26 class Annotation;
27 class Action;
28 class NormalizedShape;
29 
30 /**
31  * NormalizedPoint is a helper class which stores the coordinates
32  * of a normalized point.
33  *
34  * @par Normalized Coordinate System
35  * @parblock
36  * Normalized means that the coordinates are always between 0 and 1,
37  * unless the point shall be outside of the reference area.
38  *
39  * The reference area is a rectangle, and all normalized points
40  * with coordinates of 0 or 1 describe its edges.
41  *
42  * This allows to locate things on a reference area without knowing its
43  * (current or future) actual size. When the reference area is resized,
44  * all things which are described in normalized coordinates keep their
45  * proportional position on the area.
46  * @endparblock
47  *
48  * @par Transformation to and from Normalized Coordinates
49  * @parblock
50  * To transform normalized coordinates to coordinates on the reference area,
51  * just multiply them with the size of the reference area.
52  *
53  * To get normalized coordinates from a point on the reference area,
54  * just divide its coordinates with the size of the reference area.
55  *
56  * Many methods have parameters @c xScale and @c yScale,
57  * these are equal to the size of the reference area.
58  * @endparblock
59  *
60  * @par Normalized Coordinate System Applied to Pages
61  * @parblock
62  * Okular uses a normalized coordinate system mainly to describe
63  * positions on pages.
64  * This is useful because pages can be shown in different sizes (zoom),
65  * but all objects shall keep their proportional position on the page.
66  *
67  * Okular maps from page to normalized coordinates as follows:
68  * * Left edge of the page: x = 0
69  * * Right edge of the page: x = 1
70  * * Top edge of the page: y = 0
71  * * Bottom edge of the page: y = 1
72  * @endparblock
73  *
74  * @par Example: Draw a Point on a Page
75  * @parblock
76  * The point is given in normalized coordinates (0.5, 0.3).
77  *
78  * If you want to draw it on a 800x600 page,
79  * just multiply the x coordinate (0.5) with the page width (800),
80  * and the y coordinate (0.3) with the page height (600).
81  * So, the point will be drawn on the page at (400, 180).
82  *
83  * That allows you to zoom the page by just multiplying the normalized points with the
84  * zoomed page size.
85  * @endparblock
86  *
87  * @par Example: Select Text on a Page using Mouse Events
88  * @parblock
89  * The position of all glyphs and words is stored in normalized coordinates.
90  * (This is what TextPage actually does.)
91  * Mouse press and release events are given in page coordinates (400, 180) and (600, 450),
92  * while the page has a size of 800x600.
93  *
94  * If you want to search all text between the mouse click and release event,
95  * you need their normalized coordinates.
96  * Just divide the x coordinates (400 and 600) by the page width (800),
97  * and the y coordinates (180 and 450) by the page height (600).
98  * So, you have to search for all glyphs between (0.5, 0.3) and (0.75, 0.75).
99  *
100  * That allows you to process all glyphs and words without
101  * having to keep any of their positions in sync with the page.
102  * @endparblock
103  *
104  * @par Geometric operations
105  * @parblock
106  * NormalizedPoint supports basic geometric operations.
107  * * You can transform it with a QTransform matrix.
108  * * With the size of the reference area, you can calculate the squared
109  * absolute distance to another NormalizedPoint or a line of two NormalizedPoints.
110  *
111  * NormalizedRect provides additional geometric operations for rectangles.
112  * @endparblock
113  *
114  * @see NormalizedRect
115  */
116 class OKULARCORE_EXPORT NormalizedPoint
117 {
118 public:
119  /**
120  * Creates a normalized point at (0, 0).
121  */
122  NormalizedPoint();
123 
124  /**
125  * Creates a new normalized point with the normalized coordinates (@p x, @p y ).
126  */
127  NormalizedPoint(double x, double y);
128 
129  /**
130  * Creates a new normalized point from an absolute point (@p x, @p y)
131  * on a reference area of size @p xScale x @p yScale.
132  */
133  NormalizedPoint(int x, int y, int xScale, int yScale);
134 
135  /**
136  * @internal
137  */
138  NormalizedPoint &operator=(const NormalizedPoint &);
139 
141  // TODO next ABI break, move the = default to here
142  ~NormalizedPoint(); // NOLINT(performance-trivially-destructible)
143 
144  /**
145  * Transforms the normalized point with the operations defined by @p matrix.
146  */
147  void transform(const QTransform &matrix);
148 
149  /**
150  * Returns squared distance to normalized point (@p x, @p y)
151  * on a reference area of size @p xScale x @p yScale.
152  * @since 0.17 (KDE 4.11)
153  */
154  double distanceSqr(double x, double y, double xScale, double yScale) const;
155 
156  /**
157  * Returns squared distance of the normalized point (@p x, @p y)
158  * to the line segment from @p start to @p end
159  * on a reference area of size @p xScale x @p yScale.
160  * @since 0.17 (KDE 4.11)
161  */
162  static double distanceSqr(double x, double y, double xScale, double yScale, const NormalizedPoint &start, const NormalizedPoint &end);
163 
164  /**
165  * The normalized x coordinate.
166  */
167  double x;
168 
169  /**
170  * The normalized y coordinate.
171  */
172  double y;
173 };
174 
175 /**
176  * A NormalizedRect is a rectangle which can be defined by two NormalizedPoints.
177  *
178  * It describes a rectangular area on a reference area of undefined size.
179  * For more information about the normalized coordinate system, see NormalizedPoint.
180  *
181  * In Okular, NormalizedRect can be used e. g. to describe bounding boxes of TextEntity objects,
182  * and the highlight area of text selections.
183  *
184  * If you need to describe an area which consists of multiple rectangles,
185  * you can use RegularAreaRect instead.
186  *
187  * @see NormalizedPoint, RegularAreaRect, TextEntity
188  */
189 class OKULARCORE_EXPORT NormalizedRect
190 {
191 public:
192  /**
193  * Creates a null normalized rectangle.
194  * @see isNull()
195  */
196  NormalizedRect();
197 
198  /**
199  * Creates a normalized rectangle with the normalized coordinates
200  * @p left, @p top, @p right, @p bottom.
201  *
202  * If you need the x, y, width and height coordinates use the
203  * following formulas:
204  *
205  * @li x = left
206  * @li y = top
207  * @li width = right - left
208  * @li height = bottom - top
209  *
210  * @note
211  * The coordinates for @p left and @p top should be lower than
212  * @p right and @p bottom, respectively.
213  * At negative width or height the behaviour of some operations is undefined.
214  */
215  NormalizedRect(double left, double top, double right, double bottom);
216 
217  /**
218  * Creates a normalized rectangle from the given @p rectangle
219  * on a reference area of size @p xScale x @p yScale.
220  *
221  * @note
222  * The rectangle should have positive width and height.
223  * You can use e. g. QRect::normalize() to ensure this.
224  * At negative width or height the behaviour of some operations is undefined.
225  */
226  NormalizedRect(const QRect &rectangle, double xScale, double yScale);
227 
228  /**
229  * @internal
230  */
232 
233  /**
234  * @internal
235  */
236  NormalizedRect &operator=(const NormalizedRect &other);
237 
238  // TODO next ABI break, move the = default to here
239  ~NormalizedRect(); // NOLINT(performance-trivially-destructible)
240 
241  /**
242  * Build a normalized rect from a QRectF, which already has normalized coordinates.
243  */
244  static NormalizedRect fromQRectF(const QRectF &rect);
245 
246  /**
247  * Returns whether this normalized rectangle is a null normalized rect.
248  */
249  bool isNull() const;
250 
251  /**
252  * Returns whether the normalized rectangle contains the normalized point
253  * (@p x, @p y).
254  */
255  bool contains(double x, double y) const;
256 
257  /**
258  * Returns whether the normalized rectangle intersects the @p other normalized
259  * rectangle.
260  */
261  bool intersects(const NormalizedRect &other) const;
262 
263  /**
264  * This is an overloaded member function, provided for convenience. It behaves essentially
265  * like the above function.
266  */
267  bool intersects(const NormalizedRect *other) const;
268 
269  /**
270  * Returns whether the normalized rectangle intersects an other normalized
271  * rectangle, which is defined by @p left, @p top, @p right and @p bottom.
272  */
273  bool intersects(double left, double top, double right, double bottom) const;
274 
275  /**
276  * Returns the rectangle mapped to a reference area of @p xScale x @p yScale.
277  */
278  QRect geometry(int xScale, int yScale) const;
279 
280  /**
281  * Same functionality as geometry, but the output is now rounded before typecasting to int
282  *
283  * @since 0.14 (KDE 4.8)
284  */
285  QRect roundedGeometry(int xScale, int yScale) const;
286 
287  /**
288  * Returns the normalized bounding rectangle of the normalized rectangle
289  * combined with the @p other normalized rectangle.
290  */
291  NormalizedRect operator|(const NormalizedRect &other) const;
292 
293  /**
294  * Sets the normalized rectangle to the normalized bounding rectangle
295  * of itself combined with the @p other normalized rectangle.
296  */
297  NormalizedRect &operator|=(const NormalizedRect &other);
298 
299  /**
300  * Returns the intersection of this normalized rectangle with the specified
301  * @p other. If the rects do not intersect then the result is a null rectangle.
302  *
303  * @since 0.7 (KDE 4.1)
304  */
305  NormalizedRect operator&(const NormalizedRect &other) const;
306 
307  /**
308  * Returns whether the normalized rectangle is equal to the @p other
309  * normalized rectangle.
310  */
311  bool operator==(const NormalizedRect &other) const;
312 
313  /**
314  * Returns the center of the rectangle
315  * @since 0.10 (KDE 4.4)
316  */
317  NormalizedPoint center() const;
318 
319  /**
320  * Transforms the normalized rectangle with the operations defined by @p matrix.
321  */
322  void transform(const QTransform &matrix);
323 
324  /**
325  * Returns true if the point @p pt is located below the bottom of the rectangle
326  * @since 0.14 (KDE 4.8)
327  */
328  bool isBottom(const NormalizedPoint &pt) const
329  {
330  return bottom < pt.y;
331  }
332 
333  /**
334  * Returns true if the point @p pt is located above the top of the rectangle
335  * @since 0.14 (KDE 4.8)
336  */
337  bool isTop(const NormalizedPoint &pt) const
338  {
339  return top > pt.y;
340  }
341 
342  /**
343  * Returns true if the point @p pt is located below the top of the rectangle
344  * @since 0.14 (KDE 4.8)
345  */
346  bool isBottomOrLevel(const NormalizedPoint &pt) const
347  {
348  return top < pt.y;
349  }
350 
351  /**
352  * Returns true if the point @p pt is located above the bottom of the rectangle
353  * @since 0.14 (KDE 4.8)
354  */
355  bool isTopOrLevel(const NormalizedPoint &pt) const
356  {
357  return bottom > pt.y;
358  }
359 
360  /**
361  * Returns true if the point @p pt is located to the right of the left edge of the rectangle
362  * @since 0.14 (KDE 4.8)
363  */
364  bool isLeft(const NormalizedPoint &pt) const
365  {
366  return left < pt.x;
367  }
368 
369  /**
370  * Returns true if the point @p pt is located to the left of the right edge of the rectangle
371  * @since 0.14 (KDE 4.8)
372  */
373  bool isRight(const NormalizedPoint &pt) const
374  {
375  return right > pt.x;
376  }
377 
378  /**
379  * Returns the squared distance of the normalized point (@p x, @p y)
380  * to the closest edge, or 0 if the point is within the rectangle;
381  * using a reference area of size @p xScale x @p yScale
382  * @since 0.17 (KDE 4.11)
383  */
384  double distanceSqr(double x, double y, double xScale, double yScale) const
385  {
386  double distX = 0;
387  if (x < left)
388  distX = left - x;
389  else if (x > right)
390  distX = x - right;
391 
392  double distY = 0;
393  if (top > y)
394  distY = top - y;
395  else if (bottom < y)
396  distY = y - bottom;
397  return pow(distX * xScale, 2) + pow(distY * yScale, 2);
398  }
399 
400  /// @since 1.4
401  double width() const
402  {
403  return right - left;
404  }
405 
406  /// @since 1.4
407  double height() const
408  {
409  return bottom - top;
410  }
411 
412  /**
413  * The normalized left coordinate.
414  */
415  double left;
416 
417  /**
418  * The normalized top coordinate.
419  */
420  double top;
421 
422  /**
423  * The normalized right coordinate.
424  */
425  double right;
426 
427  /**
428  * The normalized bottom coordinate.
429  */
430  double bottom;
431 };
432 // KDE_DUMMY_QHASH_FUNCTION(NormalizedRect)
433 
434 /**
435  * @short An area with normalized coordinates that contains a reference to an object.
436  *
437  * These areas ("rects") contain a pointer to a document object
438  * (such as a hyperlink, an action, or something like that).
439  * The pointer is read and stored as 'void pointer' so cast is
440  * performed by accessors based on the value returned by objectType(). Objects
441  * are reparented to this class.
442  *
443  * Type / Class correspondence tab:
444  * - Action : class Action: description of an action
445  * - Image : class Image : description of an image (n/a)
446  * - Annotation: class Annotation: description of an annotation
447  *
448  * For more information about the normalized coordinate system, see NormalizedPoint.
449  *
450  * @see NormalizedPoint
451  */
452 class OKULARCORE_EXPORT ObjectRect
453 {
454 public:
455  /**
456  * Describes the type of storable object.
457  */
458  enum ObjectType {
459  Action, ///< An action
460  Image, ///< An image
461  OAnnotation, ///< An annotation
462  SourceRef ///< A source reference
463  };
464 
465  /**
466  * Creates a new object rectangle.
467  *
468  * @param left The left coordinate of the rectangle.
469  * @param top The top coordinate of the rectangle.
470  * @param right The right coordinate of the rectangle.
471  * @param bottom The bottom coordinate of the rectangle.
472  * @param ellipse If true the rectangle describes an ellipse.
473  * @param type The type of the storable object @see ObjectType.
474  * @param object The pointer to the storable object.
475  */
476  ObjectRect(double left, double top, double right, double bottom, bool ellipse, ObjectType type, void *object);
477 
478  /**
479  * This is an overloaded member function, provided for convenience.
480  */
481  ObjectRect(const NormalizedRect &r, bool ellipse, ObjectType type, void *object);
482 
483  /**
484  * This is an overloaded member function, provided for convenience.
485  */
486  ObjectRect(const QPolygonF &poly, ObjectType type, void *object);
487 
488  /**
489  * Destroys the object rectangle.
490  */
491  virtual ~ObjectRect();
492 
493  ObjectRect(const ObjectRect &o) = delete;
494  ObjectRect &operator=(const ObjectRect &o) = delete;
495 
496  /**
497  * Returns the object type of the object rectangle.
498  * @see ObjectType
499  */
500  ObjectType objectType() const;
501 
502  /**
503  * Returns the storable object of the object rectangle.
504  */
505  const void *object() const;
506 
507  /**
508  * Returns the region that is covered by the object rectangle.
509  */
510  const QPainterPath &region() const;
511 
512  /**
513  * Returns the bounding rect of the object rectangle for the
514  * scaling factor @p xScale and @p yScale.
515  */
516  virtual QRect boundingRect(double xScale, double yScale) const;
517 
518  /**
519  * Returns whether the object rectangle contains the point with absolute coordinates
520  * (@p x, @p y) at a page size of @p xScale x @p yScale.
521  */
522  virtual bool contains(double x, double y, double xScale, double yScale) const;
523 
524  /**
525  * Transforms the object rectangle with the operations defined by @p matrix.
526  */
527  virtual void transform(const QTransform &matrix);
528 
529  /**
530  * Returns the squared distance between the object
531  * and the point with
532  * normalized coordinates (@p x, @p y)
533  * at a page size of @p xScale x @p yScale.
534  *
535  * @since 0.8.2 (KDE 4.2.2)
536  */
537  // FIXME this should most probably be a virtual method
538  double distanceSqr(double x, double y, double xScale, double yScale) const;
539 
540 protected:
541  ObjectType m_objectType;
542  void *m_object;
543  QPainterPath m_path;
544  QPainterPath m_transformedPath;
545 };
546 
547 /**
548  * This class describes the object rectangle for an annotation.
549  */
550 class OKULARCORE_EXPORT AnnotationObjectRect : public ObjectRect
551 {
552 public:
553  /**
554  * Creates a new annotation object rectangle with the
555  * given @p annotation.
556  */
557  explicit AnnotationObjectRect(Annotation *annotation);
558 
559  /**
560  * Destroys the annotation object rectangle.
561  */
562  ~AnnotationObjectRect() override;
563 
564  /**
565  * Returns the annotation object of the annotation object rectangle.
566  */
567  Annotation *annotation() const;
568 
569  /**
570  * Returns the bounding rect of the annotation object rectangle for the
571  * scaling factor @p xScale and @p yScale.
572  */
573  QRect boundingRect(double xScale, double yScale) const override;
574 
575  /**
576  * Returns whether the annotation object rectangle contains the point @p x, @p y for the
577  * scaling factor @p xScale and @p yScale.
578  */
579  bool contains(double x, double y, double xScale, double yScale) const override;
580 
581  /**
582  * Transforms the annotation object rectangle with the operations defined by @p matrix.
583  */
584  void transform(const QTransform &matrix) override;
585 
586 private:
587  Annotation *m_annotation;
588 };
589 
590 /**
591  * This class describes the object rectangle for a source reference.
592  */
593 class OKULARCORE_EXPORT SourceRefObjectRect : public ObjectRect
594 {
595  friend class ObjectRect;
596 
597 public:
598  /**
599  * Creates a new source reference object rectangle.
600  *
601  * @param point The point of the source reference.
602  * @param srcRef The storable source reference object.
603  */
604  SourceRefObjectRect(const NormalizedPoint &point, void *srcRef);
605 
606  /**
607  * Returns the bounding rect of the source reference object rectangle for the
608  * scaling factor @p xScale and @p yScale.
609  */
610  QRect boundingRect(double xScale, double yScale) const override;
611 
612  /**
613  * Returns whether the source reference object rectangle contains the point @p x, @p y for the
614  * scaling factor @p xScale and @p yScale.
615  */
616  bool contains(double x, double y, double xScale, double yScale) const override;
617 
618 private:
619  NormalizedPoint m_point;
620 };
621 
622 /**
623  * This class is an object rect that doesn't own the given pointer, i.e. won't delete it on destruction
624  * @since 1.7
625  */
626 class OKULARCORE_EXPORT NonOwningObjectRect : public ObjectRect
627 {
628 public:
629  NonOwningObjectRect(double left, double top, double right, double bottom, bool ellipse, ObjectType type, void *object);
630  ~NonOwningObjectRect() override;
631 };
632 
633 /// @cond PRIVATE
634 /** @internal */
635 /** @internal */
636 template<typename T> T *givePtr(T &t)
637 {
638  return &t;
639 }
640 
641 /** @internal */
642 template<typename T> T &deref(T &t)
643 {
644  return t;
645 }
646 /// @endcond
647 
648 /**
649  * @short An area with normalized coordinates, consisting of NormalizedShape objects.
650  *
651  * This is a template class to describe an area which consists of
652  * multiple shapes of the same type, intersecting or non-intersecting.
653  * The coordinates are normalized, and can be mapped to a reference area of defined size.
654  * For more information about the normalized coordinate system, see NormalizedPoint.
655  *
656  * Class NormalizedShape \b must have the following functions/operators defined:
657  * - bool contains( double, double ), whether it contains the given NormalizedPoint
658  * - bool intersects( NormalizedShape )
659  * - bool isNull()
660  * - Shape geometry( int, int ), which maps to the reference area
661  * - operator|=( NormalizedShape ), which unites two NormalizedShape's
662  *
663  * @see RegularAreaRect, NormalizedPoint
664  */
665 template<class NormalizedShape, class Shape> class RegularArea : public QList<NormalizedShape>
666 {
667 public:
668  /**
669  * Returns whether this area contains the normalized point (@p x, @p y).
670  */
671  bool contains(double x, double y) const;
672 
673  /**
674  * Returns whether this area contains a NormalizedShape object that equals @p shape.
675  *
676  * @note
677  * The original NormalizedShape objects can be lost if simplify() was called.
678  */
679  bool contains(const NormalizedShape &shape) const;
680 
681  /**
682  * Returns whether this area intersects with the given @p area.
683  */
684  bool intersects(const RegularArea<NormalizedShape, Shape> *area) const;
685 
686  /**
687  * Returns whether the regular area intersects with the given @p shape.
688  */
689  bool intersects(const NormalizedShape &shape) const;
690 
691  /**
692  * Appends the given @p area to this area.
693  */
694  void appendArea(const RegularArea<NormalizedShape, Shape> *area);
695 
696  /**
697  * Appends the given @p shape to this area.
698  */
699  void appendShape(const NormalizedShape &shape, MergeSide side = MergeAll);
700 
701  /**
702  * Simplifies this regular area by merging its intersecting subareas.
703  * This might change the effective geometry of this area.
704  */
705  void simplify();
706 
707  /**
708  * Returns whether the regular area is a null area.
709  */
710  bool isNull() const;
711 
712  /**
713  * Returns the subareas of this regular area
714  * mapped to a reference area of size @p xScale x @p yScale,
715  * then translated by @p dx and @p dy.
716  */
717  QList<Shape> geometry(int xScale, int yScale, int dx = 0, int dy = 0) const;
718 
719  /**
720  * Transforms the regular area with the operations defined by @p matrix.
721  */
722  void transform(const QTransform &matrix);
723 };
724 
725 template<class NormalizedShape, class Shape> void RegularArea<NormalizedShape, Shape>::simplify()
726 {
727 #ifdef DEBUG_REGULARAREA
728  int prev_end = this->count();
729 #endif
730  int end = this->count() - 1, x = 0;
731  for (int i = 0; i < end; ++i) {
732  if (givePtr((*this)[x])->intersects(deref((*this)[i + 1]))) {
733  deref((*this)[x]) |= deref((*this)[i + 1]);
734  this->removeAt(i + 1);
735  --end;
736  --i;
737  } else {
738  x = i + 1;
739  }
740  }
741 #ifdef DEBUG_REGULARAREA
742  qCDebug(OkularCoreDebug) << "from" << prev_end << "to" << this->count();
743 #endif
744 }
745 
746 template<class NormalizedShape, class Shape> bool RegularArea<NormalizedShape, Shape>::isNull() const
747 {
748  if (this->isEmpty())
749  return true;
750 
751  typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
752  for (; it != itEnd; ++it)
753  if (!givePtr(*it)->isNull())
754  return false;
755 
756  return true;
757 }
758 
759 template<class NormalizedShape, class Shape> bool RegularArea<NormalizedShape, Shape>::intersects(const NormalizedShape &shape) const
760 {
761  if (this->isEmpty())
762  return false;
763 
764  typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
765  for (; it != itEnd; ++it)
766  if (!givePtr(*it)->isNull() && givePtr(*it)->intersects(shape))
767  return true;
768 
769  return false;
770 }
771 
772 template<class NormalizedShape, class Shape> bool RegularArea<NormalizedShape, Shape>::intersects(const RegularArea<NormalizedShape, Shape> *area) const
773 {
774  if (this->isEmpty())
775  return false;
776 
777  typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
778  for (; it != itEnd; ++it) {
779  typename QList<NormalizedShape>::const_iterator areaIt = area->begin(), areaItEnd = area->end();
780  for (; areaIt != areaItEnd; ++areaIt) {
781  if (!(*it).isNull() && (*it).intersects(*areaIt))
782  return true;
783  }
784  }
785 
786  return false;
787 }
788 
789 template<class NormalizedShape, class Shape> void RegularArea<NormalizedShape, Shape>::appendArea(const RegularArea<NormalizedShape, Shape> *area)
790 {
791  typename QList<NormalizedShape>::const_iterator areaIt = area->begin(), areaItEnd = area->end();
792  for (; areaIt != areaItEnd; ++areaIt)
793  this->append(*areaIt);
794 }
795 
796 template<class NormalizedShape, class Shape> void RegularArea<NormalizedShape, Shape>::appendShape(const NormalizedShape &shape, MergeSide side)
797 {
798  int size = this->count();
799  // if the list is empty, adds the shape normally
800  if (size == 0) {
801  this->append(shape);
802  } else {
803  bool intersection = false;
804  NormalizedShape &last = (*this)[size - 1];
805 #define O_LAST givePtr(last)
806 #define O_LAST_R O_LAST->right
807 #define O_LAST_L O_LAST->left
808 #define O_LAST_T O_LAST->top
809 #define O_LAST_B O_LAST->bottom
810 #define O_NEW givePtr(shape)
811 #define O_NEW_R O_NEW->right
812 #define O_NEW_L O_NEW->left
813 #define O_NEW_T O_NEW->top
814 #define O_NEW_B O_NEW->bottom
815  switch (side) {
816  case MergeRight:
817  intersection = (O_LAST_R >= O_NEW_L) && (O_LAST_L <= O_NEW_R) && ((O_LAST_T <= O_NEW_T && O_LAST_B >= O_NEW_B) || (O_LAST_T >= O_NEW_T && O_LAST_B <= O_NEW_B));
818  break;
819  case MergeBottom:
820  intersection = (O_LAST_B >= O_NEW_T) && (O_LAST_T <= O_NEW_B) && ((O_LAST_R <= O_NEW_R && O_LAST_L >= O_NEW_L) || (O_LAST_R >= O_NEW_R && O_LAST_L <= O_NEW_L));
821  break;
822  case MergeLeft:
823  intersection = (O_LAST_L <= O_NEW_R) && (O_LAST_R >= O_NEW_L) && ((O_LAST_T <= O_NEW_T && O_LAST_B >= O_NEW_B) || (O_LAST_T >= O_NEW_T && O_LAST_B <= O_NEW_B));
824  break;
825  case MergeTop:
826  intersection = (O_LAST_T <= O_NEW_B) && (O_LAST_B >= O_NEW_T) && ((O_LAST_R <= O_NEW_R && O_LAST_L >= O_NEW_L) || (O_LAST_R >= O_NEW_R && O_LAST_L <= O_NEW_L));
827  break;
828  case MergeAll:
829  intersection = O_LAST->intersects(shape);
830  break;
831  }
832 #undef O_LAST
833 #undef O_LAST_R
834 #undef O_LAST_L
835 #undef O_LAST_T
836 #undef O_LAST_B
837 #undef O_NEW
838 #undef O_NEW_R
839 #undef O_NEW_L
840 #undef O_NEW_T
841 #undef O_NEW_B
842  // if the new shape intersects with the last shape in the list, then
843  // merge it with that and delete the shape
844  if (intersection) {
845  deref((*this)[size - 1]) |= deref(shape);
846  } else
847  this->append(shape);
848  }
849 }
850 
851 template<class NormalizedShape, class Shape> bool RegularArea<NormalizedShape, Shape>::contains(double x, double y) const
852 {
853  if (this->isEmpty())
854  return false;
855 
856  typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
857  for (; it != itEnd; ++it)
858  if ((*it).contains(x, y))
859  return true;
860 
861  return false;
862 }
863 
864 template<class NormalizedShape, class Shape> bool RegularArea<NormalizedShape, Shape>::contains(const NormalizedShape &shape) const
865 {
866  if (this->isEmpty())
867  return false;
868 
869  return QList<NormalizedShape>::contains(shape);
870 }
871 
872 template<class NormalizedShape, class Shape> QList<Shape> RegularArea<NormalizedShape, Shape>::geometry(int xScale, int yScale, int dx, int dy) const
873 {
874  if (this->isEmpty())
875  return QList<Shape>();
876 
877  QList<Shape> ret;
878  Shape t;
879  typename QList<NormalizedShape>::const_iterator it = this->begin(), itEnd = this->end();
880  for (; it != itEnd; ++it) {
881  t = givePtr(*it)->geometry(xScale, yScale);
882  t.translate(dx, dy);
883  ret.append(t);
884  }
885 
886  return ret;
887 }
888 
889 template<class NormalizedShape, class Shape> void RegularArea<NormalizedShape, Shape>::transform(const QTransform &matrix)
890 {
891  if (this->isEmpty())
892  return;
893 
894  for (int i = 0; i < this->count(); ++i)
895  givePtr((*this)[i])->transform(matrix);
896 }
897 
898 /**
899  * This is a list of NormalizedRect, to describe an area consisting of
900  * multiple rectangles using normalized coordinates.
901  *
902  * This area can be mapped to a reference area, resulting in a list of QRects.
903  * For more information about the normalized coordinate system, see NormalizedPoint.
904  *
905  * Okular uses this area e. g. to describe a text highlight area,
906  * which consists of multiple, intersecting or non-intersecting rectangles.
907  *
908  * @see NormalizedRect, NormalizedPoint
909  */
910 class OKULARCORE_EXPORT RegularAreaRect : public RegularArea<NormalizedRect, QRect>
911 {
912 public:
913  RegularAreaRect();
914  RegularAreaRect(const RegularAreaRect &rar);
915  ~RegularAreaRect();
916 
917  RegularAreaRect &operator=(const RegularAreaRect &rar);
918 
919 private:
920  class Private;
921  Private *const d;
922 };
923 
924 /**
925  * This class stores the geometry of a highlighting area in normalized coordinates,
926  * together with highlighting specific information.
927  */
929 {
930 public:
931  /**
932  * Creates a new highlight area rect with the coordinates of
933  * the given @p area.
934  */
935  explicit HighlightAreaRect(const RegularAreaRect *area = nullptr);
936 
937  /**
938  * The search ID of the highlight owner.
939  */
940  int s_id;
941 
942  /**
943  * The color of the highlight.
944  */
946 };
947 
948 uint qHash(const Okular::NormalizedRect &r, uint seed = 0);
949 }
950 
951 #ifndef QT_NO_DEBUG_STREAM
952 /**
953  * Debug operator for normalized @p point.
954  */
955 OKULARCORE_EXPORT QDebug operator<<(QDebug str, const Okular::NormalizedPoint &point);
956 
957 /**
958  * Debug operator for normalized @p rect.
959  */
960 OKULARCORE_EXPORT QDebug operator<<(QDebug str, const Okular::NormalizedRect &rect);
961 #endif
962 
963 #endif
NormalizedPoint is a helper class which stores the coordinates of a normalized point.
Definition: area.h:116
Merge only if the bottom side of the first area intersect.
Definition: global.h:65
Merge only if the left side of the first area intersect.
Definition: global.h:66
void appendArea(const RegularArea< NormalizedShape, Shape > *area)
Appends the given area to this area.
Definition: area.h:789
QList< Shape > geometry(int xScale, int yScale, int dx=0, int dy=0) const
Returns the subareas of this regular area mapped to a reference area of size xScale x yScale...
Definition: area.h:872
bool isRight(const NormalizedPoint &pt) const
Returns true if the point pt is located to the left of the right edge of the rectangle.
Definition: area.h:373
MergeSide
The side(s) to be considered when merging areas.
Definition: global.h:63
This class describes the object rectangle for a source reference.
Definition: area.h:593
bool contains(double x, double y) const
Returns whether this area contains the normalized point (x, y).
Definition: area.h:851
Merge only if the top side of the first area intersect.
Definition: global.h:67
double left
The normalized left coordinate.
Definition: area.h:415
A NormalizedRect is a rectangle which can be defined by two NormalizedPoints.
Definition: area.h:189
void appendShape(const NormalizedShape &shape, MergeSide side=MergeAll)
Appends the given shape to this area.
Definition: area.h:796
This is a list of NormalizedRect, to describe an area consisting of multiple rectangles using normali...
Definition: area.h:910
Merge only if the right side of the first area intersect.
Definition: global.h:64
double y
The normalized y coordinate.
Definition: area.h:172
double width() const
Definition: area.h:401
bool intersects(const RegularArea< NormalizedShape, Shape > *area) const
Returns whether this area intersects with the given area.
Definition: area.h:772
global.h
Definition: action.h:16
This class describes the object rectangle for an annotation.
Definition: area.h:550
double right
The normalized right coordinate.
Definition: area.h:425
bool isNull() const
Returns whether the regular area is a null area.
Definition: area.h:746
void append(const T &value)
QColor color
The color of the highlight.
Definition: area.h:945
double height() const
Definition: area.h:407
An area with normalized coordinates that contains a reference to an object.
Definition: area.h:452
int s_id
The search ID of the highlight owner.
Definition: area.h:940
bool isTopOrLevel(const NormalizedPoint &pt) const
Returns true if the point pt is located above the bottom of the rectangle.
Definition: area.h:355
double distanceSqr(double x, double y, double xScale, double yScale) const
Returns the squared distance of the normalized point (x, y) to the closest edge, or 0 if the point is...
Definition: area.h:384
An area with normalized coordinates, consisting of NormalizedShape objects.
Definition: area.h:665
This class is an object rect that doesn&#39;t own the given pointer, i.e.
Definition: area.h:626
bool isBottom(const NormalizedPoint &pt) const
Returns true if the point pt is located below the bottom of the rectangle.
Definition: area.h:328
Merge if the areas intersects, no matter which side(s).
Definition: global.h:68
QList::iterator end()
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
void transform(const QTransform &matrix)
Transforms the regular area with the operations defined by matrix.
Definition: area.h:889
bool contains(const T &value) const const
bool isBottomOrLevel(const NormalizedPoint &pt) const
Returns true if the point pt is located below the top of the rectangle.
Definition: area.h:346
double top
The normalized top coordinate.
Definition: area.h:420
ObjectType
Describes the type of storable object.
Definition: area.h:458
QDataStream & operator<<(QDataStream &out, const KDateTime::Spec &spec)
double x
The normalized x coordinate.
Definition: area.h:167
bool isTop(const NormalizedPoint &pt) const
Returns true if the point pt is located above the top of the rectangle.
Definition: area.h:337
Annotation struct holds properties shared by all annotations.
Definition: annotations.h:85
void simplify()
Simplifies this regular area by merging its intersecting subareas.
Definition: area.h:725
double bottom
The normalized bottom coordinate.
Definition: area.h:430
bool isLeft(const NormalizedPoint &pt) const
Returns true if the point pt is located to the right of the left edge of the rectangle.
Definition: area.h:364
This class stores the geometry of a highlighting area in normalized coordinates, together with highli...
Definition: area.h:928
QList::iterator begin()
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Jun 12 2021 22:36:00 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.