Okular

utils.cpp
1 /*
2  SPDX-FileCopyrightText: 2006 Luigi Toscano <[email protected]>
3  SPDX-FileCopyrightText: 2008 Pino Toscano <[email protected]>
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 
22 using namespace Okular;
23 
24 QRect Utils::rotateRect(const QRect &source, int width, int height, int orientation) // clazy:exclude=function-args-by-value TODO remove the & when we do a BIC change elsewhere
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 
47 QSizeF Utils::realDpi(QWidget *widgetOnScreen)
48 {
49  const QScreen *screen = widgetOnScreen && widgetOnScreen->window() && widgetOnScreen->window()->windowHandle() ? widgetOnScreen->window()->windowHandle()->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 
64 inline 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  const int width = image->width();
75  const int height = image->height();
76  const QRgb paperColor = SettingsCore::paperColor().rgb();
77  int left, top, bottom, right, x, y;
78 
79 #ifdef BBOX_DEBUG
80  QTime time;
81  time.start();
82 #endif
83 
84  // Scan pixels for top non-white
85  for (top = 0; top < height; ++top)
86  for (x = 0; x < width; ++x)
87  if (!isPaperColor(image->pixel(x, top), paperColor))
88  goto got_top;
89  return NormalizedRect(0, 0, 0, 0); // the image is blank
90 got_top:
91  left = right = x;
92 
93  // Scan pixels for bottom non-white
94  for (bottom = height - 1; bottom >= top; --bottom)
95  for (x = width - 1; x >= 0; --x)
96  if (!isPaperColor(image->pixel(x, bottom), paperColor))
97  goto got_bottom;
98  Q_ASSERT(0); // image changed?!
99 got_bottom:
100  if (x < left)
101  left = x;
102  if (x > right)
103  right = x;
104 
105  // Scan for leftmost and rightmost (we already found some bounds on these):
106  for (y = top; y <= bottom && (left > 0 || right < width - 1); ++y) {
107  for (x = 0; x < left; ++x)
108  if (!isPaperColor(image->pixel(x, y), paperColor))
109  left = x;
110  for (x = width - 1; x > right + 1; --x)
111  if (!isPaperColor(image->pixel(x, y), paperColor))
112  right = x;
113  }
114 
115  NormalizedRect bbox(QRect(left, top, (right - left + 1), (bottom - top + 1)), image->width(), image->height());
116 
117 #ifdef BBOX_DEBUG
118  qCDebug(OkularCoreDebug) << "Computed bounding box" << bbox << "in" << time.elapsed() << "ms";
119 #endif
120 
121  return bbox;
122 }
123 
124 void Okular::copyQIODevice(QIODevice *from, QIODevice *to)
125 {
126  QByteArray buffer(65536, '\0');
127  qint64 read = 0;
128  qint64 written = 0;
129  while ((read = from->read(buffer.data(), buffer.size())) > 0) {
130  written = to->write(buffer.constData(), read);
131  if (read != written)
132  break;
133  }
134 }
135 
136 QTransform Okular::buildRotationMatrix(Rotation rotation)
137 {
138  QTransform matrix;
139  matrix.rotate((int)rotation * 90);
140 
141  switch (rotation) {
142  case Rotation90:
143  matrix.translate(0, -1);
144  break;
145  case Rotation180:
146  matrix.translate(-1, -1);
147  break;
148  case Rotation270:
149  matrix.translate(-1, 0);
150  break;
151  default:;
152  }
153 
154  return matrix;
155 }
156 
157 /* kate: replace-tabs on; indent-width 4; */
Rotation
A rotation.
Definition: global.h:45
QWidget * window() const const
A NormalizedRect is a rectangle which can be defined by two NormalizedPoints.
Definition: area.h:189
int height() const const
int x() const const
int y() const const
Rotated 180 degrees clockwise.
Definition: global.h:48
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
global.h
Definition: action.h:16
QRgb pixel(int x, int y) const const
int elapsed() const const
QTransform & translate(qreal dx, qreal dy)
int width() const const
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
const char * constData() const const
qint64 read(char *data, qint64 maxSize)
Rotated 2700 degrees clockwise.
Definition: global.h:49
physicalDotsPerInchX
QWindow * windowHandle() const const
QTransform & rotate(qreal angle, Qt::Axis axis)
Rotated 90 degrees clockwise.
Definition: global.h:47
int width() const const
char * data()
physicalDotsPerInchY
qint64 write(const char *data, qint64 maxSize)
void start()
int height() const const
QScreen * screen() const const
int size() const const
static QSizeF realDpi(QWidget *widgetOnScreen)
Return the real DPI of the display containing given widget.
Definition: utils.cpp:47
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Dec 6 2021 22:32:18 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.