add svg icon engine

This commit is contained in:
ws 2013-05-14 15:32:51 +02:00
parent 81308f5e23
commit 81acb16ebc
4 changed files with 242 additions and 2 deletions

View file

@ -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}

View file

@ -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
View 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
View 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