File indexing completed on 2024-04-28 04:32:48

0001 /*
0002     SPDX-FileCopyrightText: 2006 Luigi Toscano <luigi.toscano@tiscali.it>
0003     SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "utils.h"
0009 #include "utils_p.h"
0010 
0011 #include "debug_p.h"
0012 #include "settings_core.h"
0013 
0014 #include <QApplication>
0015 #include <QIODevice>
0016 #include <QImage>
0017 #include <QRect>
0018 #include <QScreen>
0019 #include <QWidget>
0020 #include <QWindow>
0021 
0022 using namespace Okular;
0023 
0024 QRect Utils::rotateRect(const QRect source, int width, int height, int orientation)
0025 {
0026     QRect ret;
0027 
0028     // adapt the coordinates of the boxes to the rotation
0029     switch (orientation) {
0030     case 1:
0031         ret = QRect(width - source.y() - source.height(), source.x(), source.height(), source.width());
0032         break;
0033     case 2:
0034         ret = QRect(width - source.x() - source.width(), height - source.y() - source.height(), source.width(), source.height());
0035         break;
0036     case 3:
0037         ret = QRect(source.y(), height - source.x() - source.width(), source.height(), source.width());
0038         break;
0039     case 0:  // no modifications
0040     default: // other cases
0041         ret = source;
0042     }
0043 
0044     return ret;
0045 }
0046 
0047 QSizeF Utils::realDpi(const QWindow *windowOnScreen)
0048 {
0049     const QScreen *screen = windowOnScreen ? windowOnScreen->screen() : qGuiApp->primaryScreen();
0050 
0051     if (screen) {
0052         const QSizeF res(screen->physicalDotsPerInchX(), screen->physicalDotsPerInchY());
0053         if (res.width() > 0 && res.height() > 0) {
0054             if (qAbs(res.width() - res.height()) / qMin(res.height(), res.width()) < 0.15) {
0055                 return res;
0056             } else {
0057                 qCDebug(OkularCoreDebug) << "QScreen calculation returned a non square dpi." << res << ". Falling back";
0058             }
0059         }
0060     }
0061     return QSizeF(72, 72);
0062 }
0063 
0064 inline static bool isPaperColor(QRgb argb, QRgb paperColor)
0065 {
0066     return (argb & 0xFFFFFF) == (paperColor & 0xFFFFFF); // ignore alpha
0067 }
0068 
0069 NormalizedRect Utils::imageBoundingBox(const QImage *image)
0070 {
0071     if (!image) {
0072         return NormalizedRect();
0073     }
0074 
0075     const int width = image->width();
0076     const int height = image->height();
0077     const QRgb paperColor = SettingsCore::paperColor().rgb();
0078     int left, top, bottom, right, x, y;
0079 
0080 #ifdef BBOX_DEBUG
0081     QTime time;
0082     time.start();
0083 #endif
0084 
0085     // Scan pixels for top non-white
0086     for (top = 0; top < height; ++top) {
0087         for (x = 0; x < width; ++x) {
0088             if (!isPaperColor(image->pixel(x, top), paperColor)) {
0089                 goto got_top;
0090             }
0091         }
0092     }
0093     return NormalizedRect(0, 0, 0, 0); // the image is blank
0094 got_top:
0095     left = right = x;
0096 
0097     // Scan pixels for bottom non-white
0098     for (bottom = height - 1; bottom >= top; --bottom) {
0099         for (x = width - 1; x >= 0; --x) {
0100             if (!isPaperColor(image->pixel(x, bottom), paperColor)) {
0101                 goto got_bottom;
0102             }
0103         }
0104     }
0105     Q_ASSERT(0); // image changed?!
0106 got_bottom:
0107     if (x < left) {
0108         left = x;
0109     }
0110     if (x > right) {
0111         right = x;
0112     }
0113 
0114     // Scan for leftmost and rightmost (we already found some bounds on these):
0115     for (y = top; y <= bottom && (left > 0 || right < width - 1); ++y) {
0116         for (x = 0; x < left; ++x) {
0117             if (!isPaperColor(image->pixel(x, y), paperColor)) {
0118                 left = x;
0119             }
0120         }
0121         for (x = width - 1; x > right + 1; --x) {
0122             if (!isPaperColor(image->pixel(x, y), paperColor)) {
0123                 right = x;
0124             }
0125         }
0126     }
0127 
0128     NormalizedRect bbox(QRect(left, top, (right - left + 1), (bottom - top + 1)), image->width(), image->height());
0129 
0130 #ifdef BBOX_DEBUG
0131     qCDebug(OkularCoreDebug) << "Computed bounding box" << bbox << "in" << time.elapsed() << "ms";
0132 #endif
0133 
0134     return bbox;
0135 }
0136 
0137 void Okular::copyQIODevice(QIODevice *from, QIODevice *to)
0138 {
0139     QByteArray buffer(65536, '\0');
0140     qint64 read = 0;
0141     qint64 written = 0;
0142     while ((read = from->read(buffer.data(), buffer.size())) > 0) {
0143         written = to->write(buffer.constData(), read);
0144         if (read != written) {
0145             break;
0146         }
0147     }
0148 }
0149 
0150 QTransform Okular::buildRotationMatrix(Rotation rotation)
0151 {
0152     QTransform matrix;
0153     matrix.rotate((int)rotation * 90);
0154 
0155     switch (rotation) {
0156     case Rotation90:
0157         matrix.translate(0, -1);
0158         break;
0159     case Rotation180:
0160         matrix.translate(-1, -1);
0161         break;
0162     case Rotation270:
0163         matrix.translate(-1, 0);
0164         break;
0165     default:;
0166     }
0167 
0168     return matrix;
0169 }
0170 
0171 /* kate: replace-tabs on; indent-width 4; */