Okular

area.cpp
1 /***************************************************************************
2  * Copyright (C) 2004-05 by Enrico Ros <[email protected]> *
3  * Copyright (C) 2005 by Piotr Szymanski <[email protected]> *
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  ***************************************************************************/
9 
10 #include "area.h"
11 
12 #include <QDebug>
13 #include <QPolygonF>
14 #include <QRect>
15 
16 #include <math.h>
17 
18 #include "action.h"
19 #include "annotations.h"
20 #include "annotations_p.h"
21 #include "debug_p.h"
22 #include "sourcereference.h"
23 
24 using namespace Okular;
25 
28  : x(0.0)
29  , y(0.0)
30 {
31 }
32 
33 NormalizedPoint::NormalizedPoint(double dX, double dY)
34  : x(dX)
35  , y(dY)
36 {
37 }
38 
39 NormalizedPoint::NormalizedPoint(int iX, int iY, int xScale, int yScale)
40  : x((double)iX / (double)xScale)
41  , y((double)iY / (double)yScale)
42 {
43 }
44 
47 NormalizedPoint::~NormalizedPoint() = default;
48 
50 {
51  qreal tmp_x = (qreal)x;
52  qreal tmp_y = (qreal)y;
53  matrix.map(tmp_x, tmp_y, &tmp_x, &tmp_y);
54  x = tmp_x;
55  y = tmp_y;
56 }
57 
58 double NormalizedPoint::distanceSqr(double x, double y, double xScale, double yScale) const
59 {
60  return pow((this->x - x) * xScale, 2) + pow((this->y - y) * yScale, 2);
61 }
62 
67 NormalizedPoint operator-(const NormalizedPoint &a, const NormalizedPoint &b)
68 {
69  return NormalizedPoint(a.x - b.x, a.y - b.y);
70 }
71 
75 double NormalizedPoint::distanceSqr(double x, double y, double xScale, double yScale, const NormalizedPoint &start, const NormalizedPoint &end)
76 {
77  NormalizedPoint point(x, y);
78  double thisDistance;
79  NormalizedPoint lineSegment(end - start);
80  const double lengthSqr = pow(lineSegment.x, 2) + pow(lineSegment.y, 2);
81 
82  // if the length of the current segment is null, we can just
83  // measure the distance to either end point
84  if (lengthSqr == 0.0) {
85  thisDistance = end.distanceSqr(x, y, xScale, yScale);
86  } else {
87  // vector from the start point of the current line segment to the measurement point
88  NormalizedPoint a = point - start;
89  // vector from the same start point to the end point of the current line segment
90  NormalizedPoint b = end - start;
91 
92  // we're using a * b (dot product) := |a| * |b| * cos(phi) and the knowledge
93  // that cos(phi) is adjacent side / hypotenuse (hypotenuse = |b|)
94  // therefore, t becomes the length of the vector that represents the projection of
95  // the point p onto the current line segment
96  //(hint: if this is still unclear, draw it!)
97  float t = (a.x * b.x + a.y * b.y) / lengthSqr;
98 
99  if (t < 0) {
100  // projection falls outside the line segment on the side of "start"
101  thisDistance = point.distanceSqr(start.x, start.y, xScale, yScale);
102  } else if (t > 1) {
103  // projection falls outside the line segment on the side of the current point
104  thisDistance = point.distanceSqr(end.x, end.y, xScale, yScale);
105  } else {
106  // projection is within [start, *i];
107  // determine the length of the perpendicular distance from the projection to the actual point
108  NormalizedPoint direction = end - start;
109  NormalizedPoint projection = start - NormalizedPoint(-t * direction.x, -t * direction.y);
110  thisDistance = projection.distanceSqr(x, y, xScale, yScale);
111  }
112  }
113  return thisDistance;
114 }
115 
117 {
118  str.nospace() << "NormPt(" << p.x << "," << p.y << ")";
119  return str.space();
120 }
121 
125  : left(0.0)
126  , top(0.0)
127  , right(0.0)
128  , bottom(0.0)
129 {
130 }
131 
132 NormalizedRect::NormalizedRect(double l, double t, double r, double b)
133  // note: check for swapping coords?
134  : left(l)
135  , top(t)
136  , right(r)
137  , bottom(b)
138 {
139 }
140 
141 NormalizedRect::NormalizedRect(const QRect &r, double xScale, double yScale) // clazy:exclude=function-args-by-value TODO when BIC changes are allowed
142  : left((double)r.left() / xScale)
143  , top((double)r.top() / yScale)
144  , right((double)r.right() / xScale)
145  , bottom((double)r.bottom() / yScale)
146 {
147 }
148 
149 NormalizedRect::NormalizedRect(const NormalizedRect &rect) = default;
150 
152 {
153  QRectF nrect = rect.normalized();
154  NormalizedRect ret;
155  ret.left = nrect.left();
156  ret.top = nrect.top();
157  ret.right = nrect.right();
158  ret.bottom = nrect.bottom();
159  return ret;
160 }
161 
163 {
164  return left == 0 && top == 0 && right == 0 && bottom == 0;
165 }
166 
167 bool NormalizedRect::contains(double x, double y) const
168 {
169  return x >= left && x <= right && y >= top && y <= bottom;
170 }
171 
173 {
174  return (r.left <= right) && (r.right >= left) && (r.top <= bottom) && (r.bottom >= top);
175 }
176 
178 {
179  return (r->left <= right) && (r->right >= left) && (r->top <= bottom) && (r->bottom >= top);
180 }
181 
182 bool NormalizedRect::intersects(double l, double t, double r, double b) const
183 {
184  return (l <= right) && (r >= left) && (t <= bottom) && (b >= top);
185 }
186 
188 {
189  NormalizedRect ret;
190  // todo !
191  ret.left = qMin(left, r.left);
192  ret.top = qMin(top, r.top);
193  ret.bottom = qMax(bottom, r.bottom);
194  ret.right = qMax(right, r.right);
195  return ret;
196 }
197 
199 {
200  left = qMin(left, r.left);
201  top = qMin(top, r.top);
202  bottom = qMax(bottom, r.bottom);
203  right = qMax(right, r.right);
204  return *this;
205 }
206 
208 {
209  if (isNull() || r.isNull())
210  return NormalizedRect();
211 
212  NormalizedRect ret;
213  ret.left = qMax(left, r.left);
214  ret.top = qMax(top, r.top);
215  ret.bottom = qMin(bottom, r.bottom);
216  ret.right = qMin(right, r.right);
217  return ret;
218 }
219 
221 
222 NormalizedRect::~NormalizedRect() = default;
223 
225 {
226  return (isNull() && r.isNull()) || (fabs(left - r.left) < 1e-4 && fabs(right - r.right) < 1e-4 && fabs(top - r.top) < 1e-4 && fabs(bottom - r.bottom) < 1e-4);
227 }
228 
230 {
231  return NormalizedPoint((left + right) / 2.0, (top + bottom) / 2.0);
232 }
233 
234 /*
235 QDebug operator << (QDebug str , const NormalizedRect &r)
236 {
237  str << "[" <<r.left() << "," << r.top() << "] x "<< "[" <<r.right() << "," << r.bottom() << "]";
238  return str;
239 }*/
240 
241 QRect NormalizedRect::geometry(int xScale, int yScale) const
242 {
243  int l = (int)(left * xScale), t = (int)(top * yScale), r = (int)(right * xScale), b = (int)(bottom * yScale);
244 
245  return QRect(l, t, r - l + 1, b - t + 1);
246 }
247 
248 QRect NormalizedRect::roundedGeometry(int xScale, int yScale) const
249 {
250  int l = (int)(left * xScale + 0.5), t = (int)(top * yScale + 0.5), r = (int)(right * xScale + 0.5), b = (int)(bottom * yScale + 0.5);
251 
252  return QRect(l, t, r - l + 1, b - t + 1);
253 }
254 
256 {
257  QRectF rect(left, top, right - left, bottom - top);
258  rect = matrix.mapRect(rect);
259 
260  left = rect.left();
261  top = rect.top();
262  right = rect.right();
263  bottom = rect.bottom();
264 }
265 
266 uint Okular::qHash(const NormalizedRect &r, uint seed)
267 {
268  return ::qHash(r.bottom, ::qHash(r.right, ::qHash(r.top, ::qHash(r.left, seed))));
269 }
270 
272 {
273  str.nospace() << "NormRect(" << r.left << "," << r.top << " x " << (r.right - r.left) << "+" << (r.bottom - r.top) << ")";
274  return str.space();
275 }
276 
277 RegularAreaRect::RegularAreaRect()
279  , d(nullptr)
280 {
281 }
282 
283 RegularAreaRect::RegularAreaRect(const RegularAreaRect &rar)
285  , d(nullptr)
286 {
287 }
288 
289 RegularAreaRect::~RegularAreaRect()
290 {
291 }
292 
293 RegularAreaRect &RegularAreaRect::operator=(const RegularAreaRect &rar)
294 {
295  if (this != &rar) {
297  }
298  return *this;
299 }
300 
302  : RegularAreaRect()
303  , s_id(-1)
304 {
305  if (area) {
307  RegularAreaRect::ConstIterator itEnd = area->end();
308  for (; it != itEnd; ++it) {
309  append(NormalizedRect(*it));
310  }
311  }
312 }
313 
316 ObjectRect::ObjectRect(double l, double t, double r, double b, bool ellipse, ObjectType type, void *object)
317  : m_objectType(type)
318  , m_object(object)
319 {
320  // assign coordinates swapping them if negative width or height
321  QRectF rect(r > l ? l : r, b > t ? t : b, fabs(r - l), fabs(b - t));
322  if (ellipse)
323  m_path.addEllipse(rect);
324  else
325  m_path.addRect(rect);
326 
327  m_transformedPath = m_path;
328 }
329 
330 ObjectRect::ObjectRect(const NormalizedRect &r, bool ellipse, ObjectType type, void *object)
331  : m_objectType(type)
332  , m_object(object)
333 {
334  QRectF rect(r.left, r.top, fabs(r.right - r.left), fabs(r.bottom - r.top));
335  if (ellipse)
336  m_path.addEllipse(rect);
337  else
338  m_path.addRect(rect);
339 
340  m_transformedPath = m_path;
341 }
342 
343 ObjectRect::ObjectRect(const QPolygonF &poly, ObjectType type, void *object)
344  : m_objectType(type)
345  , m_object(object)
346 {
347  m_path.addPolygon(poly);
348 
349  m_transformedPath = m_path;
350 }
351 
353 {
354  return m_objectType;
355 }
356 
357 const void *ObjectRect::object() const
358 {
359  return m_object;
360 }
361 
363 {
364  return m_transformedPath;
365 }
366 
367 QRect ObjectRect::boundingRect(double xScale, double yScale) const
368 {
369  const QRectF &br = m_transformedPath.boundingRect();
370 
371  return QRect((int)(br.left() * xScale), (int)(br.top() * yScale), (int)(br.width() * xScale), (int)(br.height() * yScale));
372 }
373 
374 bool ObjectRect::contains(double x, double y, double, double) const
375 {
376  return m_transformedPath.contains(QPointF(x, y));
377 }
378 
380 {
381  m_transformedPath = matrix.map(m_path);
382 }
383 
384 double ObjectRect::distanceSqr(double x, double y, double xScale, double yScale) const
385 {
386  switch (m_objectType) {
387  case Action:
388  case Image: {
389  const QRectF &rect(m_transformedPath.boundingRect());
390  return NormalizedRect(rect.x(), rect.y(), rect.right(), rect.bottom()).distanceSqr(x, y, xScale, yScale);
391  }
392  case OAnnotation: {
393  return static_cast<Annotation *>(m_object)->d_func()->distanceSqr(x, y, xScale, yScale);
394  }
395  case SourceRef: {
396  const SourceRefObjectRect *sr = static_cast<const SourceRefObjectRect *>(this);
397  const NormalizedPoint &point = sr->m_point;
398  if (point.x == -1.0) {
399  return pow((y - point.y) * yScale, 2);
400  } else if (point.y == -1.0) {
401  return pow((x - point.x) * xScale, 2);
402  } else {
403  return pow((x - point.x) * xScale, 2) + pow((y - point.y) * yScale, 2);
404  }
405  }
406  }
407  return 0.0;
408 }
409 
411 {
412  if (!m_object)
413  return;
414 
415  if (m_objectType == Action)
416  delete static_cast<Okular::Action *>(m_object);
417  else if (m_objectType == SourceRef)
418  delete static_cast<Okular::SourceReference *>(m_object);
419  else
420  qCDebug(OkularCoreDebug).nospace() << "Object deletion not implemented for type '" << m_objectType << "'.";
421 }
422 
426  : ObjectRect(QPolygonF(), OAnnotation, annotation)
427  , m_annotation(annotation)
428 {
429 }
430 
432 {
433  return m_annotation;
434 }
435 
436 QRect AnnotationObjectRect::boundingRect(double xScale, double yScale) const
437 {
438  const QRect annotRect = AnnotationUtils::annotationGeometry(m_annotation, xScale, yScale);
439  const QPoint center = annotRect.center();
440 
441  // Make sure that the rectangle has a minimum size, so that it's possible
442  // to click on it
443  const int minSize = 14;
444  const QRect minRect(center.x() - minSize / 2, center.y() - minSize / 2, minSize, minSize);
445 
446  return annotRect | minRect;
447 }
448 
449 bool AnnotationObjectRect::contains(double x, double y, double xScale, double yScale) const
450 {
451  return boundingRect(xScale, yScale).contains((int)(x * xScale), (int)(y * yScale), false);
452 }
453 
455 {
456  // the annotation pointer is kept elsewehere (in Page, most probably),
457  // so just release its pointer
458  m_object = nullptr;
459 }
460 
462 {
463  m_annotation->d_func()->annotationTransform(matrix);
464 }
465 
469  : ObjectRect(point.x, point.y, .0, .0, false, SourceRef, srcRef)
470  , m_point(point)
471 {
472  const double x = m_point.x < 0.0 ? 0.5 : m_point.x;
473  const double y = m_point.y < 0.0 ? 0.5 : m_point.y;
474  const QRectF rect(x - 2, y - 2, 5, 5);
475  m_path.addRect(rect);
476 
477  m_transformedPath = m_path;
478 }
479 
480 QRect SourceRefObjectRect::boundingRect(double xScale, double yScale) const
481 {
482  const double x = m_point.x < 0.0 ? 0.5 : m_point.x;
483  const double y = m_point.y < 0.0 ? 0.5 : m_point.y;
484 
485  return QRect(x * xScale, y * yScale, 1, 1);
486 }
487 
488 bool SourceRefObjectRect::contains(double x, double y, double xScale, double yScale) const
489 {
490  return distanceSqr(x, y, xScale, yScale) < (pow(7.0 / xScale, 2) + pow(7.0 / yScale, 2));
491 }
492 
495 NonOwningObjectRect::NonOwningObjectRect(double left, double top, double right, double bottom, bool ellipse, ObjectType type, void *object)
496  : ObjectRect(left, top, right, bottom, ellipse, type, object)
497 {
498 }
499 
500 NonOwningObjectRect::~NonOwningObjectRect()
501 {
502  // Set m_object so that ~ObjectRect() doesn't delete it
503  m_object = nullptr;
504 }
void addEllipse(const QRectF &boundingRectangle)
SourceRefObjectRect(const NormalizedPoint &point, void *srcRef)
Creates a new source reference object rectangle.
Definition: area.cpp:468
NormalizedPoint is a helper class which stores the coordinates of a normalized point.
Definition: area.h:119
QRectF boundingRect() const const
QList< T > & operator=(const QList< T > &other)
NormalizedRect()
Creates a null normalized rectangle.
Definition: area.cpp:124
virtual QRect boundingRect(double xScale, double yScale) const
Returns the bounding rect of the object rectangle for the scaling factor xScale and yScale...
Definition: area.cpp:367
This class describes the object rectangle for a source reference.
Definition: area.h:594
QPoint map(const QPoint &point) const const
void transform(const QTransform &matrix)
Transforms the normalized rectangle with the operations defined by matrix.
Definition: area.cpp:255
NormalizedPoint center() const
Returns the center of the rectangle.
Definition: area.cpp:229
bool contains(const QPointF &point) const const
double left
The normalized left coordinate.
Definition: area.h:416
A NormalizedRect is a rectangle which can be defined by two NormalizedPoints.
Definition: area.h:191
QDebug & nospace()
NormalizedRect operator&(const NormalizedRect &other) const
Returns the intersection of this normalized rectangle with the specified other.
Definition: area.cpp:207
NormalizedRect & operator|=(const NormalizedRect &other)
Sets the normalized rectangle to the normalized bounding rectangle of itself combined with the other ...
Definition: area.cpp:198
const void * object() const
Returns the storable object of the object rectangle.
Definition: area.cpp:357
This is a list of NormalizedRect, to describe an area consisting of multiple rectangles using normali...
Definition: area.h:911
qreal top() const const
ObjectType objectType() const
Returns the object type of the object rectangle.
Definition: area.cpp:352
double y
The normalized y coordinate.
Definition: area.h:174
AnnotationObjectRect(Annotation *annotation)
Creates a new annotation object rectangle with the given annotation.
Definition: area.cpp:425
bool contains(double x, double y, double xScale, double yScale) const override
Returns whether the source reference object rectangle contains the point x, y for the scaling factor ...
Definition: area.cpp:488
NormalizedRect operator|(const NormalizedRect &other) const
Returns the normalized bounding rectangle of the normalized rectangle combined with the other normali...
Definition: area.cpp:187
global.h
Definition: action.h:19
HighlightAreaRect(const RegularAreaRect *area=nullptr)
Creates a new highlight area rect with the coordinates of the given area.
Definition: area.cpp:301
qreal left() const const
bool intersects(const NormalizedRect &other) const
Returns whether the normalized rectangle intersects the other normalized rectangle.
Definition: area.cpp:172
int x() const const
int y() const const
void transform(const QTransform &matrix) override
Transforms the annotation object rectangle with the operations defined by matrix. ...
Definition: area.cpp:461
bool contains(double x, double y, double xScale, double yScale) const override
Returns whether the annotation object rectangle contains the point x, y for the scaling factor xScale...
Definition: area.cpp:449
static QRect annotationGeometry(const Annotation *annotation, double scaleX, double scaleY)
Returns the geometry of the given annotation scaled by scaleX and scaleY.
ObjectRect(double left, double top, double right, double bottom, bool ellipse, ObjectType type, void *object)
Creates a new object rectangle.
Definition: area.cpp:316
qreal bottom() const const
bool contains(double x, double y) const
Returns whether the normalized rectangle contains the normalized point (x, y).
Definition: area.cpp:167
double right
The normalized right coordinate.
Definition: area.h:426
void append(const T &value)
void addPolygon(const QPolygonF &polygon)
NormalizedRect & operator=(const NormalizedRect &other)
An area with normalized coordinates that contains a reference to an object.
Definition: area.h:453
QRectF normalized() const const
void addRect(const QRectF &rectangle)
NormalizedPoint()
Creates a normalized point at (0, 0).
Definition: area.cpp:27
NonOwningObjectRect(double left, double top, double right, double bottom, bool ellipse, ObjectType type, void *object)
class NonOwningObjectRect
Definition: area.cpp:495
QPoint center() const const
bool operator==(const NormalizedRect &other) const
Returns whether the normalized rectangle is equal to the other normalized rectangle.
Definition: area.cpp:224
virtual void transform(const QTransform &matrix)
Transforms the object rectangle with the operations defined by matrix.
Definition: area.cpp:379
double distanceSqr(double x, double y, double xScale, double yScale) const
Returns squared distance to normalized point (x, y) on a reference area of size xScale x yScale...
Definition: area.cpp:58
QRect roundedGeometry(int xScale, int yScale) const
Same functionality as geometry, but the output is now rounded before typecasting to int...
Definition: area.cpp:248
QRect geometry(int xScale, int yScale) const
Returns the rectangle mapped to a reference area of xScale x yScale.
Definition: area.cpp:241
QList::iterator end()
qreal right() const const
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
QDebug & space()
double top
The normalized top coordinate.
Definition: area.h:421
Encapsulates data that describes an action.
Definition: action.h:43
virtual bool contains(double x, double y, double xScale, double yScale) const
Returns whether the object rectangle contains the point with absolute coordinates (x...
Definition: area.cpp:374
Defines a source reference.
ObjectType
Describes the type of storable object.
Definition: area.h:459
QRect boundingRect(double xScale, double yScale) const override
Returns the bounding rect of the source reference object rectangle for the scaling factor xScale and ...
Definition: area.cpp:480
QDataStream & operator<<(QDataStream &out, const KDateTime::Spec &spec)
bool contains(const QRect &rectangle, bool proper) const const
double x
The normalized x coordinate.
Definition: area.h:169
QRect boundingRect(double xScale, double yScale) const override
Returns the bounding rect of the annotation object rectangle for the scaling factor xScale and yScale...
Definition: area.cpp:436
qreal width() const const
A source reference.
Definition: area.h:463
double distanceSqr(double x, double y, double xScale, double yScale) const
Returns the squared distance between the object and the point with normalized coordinates (x...
Definition: area.cpp:384
Annotation struct holds properties shared by all annotations.
Definition: annotations.h:88
bool isNull() const
Returns whether this normalized rectangle is a null normalized rect.
Definition: area.cpp:162
Annotation * annotation() const
Returns the annotation object of the annotation object rectangle.
Definition: area.cpp:431
const QPainterPath & region() const
Returns the region that is covered by the object rectangle.
Definition: area.cpp:362
qreal height() const const
NormalizedPoint & operator=(const NormalizedPoint &)
static NormalizedRect fromQRectF(const QRectF &rect)
Build a normalized rect from a QRectF, which already has normalized coordinates.
Definition: area.cpp:151
double bottom
The normalized bottom coordinate.
Definition: area.h:431
~AnnotationObjectRect() override
Destroys the annotation object rectangle.
Definition: area.cpp:454
void transform(const QTransform &matrix)
Transforms the normalized point with the operations defined by matrix.
Definition: area.cpp:49
QRect mapRect(const QRect &rectangle) const const
QList::iterator begin()
virtual ~ObjectRect()
Destroys the object rectangle.
Definition: area.cpp:410
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Sep 23 2020 22:36:12 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.