add svg icon engine
This commit is contained in:
parent
81308f5e23
commit
81acb16ebc
4 changed files with 242 additions and 2 deletions
|
@ -205,7 +205,7 @@ add_executable ( ${ExecutableName}
|
|||
inspectorGlissando.cpp inspectorNote.cpp paletteBoxButton.cpp
|
||||
driver.cpp exportmidi.cpp noteGroups.cpp
|
||||
pathlistdialog.cpp exampleview.cpp inspectorTextLine.cpp
|
||||
importmidi_panel.cpp importmidi_operations.cpp
|
||||
importmidi_panel.cpp importmidi_operations.cpp miconengine.cpp
|
||||
|
||||
${OMR_FILES}
|
||||
${AUDIO}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "preferences.h"
|
||||
#include "libmscore/sym.h"
|
||||
#include "libmscore/mscore.h"
|
||||
#include "miconengine.h"
|
||||
|
||||
namespace Ms {
|
||||
|
||||
|
@ -130,7 +131,9 @@ void genIcons()
|
|||
{
|
||||
// qDebug("genIcons <%s>\n", qPrintable(iconPath + iconGroup));
|
||||
for (int i = 0; i < voice1_ICON; ++i) {
|
||||
icons[i] = new QIcon(iconPath + iconGroup + iconNames[i]);
|
||||
QIcon* icon = new QIcon(new MIconEngine);
|
||||
icon->addFile(iconPath + iconGroup + iconNames[i]);
|
||||
icons[i] = icon;
|
||||
if (icons[i]->isNull() || icons[i]->pixmap(12).isNull()) {
|
||||
qDebug("cannot load Icon <%s>\n", qPrintable(iconPath + iconGroup + iconNames[i]));
|
||||
}
|
||||
|
|
202
mscore/miconengine.cpp
Normal file
202
mscore/miconengine.cpp
Normal file
|
@ -0,0 +1,202 @@
|
|||
#include "miconengine.h"
|
||||
|
||||
//---------------------------------------------------------
|
||||
// MIconEnginePrivate
|
||||
//---------------------------------------------------------
|
||||
|
||||
class MIconEnginePrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
MIconEnginePrivate() : svgBuffers(0), addedPixmaps(0) { stepSerialNum(); }
|
||||
~MIconEnginePrivate() { delete addedPixmaps; delete svgBuffers; }
|
||||
static int hashKey(QIcon::Mode mode, QIcon::State state) { return (((mode)<<4)|state); }
|
||||
|
||||
QString pmcKey(const QSize &size, QIcon::Mode mode, QIcon::State state) {
|
||||
return QLatin1String("$qt_svgicon_")
|
||||
+ QString::number(serialNum, 16).append(QLatin1Char('_'))
|
||||
+ QString::number((((((size.width()<<11)|size.height())<<11)|mode)<<4)|state, 16);
|
||||
}
|
||||
|
||||
void stepSerialNum() { serialNum = lastSerialNum.fetchAndAddRelaxed(1); }
|
||||
void loadDataForModeAndState(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state);
|
||||
|
||||
QHash<int, QString> svgFiles;
|
||||
QHash<int, QByteArray> *svgBuffers;
|
||||
QHash<int, QPixmap> *addedPixmaps;
|
||||
int serialNum;
|
||||
static QAtomicInt lastSerialNum;
|
||||
};
|
||||
|
||||
QAtomicInt MIconEnginePrivate::lastSerialNum;
|
||||
|
||||
static inline int pmKey(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return ((((((size.width()<<11)|size.height())<<11)|mode)<<4)|state);
|
||||
}
|
||||
|
||||
MIconEngine::MIconEngine()
|
||||
: d(new MIconEnginePrivate)
|
||||
{
|
||||
}
|
||||
|
||||
MIconEngine::MIconEngine(const MIconEngine &other)
|
||||
: QIconEngine(other), d(new MIconEnginePrivate)
|
||||
{
|
||||
d->svgFiles = other.d->svgFiles;
|
||||
if (other.d->svgBuffers)
|
||||
d->svgBuffers = new QHash<int, QByteArray>(*other.d->svgBuffers);
|
||||
if (other.d->addedPixmaps)
|
||||
d->addedPixmaps = new QHash<int, QPixmap>(*other.d->addedPixmaps);
|
||||
}
|
||||
|
||||
MIconEngine::~MIconEngine()
|
||||
{
|
||||
}
|
||||
|
||||
QSize MIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
if (d->addedPixmaps) {
|
||||
QPixmap pm = d->addedPixmaps->value(d->hashKey(mode, state));
|
||||
if (!pm.isNull() && pm.size() == size)
|
||||
return size;
|
||||
}
|
||||
|
||||
QPixmap pm = pixmap(size, mode, state);
|
||||
if (pm.isNull())
|
||||
return QSize();
|
||||
return pm.size();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// loadDataForModeAndState
|
||||
//---------------------------------------------------------
|
||||
|
||||
void MIconEnginePrivate::loadDataForModeAndState(QSvgRenderer* renderer, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
QByteArray buf;
|
||||
if (svgBuffers) {
|
||||
buf = svgBuffers->value(hashKey(mode, state));
|
||||
if (buf.isEmpty())
|
||||
buf = svgBuffers->value(hashKey(QIcon::Normal, QIcon::Off));
|
||||
}
|
||||
if (!buf.isEmpty()) {
|
||||
buf = qUncompress(buf);
|
||||
renderer->load(buf);
|
||||
}
|
||||
else {
|
||||
QString svgFile = svgFiles.value(hashKey(mode, state));
|
||||
if (svgFile.isEmpty())
|
||||
svgFile = svgFiles.value(hashKey(QIcon::Normal, QIcon::Off));
|
||||
if (!svgFile.isEmpty())
|
||||
renderer->load(svgFile);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// pixmap
|
||||
//---------------------------------------------------------
|
||||
|
||||
QPixmap MIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
QPixmap pm;
|
||||
|
||||
QString pmckey(d->pmcKey(size, mode, state));
|
||||
if (QPixmapCache::find(pmckey, pm))
|
||||
return pm;
|
||||
|
||||
if (d->addedPixmaps) {
|
||||
pm = d->addedPixmaps->value(d->hashKey(mode, state));
|
||||
if (!pm.isNull() && pm.size() == size)
|
||||
return pm;
|
||||
}
|
||||
|
||||
QSvgRenderer renderer;
|
||||
d->loadDataForModeAndState(&renderer, mode, state);
|
||||
if (!renderer.isValid())
|
||||
return pm;
|
||||
|
||||
QSize actualSize = renderer.defaultSize();
|
||||
if (!actualSize.isNull())
|
||||
actualSize.scale(size, Qt::KeepAspectRatio);
|
||||
|
||||
QImage img(actualSize, QImage::Format_ARGB32_Premultiplied);
|
||||
img.fill(0x00000000);
|
||||
QPainter p(&img);
|
||||
renderer.render(&p);
|
||||
p.end();
|
||||
|
||||
#if 0 // test:
|
||||
if (state == QIcon::On) {
|
||||
int ww = img.width();
|
||||
for (int y = 0; y < img.height(); ++y) {
|
||||
quint32* p = (quint32*)img.scanLine(y);
|
||||
for (int x = 0; x < ww; ++x) {
|
||||
if (*p & 0xff000000)
|
||||
*p = (*p & 0xff000000) + 0xff; // blue
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pm = QPixmap::fromImage(img);
|
||||
if (qobject_cast<QApplication *>(QCoreApplication::instance())) {
|
||||
QStyleOption opt(0);
|
||||
opt.palette = QApplication::palette(); // opt.palette = QGuiApplication::palette();
|
||||
QPixmap generated = QApplication::style()->generatedIconPixmap(mode, pm, &opt);
|
||||
if (!generated.isNull())
|
||||
pm = generated;
|
||||
}
|
||||
|
||||
if (!pm.isNull())
|
||||
QPixmapCache::insert(pmckey, pm);
|
||||
|
||||
return pm;
|
||||
}
|
||||
|
||||
void MIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
if (!d->addedPixmaps)
|
||||
d->addedPixmaps = new QHash<int, QPixmap>;
|
||||
d->stepSerialNum();
|
||||
d->addedPixmaps->insert(d->hashKey(mode, state), pixmap);
|
||||
}
|
||||
|
||||
void MIconEngine::addFile(const QString &fileName, const QSize &, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
if (!fileName.isEmpty()) {
|
||||
QString abs = fileName;
|
||||
if (fileName.at(0) != QLatin1Char(':'))
|
||||
abs = QFileInfo(fileName).absoluteFilePath();
|
||||
if (abs.endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)
|
||||
|| abs.endsWith(QLatin1String(".svgz"), Qt::CaseInsensitive)
|
||||
|| abs.endsWith(QLatin1String(".svg.gz"), Qt::CaseInsensitive))
|
||||
{
|
||||
QSvgRenderer renderer(abs);
|
||||
if (renderer.isValid()) {
|
||||
d->stepSerialNum();
|
||||
d->svgFiles.insert(d->hashKey(mode, state), abs);
|
||||
}
|
||||
} else {
|
||||
QPixmap pm(abs);
|
||||
if (!pm.isNull())
|
||||
addPixmap(pm, mode, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
painter->drawPixmap(rect, pixmap(rect.size(), mode, state));
|
||||
}
|
||||
|
||||
QString MIconEngine::key() const
|
||||
{
|
||||
return QLatin1String("svg");
|
||||
}
|
||||
|
||||
QIconEngine *MIconEngine::clone() const
|
||||
{
|
||||
return new MIconEngine(*this);
|
||||
}
|
||||
|
35
mscore/miconengine.h
Normal file
35
mscore/miconengine.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef __MICONENGINE_H__
|
||||
#define __MICONENGINE_H__
|
||||
|
||||
#include <QtGui/qiconengine.h>
|
||||
#include <QtCore/qshareddata.h>
|
||||
|
||||
class MIconEnginePrivate;
|
||||
|
||||
//---------------------------------------------------------
|
||||
// MIconEngine
|
||||
//---------------------------------------------------------
|
||||
|
||||
class MIconEngine : public QIconEngine
|
||||
{
|
||||
public:
|
||||
MIconEngine();
|
||||
MIconEngine(const MIconEngine &other);
|
||||
~MIconEngine();
|
||||
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state);
|
||||
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
|
||||
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
|
||||
|
||||
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state);
|
||||
void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state);
|
||||
|
||||
QString key() const;
|
||||
QIconEngine *clone() const;
|
||||
bool read(QDataStream &in) { return false; }
|
||||
bool write(QDataStream &out) const { return false; }
|
||||
|
||||
private:
|
||||
QSharedDataPointer<MIconEnginePrivate> d;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue