Okular

utils.cpp
1/*
2 SPDX-FileCopyrightText: 2006 Luigi Toscano <luigi.toscano@tiscali.it>
3 SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6*/
7
8#include "utils.h"
9#include "utils_p.h"
10
11#include "debug_p.h"
12#include "settings_core.h"
13
14#include <QApplication>
15#include <QIODevice>
16#include <QImage>
17#include <QRect>
18#include <QScreen>
19#include <QWidget>
20#include <QWindow>
21
22using namespace Okular;
23
24QRect Utils::rotateRect(const QRect source, int width, int height, int orientation)
25{
26 QRect ret;
27
28 // adapt the coordinates of the boxes to the rotation
29 switch (orientation) {
30 case 1:
31 ret = QRect(width - source.y() - source.height(), source.x(), source.height(), source.width());
32 break;
33 case 2:
34 ret = QRect(width - source.x() - source.width(), height - source.y() - source.height(), source.width(), source.height());
35 break;
36 case 3:
37 ret = QRect(source.y(), height - source.x() - source.width(), source.height(), source.width());
38 break;
39 case 0: // no modifications
40 default: // other cases
41 ret = source;
42 }
43
44 return ret;
45}
46
47QSizeF Utils::realDpi(const QWindow *windowOnScreen)
48{
49 const QScreen *screen = windowOnScreen ? windowOnScreen->screen() : qGuiApp->primaryScreen();
50
51 if (screen) {
52 const QSizeF res(screen->physicalDotsPerInchX(), screen->physicalDotsPerInchY());
53 if (res.width() > 0 && res.height() > 0) {
54 if (qAbs(res.width() - res.height()) / qMin(res.height(), res.width()) < 0.15) {
55 return res;
56 } else {
57 qCDebug(OkularCoreDebug) << "QScreen calculation returned a non square dpi." << res << ". Falling back";
58 }
59 }
60 }
61 return QSizeF(72, 72);
62}
63
64inline static bool isPaperColor(QRgb argb, QRgb paperColor)
65{
66 return (argb & 0xFFFFFF) == (paperColor & 0xFFFFFF); // ignore alpha
67}
68
70{
71 if (!image) {
72 return NormalizedRect();
73 }
74
75 const int width = image->width();
76 const int height = image->height();
77 const QRgb paperColor = SettingsCore::paperColor().rgb();
78 int left, top, bottom, right, x, y;
79
80#ifdef BBOX_DEBUG
81 QTime time;
82 time.start();
83#endif
84
85 // Scan pixels for top non-white
86 for (top = 0; top < height; ++top) {
87 for (x = 0; x < width; ++x) {
88 if (!isPaperColor(image->pixel(x, top), paperColor)) {
89 goto got_top;
90 }
91 }
92 }
93 return NormalizedRect(0, 0, 0, 0); // the image is blank
94got_top:
95 left = right = x;
96
97 // Scan pixels for bottom non-white
98 for (bottom = height - 1; bottom >= top; --bottom) {
99 for (x = width - 1; x >= 0; --x) {
100 if (!isPaperColor(image->pixel(x, bottom), paperColor)) {
101 goto got_bottom;
102 }
103 }
104 }
105 Q_ASSERT(0); // image changed?!
106got_bottom:
107 if (x < left) {
108 left = x;
109 }
110 if (x > right) {
111 right = x;
112 }
113
114 // Scan for leftmost and rightmost (we already found some bounds on these):
115 for (y = top; y <= bottom && (left > 0 || right < width - 1); ++y) {
116 for (x = 0; x < left; ++x) {
117 if (!isPaperColor(image->pixel(x, y), paperColor)) {
118 left = x;
119 }
120 }
121 for (x = width - 1; x > right + 1; --x) {
122 if (!isPaperColor(image->pixel(x, y), paperColor)) {
123 right = x;
124 }
125 }
126 }
127
128 NormalizedRect bbox(QRect(left, top, (right - left + 1), (bottom - top + 1)), image->width(), image->height());
129
130#ifdef BBOX_DEBUG
131 qCDebug(OkularCoreDebug) << "Computed bounding box" << bbox << "in" << time.elapsed() << "ms";
132#endif
133
134 return bbox;
135}
136
137void Okular::copyQIODevice(QIODevice *from, QIODevice *to)
138{
139 QByteArray buffer(65536, '\0');
140 qint64 read = 0;
141 qint64 written = 0;
142 while ((read = from->read(buffer.data(), buffer.size())) > 0) {
143 written = to->write(buffer.constData(), read);
144 if (read != written) {
145 break;
146 }
147 }
148}
149
150QTransform Okular::buildRotationMatrix(Rotation rotation)
151{
152 QTransform matrix;
153 matrix.rotate((int)rotation * 90);
154
155 switch (rotation) {
156 case Rotation90:
157 matrix.translate(0, -1);
158 break;
159 case Rotation180:
160 matrix.translate(-1, -1);
161 break;
162 case Rotation270:
163 matrix.translate(-1, 0);
164 break;
165 default:;
166 }
167
168 return matrix;
169}
170
171/* kate: replace-tabs on; indent-width 4; */
A NormalizedRect is a rectangle which can be defined by two NormalizedPoints.
Definition area.h:189
static QRect rotateRect(const QRect source, int width, int height, int orientation)
Rotate the rect source in the area width x height with the specified orientation .
Definition utils.cpp:24
static QSizeF realDpi(const QWindow *windowOnScreen)
Return the real DPI of the display containing given window.
Definition utils.cpp:47
static NormalizedRect imageBoundingBox(const QImage *image)
Compute the smallest rectangle that contains all non-white pixels in image), in normalized [0,...
Definition utils.cpp:69
global.h
Definition action.h:17
Rotation
A rotation.
Definition global.h:46
@ Rotation270
Rotated 2700 degrees clockwise.
Definition global.h:50
@ Rotation90
Rotated 90 degrees clockwise.
Definition global.h:48
@ Rotation180
Rotated 180 degrees clockwise.
Definition global.h:49
int height() const const
QRgb pixel(const QPoint &position) const const
int width() const const
QByteArray read(qint64 maxSize)
qint64 write(const QByteArray &data)
int height() const const
int width() const const
int x() const const
int y() const const
physicalDotsPerInchX
physicalDotsPerInchY
qreal height() const const
qreal width() const const
QTransform & rotate(qreal a, Qt::Axis axis)
QTransform & translate(qreal dx, qreal dy)
QScreen * screen() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:35 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.