Okular

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

KDE's Doxygen guidelines are available online.