2005-07-15 18:20:57 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2004-05 by Enrico Ros <eros.kde@email.it> *
|
|
|
|
* Copyright (C) 2005 by Piotr Szymanski <niedakh@gmail.com> *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
***************************************************************************/
|
2006-09-19 17:17:29 +00:00
|
|
|
|
2007-04-19 18:30:20 +00:00
|
|
|
#include "area.h"
|
|
|
|
|
2018-08-31 09:23:45 +00:00
|
|
|
#include <QPolygonF>
|
|
|
|
#include <QRect>
|
2006-09-21 08:45:36 +00:00
|
|
|
|
2007-04-20 11:26:05 +00:00
|
|
|
#include "action.h"
|
2006-09-19 17:17:29 +00:00
|
|
|
#include "annotations.h"
|
2007-05-04 20:45:45 +00:00
|
|
|
#include "annotations_p.h"
|
2008-01-20 16:39:21 +00:00
|
|
|
#include "debug_p.h"
|
2007-01-02 17:50:24 +00:00
|
|
|
#include "sourcereference.h"
|
2005-07-15 18:20:57 +00:00
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
using namespace Okular;
|
2006-07-12 22:00:46 +00:00
|
|
|
|
2005-07-15 18:20:57 +00:00
|
|
|
/** class NormalizedPoint **/
|
|
|
|
NormalizedPoint::NormalizedPoint()
|
|
|
|
: x(0.0)
|
|
|
|
, y(0.0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NormalizedPoint::NormalizedPoint(double dX, double dY)
|
|
|
|
: x(dX)
|
|
|
|
, y(dY)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NormalizedPoint::NormalizedPoint(int iX, int iY, int xScale, int yScale)
|
|
|
|
: x((double)iX / (double)xScale)
|
|
|
|
, y((double)iY / (double)yScale)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-01-09 23:44:41 +00:00
|
|
|
NormalizedPoint &NormalizedPoint::operator=(const NormalizedPoint &p) = default;
|
|
|
|
NormalizedPoint::NormalizedPoint(const NormalizedPoint &) = default;
|
|
|
|
NormalizedPoint::~NormalizedPoint() = default;
|
2006-09-26 22:22:01 +00:00
|
|
|
|
2012-09-08 15:06:02 +00:00
|
|
|
void NormalizedPoint::transform(const QTransform &matrix)
|
2006-11-20 07:53:32 +00:00
|
|
|
{
|
2008-07-25 20:51:42 +00:00
|
|
|
qreal tmp_x = (qreal)x;
|
|
|
|
qreal tmp_y = (qreal)y;
|
|
|
|
matrix.map(tmp_x, tmp_y, &tmp_x, &tmp_y);
|
|
|
|
x = tmp_x;
|
|
|
|
y = tmp_y;
|
2006-11-20 07:53:32 +00:00
|
|
|
}
|
2005-07-15 18:20:57 +00:00
|
|
|
|
2013-06-23 17:19:25 +00:00
|
|
|
double NormalizedPoint::distanceSqr(double x, double y, double xScale, double yScale) const
|
|
|
|
{
|
|
|
|
return pow((this->x - x) * xScale, 2) + pow((this->y - y) * yScale, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a vector from the given points @p a and @p b
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
NormalizedPoint operator-(const NormalizedPoint &a, const NormalizedPoint &b)
|
|
|
|
{
|
|
|
|
return NormalizedPoint(a.x - b.x, a.y - b.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Calculates distance of the point @p x @p y @p xScale @p yScale to the line segment from @p start to @p end
|
|
|
|
*/
|
|
|
|
double NormalizedPoint::distanceSqr(double x, double y, double xScale, double yScale, const NormalizedPoint &start, const NormalizedPoint &end)
|
|
|
|
{
|
|
|
|
NormalizedPoint point(x, y);
|
|
|
|
double thisDistance;
|
|
|
|
NormalizedPoint lineSegment(end - start);
|
|
|
|
const double lengthSqr = pow(lineSegment.x, 2) + pow(lineSegment.y, 2);
|
2020-07-10 22:15:05 +00:00
|
|
|
|
2013-06-23 17:19:25 +00:00
|
|
|
// if the length of the current segment is null, we can just
|
|
|
|
// measure the distance to either end point
|
|
|
|
if (lengthSqr == 0.0) {
|
|
|
|
thisDistance = end.distanceSqr(x, y, xScale, yScale);
|
|
|
|
} else {
|
|
|
|
// vector from the start point of the current line segment to the measurement point
|
|
|
|
NormalizedPoint a = point - start;
|
|
|
|
// vector from the same start point to the end point of the current line segment
|
|
|
|
NormalizedPoint b = end - start;
|
|
|
|
|
|
|
|
// we're using a * b (dot product) := |a| * |b| * cos(phi) and the knowledge
|
|
|
|
// that cos(phi) is adjacent side / hypotenuse (hypotenuse = |b|)
|
|
|
|
// therefore, t becomes the length of the vector that represents the projection of
|
|
|
|
// the point p onto the current line segment
|
|
|
|
//(hint: if this is still unclear, draw it!)
|
|
|
|
float t = (a.x * b.x + a.y * b.y) / lengthSqr;
|
|
|
|
|
|
|
|
if (t < 0) {
|
|
|
|
// projection falls outside the line segment on the side of "start"
|
|
|
|
thisDistance = point.distanceSqr(start.x, start.y, xScale, yScale);
|
|
|
|
} else if (t > 1) {
|
|
|
|
// projection falls outside the line segment on the side of the current point
|
|
|
|
thisDistance = point.distanceSqr(end.x, end.y, xScale, yScale);
|
|
|
|
} else {
|
|
|
|
// projection is within [start, *i];
|
|
|
|
// determine the length of the perpendicular distance from the projection to the actual point
|
|
|
|
NormalizedPoint direction = end - start;
|
|
|
|
NormalizedPoint projection = start - NormalizedPoint(-t * direction.x, -t * direction.y);
|
|
|
|
thisDistance = projection.distanceSqr(x, y, xScale, yScale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return thisDistance;
|
|
|
|
}
|
|
|
|
|
2007-07-30 23:58:04 +00:00
|
|
|
QDebug operator<<(QDebug str, const Okular::NormalizedPoint &p)
|
2006-12-31 17:52:24 +00:00
|
|
|
{
|
2007-07-31 10:19:48 +00:00
|
|
|
str.nospace() << "NormPt(" << p.x << "," << p.y << ")";
|
|
|
|
return str.space();
|
2006-12-31 17:52:24 +00:00
|
|
|
}
|
|
|
|
|
2005-07-15 18:20:57 +00:00
|
|
|
/** class NormalizedRect **/
|
|
|
|
|
|
|
|
NormalizedRect::NormalizedRect()
|
|
|
|
: left(0.0)
|
|
|
|
, top(0.0)
|
|
|
|
, right(0.0)
|
|
|
|
, bottom(0.0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NormalizedRect::NormalizedRect(double l, double t, double r, double b)
|
|
|
|
// note: check for swapping coords?
|
|
|
|
: left(l)
|
|
|
|
, top(t)
|
|
|
|
, right(r)
|
|
|
|
, bottom(b)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-02-20 17:45:46 +00:00
|
|
|
NormalizedRect::NormalizedRect(const QRect &r, double xScale, double yScale) // clazy:exclude=function-args-by-value TODO when BIC changes are allowed
|
2005-07-15 18:20:57 +00:00
|
|
|
: left((double)r.left() / xScale)
|
|
|
|
, top((double)r.top() / yScale)
|
|
|
|
, right((double)r.right() / xScale)
|
|
|
|
, bottom((double)r.bottom() / yScale)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-01-09 23:44:41 +00:00
|
|
|
NormalizedRect::NormalizedRect(const NormalizedRect &rect) = default;
|
2006-06-23 21:11:52 +00:00
|
|
|
|
2007-02-01 18:31:45 +00:00
|
|
|
NormalizedRect NormalizedRect::fromQRectF(const QRectF &rect)
|
|
|
|
{
|
2008-12-28 01:20:43 +00:00
|
|
|
QRectF nrect = rect.normalized();
|
2007-02-01 18:31:45 +00:00
|
|
|
NormalizedRect ret;
|
2008-12-28 01:20:43 +00:00
|
|
|
ret.left = nrect.left();
|
|
|
|
ret.top = nrect.top();
|
|
|
|
ret.right = nrect.right();
|
|
|
|
ret.bottom = nrect.bottom();
|
2007-02-01 18:31:45 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-07-15 18:20:57 +00:00
|
|
|
bool NormalizedRect::isNull() const
|
|
|
|
{
|
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
|
|
|
return left == 0 && top == 0 && right == 0 && bottom == 0;
|
2005-07-15 18:20:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NormalizedRect::contains(double x, double y) const
|
|
|
|
{
|
|
|
|
return x >= left && x <= right && y >= top && y <= bottom;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NormalizedRect::intersects(const NormalizedRect &r) const
|
|
|
|
{
|
|
|
|
return (r.left <= right) && (r.right >= left) && (r.top <= bottom) && (r.bottom >= top);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NormalizedRect::intersects(const NormalizedRect *r) const
|
|
|
|
{
|
|
|
|
return (r->left <= right) && (r->right >= left) && (r->top <= bottom) && (r->bottom >= top);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NormalizedRect::intersects(double l, double t, double r, double b) const
|
|
|
|
{
|
|
|
|
return (l <= right) && (r >= left) && (t <= bottom) && (b >= top);
|
|
|
|
}
|
|
|
|
|
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
|
|
|
NormalizedRect NormalizedRect::operator|(const NormalizedRect &r) const
|
|
|
|
{
|
|
|
|
NormalizedRect ret;
|
|
|
|
// todo !
|
2006-03-29 17:16:46 +00:00
|
|
|
ret.left = qMin(left, r.left);
|
|
|
|
ret.top = qMin(top, r.top);
|
|
|
|
ret.bottom = qMax(bottom, r.bottom);
|
|
|
|
ret.right = qMax(right, r.right);
|
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
NormalizedRect &NormalizedRect::operator|=(const NormalizedRect &r)
|
|
|
|
{
|
2006-10-12 21:43:55 +00:00
|
|
|
left = qMin(left, r.left);
|
|
|
|
top = qMin(top, r.top);
|
|
|
|
bottom = qMax(bottom, r.bottom);
|
|
|
|
right = qMax(right, r.right);
|
|
|
|
return *this;
|
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
|
|
|
}
|
2006-06-23 21:11:52 +00:00
|
|
|
|
2008-05-18 21:08:31 +00:00
|
|
|
NormalizedRect NormalizedRect::operator&(const NormalizedRect &r) const
|
|
|
|
{
|
|
|
|
if (isNull() || r.isNull())
|
|
|
|
return NormalizedRect();
|
|
|
|
|
|
|
|
NormalizedRect ret;
|
|
|
|
ret.left = qMax(left, r.left);
|
|
|
|
ret.top = qMax(top, r.top);
|
|
|
|
ret.bottom = qMin(bottom, r.bottom);
|
|
|
|
ret.right = qMin(right, r.right);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-01-09 23:44:41 +00:00
|
|
|
NormalizedRect &NormalizedRect::operator=(const NormalizedRect &r) = default;
|
|
|
|
|
|
|
|
NormalizedRect::~NormalizedRect() = default;
|
2006-06-23 21:11:52 +00:00
|
|
|
|
2006-07-12 22:00:46 +00:00
|
|
|
bool NormalizedRect::operator==(const NormalizedRect &r) const
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-11-12 21:45:35 +00:00
|
|
|
NormalizedPoint NormalizedRect::center() const
|
|
|
|
{
|
|
|
|
return NormalizedPoint((left + right) / 2.0, (top + bottom) / 2.0);
|
|
|
|
}
|
|
|
|
|
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
|
|
|
/*
|
2007-07-30 23:58:04 +00:00
|
|
|
QDebug operator << (QDebug str , const NormalizedRect &r)
|
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
|
|
|
{
|
|
|
|
str << "[" <<r.left() << "," << r.top() << "] x "<< "[" <<r.right() << "," << r.bottom() << "]";
|
|
|
|
return str;
|
|
|
|
}*/
|
|
|
|
|
2005-07-15 18:20:57 +00:00
|
|
|
QRect NormalizedRect::geometry(int xScale, int yScale) const
|
|
|
|
{
|
|
|
|
int l = (int)(left * xScale), t = (int)(top * yScale), r = (int)(right * xScale), b = (int)(bottom * yScale);
|
2006-11-20 07:53:32 +00:00
|
|
|
|
2005-07-15 18:20:57 +00:00
|
|
|
return QRect(l, t, r - l + 1, b - t + 1);
|
|
|
|
}
|
|
|
|
|
2011-07-02 15:24:50 +00:00
|
|
|
QRect NormalizedRect::roundedGeometry(int xScale, int yScale) const
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
|
|
|
return QRect(l, t, r - l + 1, b - t + 1);
|
|
|
|
}
|
|
|
|
|
2012-09-08 15:06:02 +00:00
|
|
|
void NormalizedRect::transform(const QTransform &matrix)
|
2006-11-20 07:53:32 +00:00
|
|
|
{
|
|
|
|
QRectF rect(left, top, right - left, bottom - top);
|
|
|
|
rect = matrix.mapRect(rect);
|
|
|
|
|
|
|
|
left = rect.left();
|
|
|
|
top = rect.top();
|
|
|
|
right = rect.right();
|
|
|
|
bottom = rect.bottom();
|
|
|
|
}
|
|
|
|
|
2020-02-19 15:59:44 +00:00
|
|
|
uint Okular::qHash(const NormalizedRect &r, uint seed)
|
2015-10-17 12:10:16 +00:00
|
|
|
{
|
2020-02-19 15:59:44 +00:00
|
|
|
return ::qHash(r.bottom, ::qHash(r.right, ::qHash(r.top, ::qHash(r.left, seed))));
|
2015-10-17 12:10:16 +00:00
|
|
|
}
|
|
|
|
|
2007-07-30 23:58:04 +00:00
|
|
|
QDebug operator<<(QDebug str, const Okular::NormalizedRect &r)
|
2006-12-31 17:52:24 +00:00
|
|
|
{
|
2007-07-31 10:19:48 +00:00
|
|
|
str.nospace() << "NormRect(" << r.left << "," << r.top << " x " << (r.right - r.left) << "+" << (r.bottom - r.top) << ")";
|
|
|
|
return str.space();
|
2006-12-31 17:52:24 +00:00
|
|
|
}
|
|
|
|
|
2007-07-10 23:15:14 +00:00
|
|
|
RegularAreaRect::RegularAreaRect()
|
2017-09-05 21:27:18 +00:00
|
|
|
: RegularArea<NormalizedRect, QRect>()
|
|
|
|
, d(nullptr)
|
2007-07-10 23:15:14 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
RegularAreaRect::RegularAreaRect(const RegularAreaRect &rar)
|
2017-09-05 21:27:18 +00:00
|
|
|
: RegularArea<NormalizedRect, QRect>(rar)
|
|
|
|
, d(nullptr)
|
2007-07-10 23:15:14 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
RegularAreaRect::~RegularAreaRect()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
RegularAreaRect &RegularAreaRect::operator=(const RegularAreaRect &rar)
|
|
|
|
{
|
2019-12-23 13:57:50 +00:00
|
|
|
if (this != &rar) {
|
|
|
|
RegularArea<NormalizedRect, QRect>::operator=(rar);
|
|
|
|
}
|
2007-07-10 23:15:14 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2006-10-12 21:55:32 +00:00
|
|
|
HighlightAreaRect::HighlightAreaRect(const RegularAreaRect *area)
|
|
|
|
: RegularAreaRect()
|
|
|
|
, s_id(-1)
|
2005-07-15 18:20:57 +00:00
|
|
|
{
|
2006-10-12 21:55:32 +00:00
|
|
|
if (area) {
|
|
|
|
RegularAreaRect::ConstIterator it = area->begin();
|
|
|
|
RegularAreaRect::ConstIterator itEnd = area->end();
|
|
|
|
for (; it != itEnd; ++it) {
|
2007-09-05 14:51:40 +00:00
|
|
|
append(NormalizedRect(*it));
|
2006-10-12 21:55:32 +00:00
|
|
|
}
|
|
|
|
}
|
2005-07-15 18:20:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** class ObjectRect **/
|
|
|
|
|
2019-12-20 15:40:59 +00:00
|
|
|
ObjectRect::ObjectRect(double l, double t, double r, double b, bool ellipse, ObjectType type, void *object)
|
|
|
|
: m_objectType(type)
|
|
|
|
, m_object(object)
|
2005-07-15 18:20:57 +00:00
|
|
|
{
|
2006-07-13 15:03:18 +00:00
|
|
|
// assign coordinates swapping them if negative width or height
|
|
|
|
QRectF rect(r > l ? l : r, b > t ? t : b, fabs(r - l), fabs(b - t));
|
|
|
|
if (ellipse)
|
|
|
|
m_path.addEllipse(rect);
|
|
|
|
else
|
|
|
|
m_path.addRect(rect);
|
2006-11-20 07:53:32 +00:00
|
|
|
|
2007-01-02 17:05:49 +00:00
|
|
|
m_transformedPath = m_path;
|
2006-07-13 15:03:18 +00:00
|
|
|
}
|
|
|
|
|
2019-12-20 15:40:59 +00:00
|
|
|
ObjectRect::ObjectRect(const NormalizedRect &r, bool ellipse, ObjectType type, void *object)
|
|
|
|
: m_objectType(type)
|
|
|
|
, m_object(object)
|
2006-07-13 15:03:18 +00:00
|
|
|
{
|
2019-12-20 15:40:59 +00:00
|
|
|
QRectF rect(r.left, r.top, fabs(r.right - r.left), fabs(r.bottom - r.top));
|
2006-07-13 15:03:18 +00:00
|
|
|
if (ellipse)
|
|
|
|
m_path.addEllipse(rect);
|
|
|
|
else
|
|
|
|
m_path.addRect(rect);
|
2006-11-20 07:53:32 +00:00
|
|
|
|
2007-01-02 17:05:49 +00:00
|
|
|
m_transformedPath = m_path;
|
2006-07-13 15:03:18 +00:00
|
|
|
}
|
|
|
|
|
2019-12-20 15:40:59 +00:00
|
|
|
ObjectRect::ObjectRect(const QPolygonF &poly, ObjectType type, void *object)
|
|
|
|
: m_objectType(type)
|
|
|
|
, m_object(object)
|
2006-07-13 15:03:18 +00:00
|
|
|
{
|
|
|
|
m_path.addPolygon(poly);
|
2006-11-20 07:53:32 +00:00
|
|
|
|
2007-01-02 17:05:49 +00:00
|
|
|
m_transformedPath = m_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectRect::ObjectType ObjectRect::objectType() const
|
|
|
|
{
|
|
|
|
return m_objectType;
|
|
|
|
}
|
|
|
|
|
|
|
|
const void *ObjectRect::object() const
|
|
|
|
{
|
|
|
|
return m_object;
|
2006-11-20 07:53:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const QPainterPath &ObjectRect::region() const
|
|
|
|
{
|
2007-01-02 17:05:49 +00:00
|
|
|
return m_transformedPath;
|
2005-07-15 18:20:57 +00:00
|
|
|
}
|
|
|
|
|
2006-09-19 17:17:29 +00:00
|
|
|
QRect ObjectRect::boundingRect(double xScale, double yScale) const
|
2005-08-30 13:24:29 +00:00
|
|
|
{
|
2007-01-02 17:05:49 +00:00
|
|
|
const QRectF &br = m_transformedPath.boundingRect();
|
2006-11-20 07:53:32 +00:00
|
|
|
|
2006-07-13 15:03:18 +00:00
|
|
|
return QRect((int)(br.left() * xScale), (int)(br.top() * yScale), (int)(br.width() * xScale), (int)(br.height() * yScale));
|
2005-08-30 13:24:29 +00:00
|
|
|
}
|
|
|
|
|
2006-11-20 07:53:32 +00:00
|
|
|
bool ObjectRect::contains(double x, double y, double, double) const
|
|
|
|
{
|
2007-01-02 17:05:49 +00:00
|
|
|
return m_transformedPath.contains(QPointF(x, y));
|
2006-11-20 07:53:32 +00:00
|
|
|
}
|
|
|
|
|
2012-09-08 15:06:02 +00:00
|
|
|
void ObjectRect::transform(const QTransform &matrix)
|
2006-11-20 07:53:32 +00:00
|
|
|
{
|
2007-01-02 17:05:49 +00:00
|
|
|
m_transformedPath = matrix.map(m_path);
|
2006-11-20 07:53:32 +00:00
|
|
|
}
|
|
|
|
|
2009-03-23 12:05:00 +00:00
|
|
|
double ObjectRect::distanceSqr(double x, double y, double xScale, double yScale) const
|
|
|
|
{
|
|
|
|
switch (m_objectType) {
|
|
|
|
case Action:
|
|
|
|
case Image: {
|
2013-06-23 17:19:25 +00:00
|
|
|
const QRectF &rect(m_transformedPath.boundingRect());
|
|
|
|
return NormalizedRect(rect.x(), rect.y(), rect.right(), rect.bottom()).distanceSqr(x, y, xScale, yScale);
|
|
|
|
}
|
2009-03-23 12:05:00 +00:00
|
|
|
case OAnnotation: {
|
2013-06-23 17:19:25 +00:00
|
|
|
return static_cast<Annotation *>(m_object)->d_func()->distanceSqr(x, y, xScale, yScale);
|
2009-03-23 12:05:00 +00:00
|
|
|
}
|
|
|
|
case SourceRef: {
|
|
|
|
const SourceRefObjectRect *sr = static_cast<const SourceRefObjectRect *>(this);
|
|
|
|
const NormalizedPoint &point = sr->m_point;
|
|
|
|
if (point.x == -1.0) {
|
2013-06-23 17:19:25 +00:00
|
|
|
return pow((y - point.y) * yScale, 2);
|
2009-03-23 12:05:00 +00:00
|
|
|
} else if (point.y == -1.0) {
|
2013-06-23 17:19:25 +00:00
|
|
|
return pow((x - point.x) * xScale, 2);
|
2009-03-23 12:05:00 +00:00
|
|
|
} else {
|
2013-06-23 17:19:25 +00:00
|
|
|
return pow((x - point.x) * xScale, 2) + pow((y - point.y) * yScale, 2);
|
2009-03-23 12:05:00 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-10 22:15:05 +00:00
|
|
|
}
|
2009-03-23 12:05:00 +00:00
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
2005-07-15 18:20:57 +00:00
|
|
|
ObjectRect::~ObjectRect()
|
|
|
|
{
|
2007-01-02 17:05:49 +00:00
|
|
|
if (!m_object)
|
2005-07-15 18:20:57 +00:00
|
|
|
return;
|
|
|
|
|
2007-04-20 12:37:12 +00:00
|
|
|
if (m_objectType == Action)
|
|
|
|
delete static_cast<Okular::Action *>(m_object);
|
2006-11-17 22:15:15 +00:00
|
|
|
else if (m_objectType == SourceRef)
|
2007-01-02 17:05:49 +00:00
|
|
|
delete static_cast<Okular::SourceReference *>(m_object);
|
2005-07-15 18:20:57 +00:00
|
|
|
else
|
2014-09-11 17:36:01 +00:00
|
|
|
qCDebug(OkularCoreDebug).nospace() << "Object deletion not implemented for type '" << m_objectType << "'.";
|
2005-07-15 18:20:57 +00:00
|
|
|
}
|
2006-09-19 17:17:29 +00:00
|
|
|
|
|
|
|
/** class AnnotationObjectRect **/
|
|
|
|
|
2007-01-02 17:05:49 +00:00
|
|
|
AnnotationObjectRect::AnnotationObjectRect(Annotation *annotation)
|
|
|
|
: ObjectRect(QPolygonF(), OAnnotation, annotation)
|
|
|
|
, m_annotation(annotation)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Annotation *AnnotationObjectRect::annotation() const
|
2006-09-19 17:17:29 +00:00
|
|
|
{
|
2007-01-02 17:05:49 +00:00
|
|
|
return m_annotation;
|
2006-09-19 17:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QRect AnnotationObjectRect::boundingRect(double xScale, double yScale) const
|
|
|
|
{
|
2012-12-16 18:35:04 +00:00
|
|
|
const QRect annotRect = AnnotationUtils::annotationGeometry(m_annotation, xScale, yScale);
|
|
|
|
const QPoint center = annotRect.center();
|
|
|
|
|
|
|
|
// Make sure that the rectangle has a minimum size, so that it's possible
|
|
|
|
// to click on it
|
|
|
|
const int minSize = 14;
|
|
|
|
const QRect minRect(center.x() - minSize / 2, center.y() - minSize / 2, minSize, minSize);
|
|
|
|
|
|
|
|
return annotRect | minRect;
|
2006-09-19 17:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool AnnotationObjectRect::contains(double x, double y, double xScale, double yScale) const
|
|
|
|
{
|
|
|
|
return boundingRect(xScale, yScale).contains((int)(x * xScale), (int)(y * yScale), false);
|
|
|
|
}
|
|
|
|
|
|
|
|
AnnotationObjectRect::~AnnotationObjectRect()
|
|
|
|
{
|
2006-09-21 08:45:36 +00:00
|
|
|
// the annotation pointer is kept elsewehere (in Page, most probably),
|
2006-09-19 17:17:29 +00:00
|
|
|
// so just release its pointer
|
2017-09-05 21:27:18 +00:00
|
|
|
m_object = nullptr;
|
2006-09-19 17:17:29 +00:00
|
|
|
}
|
|
|
|
|
2012-09-08 15:06:02 +00:00
|
|
|
void AnnotationObjectRect::transform(const QTransform &matrix)
|
2006-11-20 07:53:32 +00:00
|
|
|
{
|
2007-07-22 20:49:27 +00:00
|
|
|
m_annotation->d_func()->annotationTransform(matrix);
|
2006-11-20 07:53:32 +00:00
|
|
|
}
|
|
|
|
|
2006-11-17 22:15:15 +00:00
|
|
|
/** class SourceRefObjectRect **/
|
|
|
|
|
|
|
|
SourceRefObjectRect::SourceRefObjectRect(const NormalizedPoint &point, void *srcRef)
|
|
|
|
: ObjectRect(point.x, point.y, .0, .0, false, SourceRef, srcRef)
|
|
|
|
, m_point(point)
|
|
|
|
{
|
2009-03-23 12:05:00 +00:00
|
|
|
const double x = m_point.x < 0.0 ? 0.5 : m_point.x;
|
|
|
|
const double y = m_point.y < 0.0 ? 0.5 : m_point.y;
|
|
|
|
const QRectF rect(x - 2, y - 2, 5, 5);
|
|
|
|
m_path.addRect(rect);
|
|
|
|
|
|
|
|
m_transformedPath = m_path;
|
2006-11-17 22:15:15 +00:00
|
|
|
}
|
|
|
|
|
2009-03-23 12:05:00 +00:00
|
|
|
QRect SourceRefObjectRect::boundingRect(double xScale, double yScale) const
|
2006-11-17 22:15:15 +00:00
|
|
|
{
|
2009-03-23 12:05:00 +00:00
|
|
|
const double x = m_point.x < 0.0 ? 0.5 : m_point.x;
|
|
|
|
const double y = m_point.y < 0.0 ? 0.5 : m_point.y;
|
|
|
|
|
|
|
|
return QRect(x * xScale, y * yScale, 1, 1);
|
2006-11-17 22:15:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SourceRefObjectRect::contains(double x, double y, double xScale, double yScale) const
|
|
|
|
{
|
2009-03-23 12:05:00 +00:00
|
|
|
return distanceSqr(x, y, xScale, yScale) < (pow(7.0 / xScale, 2) + pow(7.0 / yScale, 2));
|
2006-11-17 22:15:15 +00:00
|
|
|
}
|
2019-01-28 21:08:24 +00:00
|
|
|
|
|
|
|
/** class NonOwningObjectRect **/
|
|
|
|
|
|
|
|
NonOwningObjectRect::NonOwningObjectRect(double left, double top, double right, double bottom, bool ellipse, ObjectType type, void *object)
|
|
|
|
: ObjectRect(left, top, right, bottom, ellipse, type, object)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NonOwningObjectRect::~NonOwningObjectRect()
|
|
|
|
{
|
|
|
|
// Set m_object so that ~ObjectRect() doesn't delete it
|
|
|
|
m_object = nullptr;
|
|
|
|
}
|