24
#include "PreCompiled.h"
26
# include <QApplication>
32
# include <QImageReader>
36
# include <QSvgRenderer>
37
# include <QStyleOption>
41
#include <Inventor/fields/SoSFImage.h>
43
#include <App/Application.h>
44
#include <Base/Console.h>
45
#include <Base/ConsoleObserver.h>
47
#include "BitmapFactory.h"
52
static const char *not_found[]={
56
"........................",
57
"........................",
58
"...##..............##...",
59
"..####............####..",
60
"..#####..........#####..",
61
"..######........#####...",
62
"...######......######...",
63
"....######....######....",
64
".....######..######.....",
65
"......############......",
66
".......##########.......",
67
"........########........",
68
".........######.........",
69
"........########........",
70
".......##########.......",
71
"......############......",
72
".....######..######.....",
73
"....######....######....",
74
"..#######......######...",
75
".#######........######..",
76
".######..........#####..",
77
"..####.............##...",
78
"........................",
79
"........................"};
82
class BitmapFactoryInstP
85
QMap<std::string, const char**> xpmMap;
86
QMap<std::string, QPixmap> xpmCache;
90
BitmapFactoryInst* BitmapFactoryInst::_pcSingleton = nullptr;
92
BitmapFactoryInst& BitmapFactoryInst::instance()
96
_pcSingleton = new BitmapFactoryInst;
97
std::map<std::string,std::string>::const_iterator it;
98
it = App::GetApplication().Config().find("ProgramIcons");
99
if (it != App::GetApplication().Config().end()) {
100
QString home = QString::fromStdString(App::Application::getHomePath());
101
QString path = QString::fromUtf8(it->second.c_str());
102
if (QDir(path).isRelative()) {
103
path = QFileInfo(QDir(home), path).absoluteFilePath();
105
_pcSingleton->addPath(path);
107
_pcSingleton->addPath(QString::fromLatin1("%1/icons").arg(QString::fromStdString(App::Application::getHomePath())));
108
_pcSingleton->addPath(QString::fromLatin1("%1/icons").arg(QString::fromStdString(App::Application::getUserAppDataDir())));
109
_pcSingleton->addPath(QLatin1String(":/icons/"));
110
_pcSingleton->addPath(QLatin1String(":/Icons/"));
113
return *_pcSingleton;
116
void BitmapFactoryInst::destruct ()
120
_pcSingleton = nullptr;
123
BitmapFactoryInst::BitmapFactoryInst()
125
d = new BitmapFactoryInstP;
126
restoreCustomPaths();
129
BitmapFactoryInst::~BitmapFactoryInst()
134
void BitmapFactoryInst::restoreCustomPaths()
136
Base::Reference<ParameterGrp> group = App::GetApplication().GetParameterGroupByPath
137
("User parameter:BaseApp/Preferences/Bitmaps");
138
std::vector<std::string> paths = group->GetASCIIs("CustomPath");
139
for (auto & path : paths) {
140
addPath(QString::fromUtf8(path.c_str()));
144
void BitmapFactoryInst::addPath(const QString& path)
146
QDir::addSearchPath(QString::fromLatin1("icons"), path);
149
void BitmapFactoryInst::removePath(const QString& path)
151
QStringList iconPaths = QDir::searchPaths(QString::fromLatin1("icons"));
152
int pos = iconPaths.indexOf(path);
154
iconPaths.removeAt(pos);
155
QDir::setSearchPaths(QString::fromLatin1("icons"), iconPaths);
159
QStringList BitmapFactoryInst::getPaths() const
161
return QDir::searchPaths(QString::fromLatin1("icons"));
164
QStringList BitmapFactoryInst::findIconFiles() const
166
QStringList files, filters;
167
QList<QByteArray> formats = QImageReader::supportedImageFormats();
168
for (QList<QByteArray>::iterator it = formats.begin(); it != formats.end(); ++it)
169
filters << QString::fromLatin1("*.%1").arg(QString::fromLatin1(*it).toLower());
171
QStringList paths = QDir::searchPaths(QString::fromLatin1("icons"));
172
paths.removeDuplicates();
173
for (QStringList::Iterator pt = paths.begin(); pt != paths.end(); ++pt) {
175
d.setNameFilters(filters);
176
QFileInfoList fi = d.entryInfoList();
177
for (QFileInfoList::iterator it = fi.begin(); it != fi.end(); ++it)
178
files << it->absoluteFilePath();
181
files.removeDuplicates();
185
void BitmapFactoryInst::addXPM(const char* name, const char** pXPM)
187
d->xpmMap[name] = pXPM;
190
void BitmapFactoryInst::addPixmapToCache(const char* name, const QPixmap& icon)
192
d->xpmCache[name] = icon;
195
bool BitmapFactoryInst::findPixmapInCache(const char* name, QPixmap& px) const
197
QMap<std::string, QPixmap>::Iterator it = d->xpmCache.find(name);
198
if (it != d->xpmCache.end()) {
205
QIcon BitmapFactoryInst::iconFromTheme(const char* name, const QIcon& fallback)
207
QString iconName = QString::fromUtf8(name);
208
QIcon icon = QIcon::fromTheme(iconName, fallback);
210
QPixmap px = pixmap(name);
218
bool BitmapFactoryInst::loadPixmap(const QString& filename, QPixmap& icon) const
220
QFileInfo fi(filename);
223
if (fi.suffix().toLower() == QLatin1String("svg")) {
224
QFile svgFile(fi.filePath());
225
if (svgFile.open(QFile::ReadOnly | QFile::Text)) {
226
QByteArray content = svgFile.readAll();
227
icon = pixmapFromSvg(content, QSize(64,64));
232
icon.load(fi.filePath());
236
return !icon.isNull();
239
QPixmap BitmapFactoryInst::pixmap(const char* name) const
241
if (!name || *name == '\0')
245
QMap<std::string, QPixmap>::Iterator it = d->xpmCache.find(name);
246
if (it != d->xpmCache.end())
251
QMap<std::string,const char**>::Iterator It = d->xpmMap.find(name);
252
if (It != d->xpmMap.end())
253
icon = QPixmap(It.value());
256
QString fn = QString::fromUtf8(name);
258
loadPixmap(fn, icon);
262
QList<QByteArray> formats = QImageReader::supportedImageFormats();
263
formats.prepend("SVG");
265
QString fileName = QString::fromLatin1("icons:") + fn;
266
if (!loadPixmap(fileName, icon)) {
268
for (QList<QByteArray>::iterator fm = formats.begin(); fm != formats.end(); ++fm) {
269
QString path = QString::fromLatin1("%1.%2").arg(fileName,
270
QString::fromLatin1((*fm).toLower().constData()));
271
if (loadPixmap(path, icon)) {
278
if (!icon.isNull()) {
279
d->xpmCache[name] = icon;
283
Base::Console().Warning("Cannot find icon: %s\n", name);
284
return QPixmap(not_found);
287
QPixmap BitmapFactoryInst::pixmapFromSvg(const char* name, const QSizeF& size,
288
const ColorMap& colorMapping) const
293
QString fn = QString::fromUtf8(name);
294
if (QFile(fn).exists())
298
if (iconPath.isEmpty()) {
299
QString fileName = QString::fromLatin1("icons:") + fn;
300
QFileInfo fi(fileName);
302
iconPath = fi.filePath();
305
fileName += QLatin1String(".svg");
306
fi.setFile(fileName);
308
iconPath = fi.filePath();
313
if (!iconPath.isEmpty()) {
314
QFile file(iconPath);
315
if (file.open(QFile::ReadOnly | QFile::Text)) {
316
QByteArray content = file.readAll();
317
icon = pixmapFromSvg(content, size, colorMapping);
324
QPixmap BitmapFactoryInst::pixmapFromSvg(const char* name, const QSizeF& size, qreal dpr,
325
const ColorMap& colorMapping) const
327
qreal width = size.width() * dpr;
328
qreal height = size.height() * dpr;
329
QPixmap px(pixmapFromSvg(name, QSizeF(width, height), colorMapping));
330
px.setDevicePixelRatio(dpr);
334
QPixmap BitmapFactoryInst::pixmapFromSvg(const QByteArray& originalContents, const QSizeF& size,
335
const ColorMap& colorMapping) const
337
QString stringContents = QString::fromUtf8(originalContents);
338
for ( const auto &colorToColor : colorMapping ) {
339
ulong fromColor = colorToColor.first;
340
ulong toColor = colorToColor.second;
341
QString fromColorString = QString::fromLatin1(":#%1;").arg(fromColor, 6, 16, QChar::fromLatin1('0'));
342
QString toColorString = QString::fromLatin1(":#%1;").arg(toColor, 6, 16, QChar::fromLatin1('0'));
343
stringContents = stringContents.replace(fromColorString, toColorString);
345
QByteArray contents = stringContents.toUtf8();
347
QImage image(size.toSize(), QImage::Format_ARGB32_Premultiplied);
348
image.fill(0x00000000);
354
const Base::ILoggerBlocker blocker("ReportOutput", Base::ConsoleSingleton::MsgType_Wrn);
360
return QPixmap::fromImage(image);
363
QStringList BitmapFactoryInst::pixmapNames() const
366
for (QMap<std::string,const char**>::Iterator It = d->xpmMap.begin(); It != d->xpmMap.end(); ++It)
367
names << QString::fromUtf8(It.key().c_str());
368
for (QMap<std::string, QPixmap>::Iterator It = d->xpmCache.begin(); It != d->xpmCache.end(); ++It) {
369
QString item = QString::fromUtf8(It.key().c_str());
370
if (!names.contains(item))
376
QPixmap BitmapFactoryInst::resize(int w, int h, const QPixmap& p, Qt::BGMode bgmode) const
378
if (bgmode == Qt::TransparentMode) {
379
if (p.width() == 0 || p.height() == 0)
383
int x = pix.width () > w ? 0 : (w - pix.width ())/2;
384
int y = pix.height() > h ? 0 : (h - pix.height())/2;
386
if (x == 0 && y == 0)
391
mask.fill(Qt::color0);
393
QBitmap bm = pix.mask();
396
QPainter painter(&mask);
397
painter.drawPixmap(QPoint(x, y), bm, QRect(0, 0, pix.width(), pix.height()));
403
pm = fillRect(x, y, pix.width(), pix.height(), pm, Qt::OpaqueMode);
408
pt.drawPixmap(x, y, pix);
414
if (pix.width() == 0 || pix.height() == 0)
417
QPalette pal = qApp->palette();
418
QColor dl = pal.color(QPalette::Disabled, QPalette::Light);
419
QColor dt = pal.color(QPalette::Disabled, QPalette::Text);
427
pt.drawPixmap(1, 1, pix);
429
pt.drawPixmap(0, 0, pix);
435
QPixmap BitmapFactoryInst::fillRect(int x, int y, int w, int h, const QPixmap& p, Qt::BGMode bgmode) const
437
QBitmap b = p.mask();
446
if (bgmode == Qt::OpaqueMode)
447
pt.fillRect(x, y, w, h, Qt::color1);
449
pt.fillRect(x, y, w, h, Qt::color0);
457
QPixmap BitmapFactoryInst::merge(const QPixmap& p1, const QPixmap& p2, bool vertical) const
468
width = qMax( p1.width(), p2.width() );
469
height = p1.height() + p2.height();
472
width = p1.width() + p2.width();
473
height = qMax( p1.height(), p2.height() );
476
QPixmap res( width, height );
477
QBitmap mask( width, height );
478
QBitmap mask1 = p1.mask();
479
QBitmap mask2 = p2.mask();
480
mask.fill( Qt::color0 );
482
auto* pt1 = new QPainter(&res);
483
pt1->drawPixmap(0, 0, p1);
484
pt1->drawPixmap(x, y, p2);
487
auto* pt2 = new QPainter(&mask);
488
pt2->drawPixmap(0, 0, mask1);
489
pt2->drawPixmap(x, y, mask2);
496
QPixmap BitmapFactoryInst::merge(const QPixmap& p1, const QPixmap& p2, Position pos) const
500
qreal dpr1 = p1.devicePixelRatio();
501
qreal dpr2 = p2.devicePixelRatio();
508
x = p1.width ()/dpr1 - p2.width ()/dpr2;
511
y = p1.height()/dpr1 - p2.height()/dpr2;
514
x = p1.width ()/dpr1 - p2.width ()/dpr2;
515
y = p1.height()/dpr1 - p2.height()/dpr2;
520
p = fillRect(x, y, p2.width(), p2.height(), p, Qt::OpaqueMode);
524
pt.setPen(Qt::NoPen);
525
pt.drawRect(x, y, p2.width(), p2.height());
526
pt.drawPixmap(x, y, p2);
532
QPixmap BitmapFactoryInst::disabled(const QPixmap& p) const
535
opt.palette = QApplication::palette();
536
return QApplication::style()->generatedIconPixmap(QIcon::Disabled, p, &opt);
539
void BitmapFactoryInst::convert(const QImage& p, SoSFImage& img) const
543
size[1] = p.height();
545
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
546
int buffersize = static_cast<int>(p.sizeInBytes());
548
int buffersize = p.byteCount();
550
int numcomponents = 0;
551
QVector<QRgb> table = p.colorTable();
552
if (!table.isEmpty()) {
553
if (p.hasAlphaChannel()) {
567
numcomponents = buffersize / (size[0] * size[1]);
571
img.setValue(size, numcomponents, nullptr);
573
unsigned char * bytes = img.startEditing(size, numcomponents);
575
int width = (int)size[0];
576
int height = (int)size[1];
578
for (int y = 0; y < height; y++)
580
unsigned char * line = &bytes[width*numcomponents*(height-(y+1))];
581
for (int x = 0; x < width; x++)
583
QRgb rgb = p.pixel(x,y);
584
switch (numcomponents)
589
line[0] = qGray( rgb );
592
line[0] = qGray( rgb );
593
line[1] = qAlpha( rgb );
596
line[0] = qRed( rgb );
597
line[1] = qGreen( rgb );
598
line[2] = qBlue( rgb );
601
line[0] = qRed( rgb );
602
line[1] = qGreen( rgb );
603
line[2] = qBlue( rgb );
604
line[3] = qAlpha( rgb );
608
line += numcomponents;
615
void BitmapFactoryInst::convert(const SoSFImage& p, QImage& img) const
620
const unsigned char * bytes = p.getValue(size, numcomponents);
624
int width = (int)size[0];
625
int height = (int)size[1];
627
img = QImage(width, height, QImage::Format_RGB32);
628
QRgb * bits = (QRgb*) img.bits();
630
for (int y = 0; y < height; y++)
632
const unsigned char * line = &bytes[width*numcomponents*(height-(y+1))];
633
for (int x = 0; x < width; x++)
635
switch (numcomponents)
639
*bits++ = qRgb(line[0], line[0], line[0]);
642
*bits++ = qRgba(line[0], line[0], line[0], line[1]);
645
*bits++ = qRgb(line[0], line[1], line[2]);
648
*bits++ = qRgba(line[0], line[1], line[2], line[3]);
652
line += numcomponents;
657
QIcon BitmapFactoryInst::mergePixmap (const QIcon &base, const QPixmap &px, Gui::BitmapFactoryInst::Position position)
661
int w = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize);
663
overlayedIcon.addPixmap(Gui::BitmapFactory().merge(base.pixmap(w, w, QIcon::Normal, QIcon::Off),
664
px,position), QIcon::Normal, QIcon::Off);
666
overlayedIcon.addPixmap(Gui::BitmapFactory().merge(base.pixmap(w, w, QIcon::Normal, QIcon::On ),
667
px,position), QIcon::Normal, QIcon::Off);
669
return overlayedIcon;