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; */