File indexing completed on 2024-05-12 15:56:58
0001 /* 0002 * SPDX-FileCopyrightText: 2000 Matthias Elter <elter@kde.org> 0003 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org> 0004 * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 #ifndef KISGLOBAL_H_ 0009 #define KISGLOBAL_H_ 0010 0011 #include <limits> 0012 0013 #include <KoConfig.h> 0014 #include "kis_assert.h" 0015 0016 #include <QPoint> 0017 #include <QPointF> 0018 0019 const quint8 quint8_MAX = std::numeric_limits<quint8>::max(); 0020 const quint16 quint16_MAX = std::numeric_limits<quint16>::max(); 0021 0022 const qint16 qint16_MIN = std::numeric_limits<qint16>::min(); 0023 const qint16 qint16_MAX = std::numeric_limits<qint16>::max(); 0024 const qint32 qint32_MAX = std::numeric_limits<qint32>::max(); 0025 const qint32 qint32_MIN = std::numeric_limits<qint32>::min(); 0026 0027 const quint8 MAX_SELECTED = std::numeric_limits<quint8>::max(); 0028 const quint8 MIN_SELECTED = std::numeric_limits<quint8>::min(); 0029 const quint8 SELECTION_THRESHOLD = 1; 0030 0031 enum OutlineStyle { 0032 OUTLINE_NONE = 0, 0033 OUTLINE_CIRCLE, 0034 OUTLINE_FULL, 0035 OUTLINE_TILT, 0036 0037 N_OUTLINE_STYLE_SIZE 0038 }; 0039 0040 enum CursorStyle { 0041 CURSOR_STYLE_NO_CURSOR = 0, 0042 CURSOR_STYLE_TOOLICON, 0043 CURSOR_STYLE_POINTER, 0044 CURSOR_STYLE_SMALL_ROUND, 0045 CURSOR_STYLE_CROSSHAIR, 0046 CURSOR_STYLE_TRIANGLE_RIGHTHANDED, 0047 CURSOR_STYLE_TRIANGLE_LEFTHANDED, 0048 CURSOR_STYLE_BLACK_PIXEL, 0049 CURSOR_STYLE_WHITE_PIXEL, 0050 CURSOR_STYLE_ERASER, 0051 0052 N_CURSOR_STYLE_SIZE 0053 }; 0054 0055 enum OldCursorStyle { 0056 OLD_CURSOR_STYLE_TOOLICON = 0, 0057 OLD_CURSOR_STYLE_CROSSHAIR = 1, 0058 OLD_CURSOR_STYLE_POINTER = 2, 0059 0060 OLD_CURSOR_STYLE_OUTLINE = 3, 0061 0062 OLD_CURSOR_STYLE_NO_CURSOR = 4, 0063 OLD_CURSOR_STYLE_SMALL_ROUND = 5, 0064 0065 OLD_CURSOR_STYLE_OUTLINE_CENTER_DOT = 6, 0066 OLD_CURSOR_STYLE_OUTLINE_CENTER_CROSS = 7, 0067 0068 OLD_CURSOR_STYLE_TRIANGLE_RIGHTHANDED = 8, 0069 OLD_CURSOR_STYLE_TRIANGLE_LEFTHANDED = 9, 0070 0071 OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_RIGHTHANDED = 10, 0072 OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_LEFTHANDED = 11 0073 }; 0074 0075 const double PRESSURE_MIN = 0.0; 0076 const double PRESSURE_MAX = 1.0; 0077 const double PRESSURE_DEFAULT = PRESSURE_MAX; 0078 const double PRESSURE_THRESHOLD = 5.0 / 255.0; 0079 0080 // copy of lcms.h 0081 #define INTENT_PERCEPTUAL 0 0082 #define INTENT_RELATIVE_COLORIMETRIC 1 0083 #define INTENT_SATURATION 2 0084 #define INTENT_ABSOLUTE_COLORIMETRIC 3 0085 0086 #include <cmath> 0087 0088 #ifndef M_PI 0089 #define M_PI 3.14159265358979323846 0090 #endif 0091 0092 // Name of the property in the KisApplication that contains the name 0093 // of the current style, even if there is a stylesheet applied 0094 constexpr const char *currentUnderlyingStyleNameProperty = "currentUnderlyingStyleName"; 0095 0096 // converts \p a to [0, 2 * M_PI) range 0097 template<typename T> 0098 typename std::enable_if<std::is_floating_point<T>::value, T>::type 0099 normalizeAngle(T a) { 0100 if (a < T(0.0)) { 0101 a = T(2 * M_PI) + std::fmod(a, T(2 * M_PI)); 0102 } 0103 0104 return a >= T(2 * M_PI) ? std::fmod(a, T(2 * M_PI)) : a; 0105 } 0106 0107 // converts \p a to [0, 360.0) range 0108 template<typename T> 0109 typename std::enable_if<std::is_floating_point<T>::value, T>::type 0110 normalizeAngleDegrees(T a) { 0111 if (a < T(0.0)) { 0112 a = T(360.0) + std::fmod(a, T(360.0)); 0113 } 0114 0115 return a >= T(360.0) ? std::fmod(a, T(360.0)) : a; 0116 } 0117 0118 inline qreal shortestAngularDistance(qreal a, qreal b) { 0119 qreal dist = fmod(qAbs(a - b), 2 * M_PI); 0120 if (dist > M_PI) dist = 2 * M_PI - dist; 0121 0122 return dist; 0123 } 0124 0125 inline qreal incrementInDirection(qreal a, qreal inc, qreal direction) { 0126 qreal b1 = a + inc; 0127 qreal b2 = a - inc; 0128 0129 qreal d1 = shortestAngularDistance(b1, direction); 0130 qreal d2 = shortestAngularDistance(b2, direction); 0131 0132 return d1 < d2 ? b1 : b2; 0133 } 0134 0135 inline qreal bisectorAngle(qreal a, qreal b) { 0136 const qreal diff = shortestAngularDistance(a, b); 0137 return incrementInDirection(a, 0.5 * diff, b); 0138 } 0139 0140 template<typename PointType> 0141 inline PointType snapToClosestAxis(PointType P) { 0142 if (qAbs(P.x()) < qAbs(P.y())) { 0143 P.setX(0); 0144 } else { 0145 P.setY(0); 0146 } 0147 return P; 0148 } 0149 0150 template<typename T> 0151 inline T pow2(const T& x) { 0152 return x * x; 0153 } 0154 0155 template<typename T> 0156 inline T pow3(const T& x) { 0157 return x * x * x; 0158 } 0159 0160 template<typename T> 0161 inline T kisDegreesToRadians(T degrees) { 0162 return degrees * M_PI / 180.0; 0163 } 0164 0165 template<typename T> 0166 inline T kisRadiansToDegrees(T radians) { 0167 return radians * 180.0 / M_PI; 0168 } 0169 0170 template<class T, typename U> 0171 inline T kisGrowRect(const T &rect, U offset) { 0172 return rect.adjusted(-offset, -offset, offset, offset); 0173 } 0174 0175 inline qreal kisDistance(const QPointF &pt1, const QPointF &pt2) { 0176 return std::sqrt(pow2(pt1.x() - pt2.x()) + pow2(pt1.y() - pt2.y())); 0177 } 0178 0179 inline qreal kisSquareDistance(const QPointF &pt1, const QPointF &pt2) { 0180 return pow2(pt1.x() - pt2.x()) + pow2(pt1.y() - pt2.y()); 0181 } 0182 0183 #include <QLineF> 0184 0185 inline qreal kisDistanceToLine(const QPointF &m, const QLineF &line) 0186 { 0187 const QPointF &p1 = line.p1(); 0188 const QPointF &p2 = line.p2(); 0189 0190 qreal distance = 0; 0191 0192 if (qFuzzyCompare(p1.x(), p2.x())) { 0193 distance = qAbs(m.x() - p2.x()); 0194 } else if (qFuzzyCompare(p1.y(), p2.y())) { 0195 distance = qAbs(m.y() - p2.y()); 0196 } else { 0197 qreal A = 1; 0198 qreal B = - (p1.x() - p2.x()) / (p1.y() - p2.y()); 0199 qreal C = - p1.x() - B * p1.y(); 0200 0201 distance = qAbs(A * m.x() + B * m.y() + C) / std::sqrt(pow2(A) + pow2(B)); 0202 } 0203 0204 return distance; 0205 } 0206 0207 inline QPointF kisProjectOnVector(const QPointF &base, const QPointF &v) 0208 { 0209 const qreal prod = base.x() * v.x() + base.y() * v.y(); 0210 const qreal lengthSq = pow2(base.x()) + pow2(base.y()); 0211 qreal coeff = prod / lengthSq; 0212 0213 return coeff * base; 0214 } 0215 0216 #include <QRect> 0217 0218 inline QRect kisEnsureInRect(QRect rc, const QRect &bounds) 0219 { 0220 if(rc.right() > bounds.right()) { 0221 rc.translate(bounds.right() - rc.right(), 0); 0222 } 0223 0224 if(rc.left() < bounds.left()) { 0225 rc.translate(bounds.left() - rc.left(), 0); 0226 } 0227 0228 if(rc.bottom() > bounds.bottom()) { 0229 rc.translate(0, bounds.bottom() - rc.bottom()); 0230 } 0231 0232 if(rc.top() < bounds.top()) { 0233 rc.translate(0, bounds.top() - rc.top()); 0234 } 0235 0236 return rc; 0237 } 0238 0239 inline QRectF kisTrimLeft( int width, QRectF &toTakeFrom) 0240 { 0241 QPointF trimmedOrigin = toTakeFrom.topLeft(); 0242 QSize trimmedSize = QSize(width, toTakeFrom.height()); 0243 toTakeFrom.setWidth(toTakeFrom.width() - width); 0244 toTakeFrom.translate(width, 0); 0245 return QRectF(trimmedOrigin, trimmedSize); 0246 } 0247 0248 inline QRect kisTrimLeft( int width, QRect &toTakeFrom) 0249 { 0250 QRectF converted = QRectF(toTakeFrom); 0251 QRectF toReturn = kisTrimLeft(width, converted); 0252 toTakeFrom = converted.toAlignedRect(); 0253 return toReturn.toAlignedRect(); 0254 } 0255 0256 inline QRectF kisTrimTop( int height, QRectF& toTakeFrom) 0257 { 0258 QPointF trimmedOrigin = toTakeFrom.topLeft(); 0259 QSize trimmedSize = QSize(toTakeFrom.width(), height); 0260 toTakeFrom.setHeight(toTakeFrom.height() - height); 0261 toTakeFrom.translate(0, height); 0262 return QRectF(trimmedOrigin, trimmedSize); 0263 } 0264 0265 inline QRect kisTrimTop( int height, QRect& toTakeFrom) 0266 { 0267 QRectF converted = QRectF(toTakeFrom); 0268 QRectF toReturn = kisTrimTop(height, converted); 0269 toTakeFrom = converted.toAlignedRect(); 0270 return toReturn.toAlignedRect(); 0271 } 0272 0273 #include "kis_pointer_utils.h" 0274 0275 /** 0276 * A special wrapper object that converts Qt-style mutexes and locks 0277 * into an object that supports Std's (and Boost's) "Lockable" 0278 * concept. Basically, it converts tryLock() into try_lock() to comply 0279 * with the syntax. 0280 */ 0281 0282 template <class T> 0283 struct StdLockableWrapper { 0284 StdLockableWrapper(T *lock) : m_lock(lock) {} 0285 0286 void lock() { 0287 m_lock->lock(); 0288 } 0289 0290 bool try_lock() { 0291 return m_lock->tryLock(); 0292 } 0293 0294 void unlock() { 0295 m_lock->unlock(); 0296 } 0297 0298 private: 0299 T *m_lock; 0300 }; 0301 0302 #endif // KISGLOBAL_H_ 0303