Pencil2D Animation
Download Community News Docs Contribute
  • Overview
  • Articles
  • Code
  •  
  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
  • File List
Loading...
Searching...
No Matches
  • core_lib
  • src
  • util
util.cpp
1/*
2
3Pencil2D - Traditional Animation Software
4Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5Copyright (C) 2012-2020 Matthew Chiawen Chang
6
7This program is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public License
9as published by the Free Software Foundation; version 2 of the License.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16*/
17#include "util.h"
18#include <QAbstractSpinBox>
19#include <QApplication>
20#include <QDir>
21#include <QFileInfo>
22#include <QStandardPaths>
23
24static inline bool clipLineToEdge(qreal& t0, qreal& t1, qreal p, qreal q)
25{
26 if (p < 0) { // Line entering the clipping window
27 t0 = qMax(t0, q / p);
28 return t0 < t1;
29 }
30 if (p > 0) { // Line leaving the clipping window
31 t1 = qMin(t1, q / p);
32 return t0 < t1;
33 }
34 return q >= 0;
35}
36
37QLineF clipLine(const QLineF& line, const QRect& clip, qreal t0, qreal t1)
38{
39 int left = clip.left(), right = left + clip.width(), top = clip.top(), bottom = top + clip.height();
40 qreal x1 = line.x1(), x2 = line.x2(), dx = line.dx(), y1 = line.y1(), y2 = line.y2(), dy = line.dy();
41
42 if ((t0 == 0 && t1 == 1 && ((x1 < left && x2 < left) ||
43 (x1 > right && x2 > right) ||
44 (y1 < top && y2 < top) ||
45 (y1 > bottom && y2 > bottom))) ||
46 !clipLineToEdge(t0, t1, -dx, x1 - left) ||
47 !clipLineToEdge(t0, t1, dx, right - x1) ||
48 !clipLineToEdge(t0, t1, -dy, y1 - top) ||
49 !clipLineToEdge(t0, t1, dy, bottom - y1)) {
50 return {};
51 }
52
53 Q_ASSERT(t0 < t1);
54 return {line.x1() + line.dx() * t0,
55 line.y1() + line.dy() * t0,
56 line.x1() + line.dx() * t1,
57 line.y1() + line.dy() * t1};
58}
59
60void clearFocusOnFinished(QAbstractSpinBox *spinBox)
61{
62 QObject::connect(spinBox, &QAbstractSpinBox::editingFinished, spinBox, &QAbstractSpinBox::clearFocus);
63}
64
65QString ffprobeLocation()
66{
67#ifdef _WIN32
68 return QApplication::applicationDirPath() + "/plugins/ffprobe.exe";
69#elif __APPLE__
70 return QApplication::applicationDirPath() + "/plugins/ffprobe";
71#else
72 QString ffprobePath = QStandardPaths::findExecutable(
73 "ffprobe",
74 QStringList()
75 << QApplication::applicationDirPath() + "/plugins"
76 << QApplication::applicationDirPath() + "/../plugins" // linuxdeployqt in FHS-like mode
77 );
78 if (!ffprobePath.isEmpty())
79 {
80 return ffprobePath;
81 }
82 return QStandardPaths::findExecutable("ffprobe"); // ffprobe is a standalone project.
83#endif
84}
85
86QString ffmpegLocation()
87{
88#ifdef _WIN32
89 return QApplication::applicationDirPath() + "/plugins/ffmpeg.exe";
90#elif __APPLE__
91 return QApplication::applicationDirPath() + "/plugins/ffmpeg";
92#else
93 QString ffmpegPath = QStandardPaths::findExecutable(
94 "ffmpeg",
95 QStringList()
96 << QApplication::applicationDirPath() + "/plugins"
97 << QApplication::applicationDirPath() + "/../plugins" // linuxdeployqt in FHS-like mode
98 );
99 if (!ffmpegPath.isEmpty())
100 {
101 return ffmpegPath;
102 }
103 return QStandardPaths::findExecutable("ffmpeg"); // ffmpeg is a standalone project.
104#endif
105}
106
107quint64 imageSize(const QImage& img)
108{
109#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
110 return img.sizeInBytes();
111#else
112 return img.byteCount();
113#endif
114}
115
116QString uniqueString(int len)
117{
118 static const char alphanum[] = "0123456789abcdefghijklmnopqrstuvwxyz";
119 const int alphanumLen = sizeof(alphanum);
120
121 if (len > 128) len = 128;
122
123 char s[128 + 1];
124 for (int i = 0; i < len; ++i)
125 {
126 s[i] = alphanum[rand() % (alphanumLen - 1)];
127 }
128 s[len] = 0;
129 return QString::fromUtf8(s);
130}
131
132QString validateDataPath(QString filePath, QString dataDirPath)
133{
134 // Make sure src path is relative
135 if (!QFileInfo(filePath).isRelative()) return QString();
136
137 QFileInfo fi(dataDirPath, filePath);
138 // Recursively resolve symlinks
139 QString canonicalPath = fi.canonicalFilePath();
140
141 QDir dataDir(dataDirPath);
142 // Resolve symlinks in data dir path so it can be compared against file paths with resolved symlinks
143 if (dataDir.exists())
144 {
145 dataDir.setPath(dataDir.canonicalPath());
146 }
147 // Iterate over parent directories of the file path to see if one of them equals the data directory
148 if (canonicalPath.isEmpty())
149 {
150 // File does not exist, use absolute path and attempt to resolve symlinks again for each parent directory
151 fi.setFile(fi.absoluteFilePath());
152 QDir ancestor(fi.absoluteFilePath());
153 while (ancestor != dataDir) {
154 if (ancestor.isRoot())
155 {
156 // Reached root directory without finding data dir
157 return QString();
158 }
159 QDir newAncestor = QFileInfo(ancestor.absolutePath()).dir();
160 if (newAncestor.exists())
161 {
162 // Resolve directory symlinks
163 newAncestor.setPath(newAncestor.canonicalPath());
164 }
165 ancestor = newAncestor;
166 }
167 // One of the parent directories of filePath matches dataDir
168 return fi.absoluteFilePath();
169 }
170 else
171 {
172 // File exists and all symlinks have been resolved in canonicalPath so no further attempts to resolve symlinks are necessary
173 fi.setFile(canonicalPath);
174 QDir ancestor = fi.dir();
175 while (ancestor != dataDir)
176 {
177 if (ancestor.isRoot()) {
178 // Data dir was not found in ancestors of the src path
179 return QString();
180 }
181 ancestor = QFileInfo(ancestor.absolutePath()).dir();
182 }
183 // One of the parent directories of filePath matches dataDir
184 return fi.absoluteFilePath();
185 }
186}
QAbstractSpinBox
QAbstractSpinBox::editingFinished
void editingFinished()
QCoreApplication::applicationDirPath
QString applicationDirPath()
QDir
QDir::absoluteFilePath
QString absoluteFilePath(const QString &fileName) const const
QDir::absolutePath
QString absolutePath() const const
QDir::canonicalPath
QString canonicalPath() const const
QDir::exists
bool exists() const const
QDir::isRoot
bool isRoot() const const
QDir::setPath
void setPath(const QString &path)
QFileInfo
QFileInfo::dir
QDir dir() const const
QImage::byteCount
int byteCount() const const
QImage
QImage::sizeInBytes
qsizetype sizeInBytes() const const
QLineF
QLineF::dx
qreal dx() const const
QLineF::dy
qreal dy() const const
QLineF::x1
qreal x1() const const
QLineF::x2
qreal x2() const const
QLineF::y1
qreal y1() const const
QLineF::y2
qreal y2() const const
QObject::connect
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QRect
QRect::height
int height() const const
QRect::left
int left() const const
QRect::top
int top() const const
QRect::width
int width() const const
QStandardPaths::findExecutable
QString findExecutable(const QString &executableName, const QStringList &paths)
QString
QString::fromUtf8
QString fromUtf8(const char *str, int size)
QString::isEmpty
bool isEmpty() const const
QStringList
Qt::left
QTextStream & left(QTextStream &stream)
Qt::right
QTextStream & right(QTextStream &stream)
QWidget::clearFocus
void clearFocus()
Generated on Thu May 8 2025 04:47:53 for Pencil2D by doxygen 1.9.6 based on revision 4513250b1d5b1a3676ec0e67b06b7a885ceaae39