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