File indexing completed on 2024-05-19 04:25:04

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 
0141 
0142 
0143 template<typename T>
0144 inline T pow2(const T& x) {
0145     return x * x;
0146 }
0147 
0148 template<typename T>
0149 inline T pow3(const T& x) {
0150     return x * x * x;
0151 }
0152 
0153 template<typename T>
0154 inline T kisDegreesToRadians(T degrees) {
0155     return degrees * M_PI / 180.0;
0156 }
0157 
0158 template<typename T>
0159 inline T kisRadiansToDegrees(T radians) {
0160     return radians * 180.0 / M_PI;
0161 }
0162 
0163 template<class T, typename U>
0164 inline T kisGrowRect(const T &rect, U offset) {
0165     return rect.adjusted(-offset, -offset, offset, offset);
0166 }
0167 
0168 inline qreal kisDistance(const QPointF &pt1, const QPointF &pt2) {
0169     return std::sqrt(pow2(pt1.x() - pt2.x()) + pow2(pt1.y() - pt2.y()));
0170 }
0171 
0172 inline qreal kisSquareDistance(const QPointF &pt1, const QPointF &pt2) {
0173     return pow2(pt1.x() - pt2.x()) + pow2(pt1.y() - pt2.y());
0174 }
0175 
0176 template<typename PointType>
0177 inline PointType snapToClosestAxis(PointType P) {
0178     if (qAbs(P.x()) < qAbs(P.y())) {
0179         P.setX(0);
0180     } else {
0181         P.setY(0);
0182     }
0183     return P;
0184 }
0185 
0186 template<typename PointType>
0187 inline PointType snapToClosestNiceAngle(PointType point, PointType startPoint, qreal angle = (2 * M_PI) / 24) {
0188     // default angle = 15 degrees
0189 
0190     const QPointF lineVector = point - startPoint;
0191     qreal lineAngle = std::atan2(lineVector.y(), lineVector.x());
0192 
0193     if (lineAngle < 0) {
0194         lineAngle += 2 * M_PI;
0195     }
0196 
0197     const quint32 constrainedLineIndex = static_cast<quint32>((lineAngle / angle) + 0.5);
0198     const qreal constrainedLineAngle = constrainedLineIndex * angle;
0199 
0200     const qreal lineLength = kisDistance(lineVector, QPointF());
0201 
0202     const QPointF constrainedLineVector(lineLength * std::cos(constrainedLineAngle), lineLength * std::sin(constrainedLineAngle));
0203 
0204     const QPointF result = startPoint + constrainedLineVector;
0205 
0206     return result;
0207 }
0208 
0209 
0210 #include <QLineF>
0211 
0212 inline qreal kisDistanceToLine(const QPointF &m, const QLineF &line)
0213 {
0214     const QPointF &p1 = line.p1();
0215     const QPointF &p2 = line.p2();
0216 
0217     qreal distance = 0;
0218 
0219     if (qFuzzyCompare(p1.x(), p2.x())) {
0220         distance = qAbs(m.x() - p2.x());
0221     } else if (qFuzzyCompare(p1.y(), p2.y())) {
0222         distance = qAbs(m.y() - p2.y());
0223     } else {
0224         qreal A = 1;
0225         qreal B = - (p1.x() - p2.x()) / (p1.y() - p2.y());
0226         qreal C = - p1.x() - B * p1.y();
0227 
0228         distance = qAbs(A * m.x() + B * m.y() + C) / std::sqrt(pow2(A) + pow2(B));
0229     }
0230 
0231     return distance;
0232 }
0233 
0234 inline QPointF kisProjectOnVector(const QPointF &base, const QPointF &v)
0235 {
0236     const qreal prod = base.x() * v.x() + base.y() * v.y();
0237     const qreal lengthSq = pow2(base.x()) + pow2(base.y());
0238     qreal coeff = prod / lengthSq;
0239 
0240     return coeff * base;
0241 }
0242 
0243 #include <QRect>
0244 
0245 inline QRect kisEnsureInRect(QRect rc, const QRect &bounds)
0246 {
0247     if(rc.right() > bounds.right()) {
0248         rc.translate(bounds.right() - rc.right(), 0);
0249     }
0250 
0251     if(rc.left() < bounds.left()) {
0252         rc.translate(bounds.left() - rc.left(), 0);
0253     }
0254 
0255     if(rc.bottom() > bounds.bottom()) {
0256         rc.translate(0, bounds.bottom() - rc.bottom());
0257     }
0258 
0259     if(rc.top() < bounds.top()) {
0260         rc.translate(0, bounds.top() - rc.top());
0261     }
0262 
0263     return rc;
0264 }
0265 
0266 inline QRectF kisTrimLeft( int width, QRectF &toTakeFrom)
0267 {
0268     QPointF trimmedOrigin = toTakeFrom.topLeft();
0269     QSize trimmedSize = QSize(width, toTakeFrom.height());
0270     toTakeFrom.setWidth(toTakeFrom.width() - width);
0271     toTakeFrom.translate(width, 0);
0272     return QRectF(trimmedOrigin, trimmedSize);
0273 }
0274 
0275 inline QRect kisTrimLeft( int width, QRect &toTakeFrom)
0276 {
0277     QRectF converted = QRectF(toTakeFrom);
0278     QRectF toReturn = kisTrimLeft(width, converted);
0279     toTakeFrom = converted.toAlignedRect();
0280     return toReturn.toAlignedRect();
0281 }
0282 
0283 inline QRectF kisTrimTop( int height, QRectF& toTakeFrom)
0284 {
0285     QPointF trimmedOrigin = toTakeFrom.topLeft();
0286     QSize trimmedSize = QSize(toTakeFrom.width(), height);
0287     toTakeFrom.setHeight(toTakeFrom.height() - height);
0288     toTakeFrom.translate(0, height);
0289     return QRectF(trimmedOrigin, trimmedSize);
0290 }
0291 
0292 inline QRect kisTrimTop( int height, QRect& toTakeFrom)
0293 {
0294     QRectF converted = QRectF(toTakeFrom);
0295     QRectF toReturn = kisTrimTop(height, converted);
0296     toTakeFrom = converted.toAlignedRect();
0297     return toReturn.toAlignedRect();
0298 }
0299 
0300 #include "kis_pointer_utils.h"
0301 #include <type_traits>
0302 
0303 // Makes compilers happy because Linux and macOS differ on how they define
0304 // quint64 (unsigned long long) vs. size_t (unsigned long (int)).
0305 template <typename T>
0306 inline T nextPowerOfTwo(T v)
0307 {
0308     static_assert(std::is_integral<T>::value, "Value has to be an integral number");
0309     using base_type = typename std::conditional<sizeof(T) == sizeof(quint64), quint64, quint32>::type;
0310     using common_type = typename std::conditional<std::is_signed<T>::value, typename std::make_signed<base_type>::type, typename std::make_unsigned<base_type>::type>::type;
0311     return static_cast<T>(qNextPowerOfTwo(static_cast<common_type>(v)));
0312 }
0313 
0314 #endif // KISGLOBAL_H_
0315