Add SVG icon rendering/cache

This commit is contained in:
Petr Mrázek 2013-03-20 07:59:35 +01:00
parent 7d7e4034f4
commit e4806ab08d
6 changed files with 187 additions and 36 deletions

View File

@ -31,7 +31,6 @@ ENDIF()
# First, include header overrides
include_directories(hacks)
######## 3rd Party Libs ########
# Find the required Qt parts
@ -155,7 +154,7 @@ MESSAGE(STATUS "Job URL: ${MultiMC_JOB_URL}")
######## Configure header ########
configure_file("${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/include/config.h")
include_directories(${PROJECT_BINARY_DIR}/include)
################################ FILES ################################
@ -172,6 +171,7 @@ gui/aboutdialog.h
gui/consolewindow.h
gui/instancemodel.h
gui/instancedelegate.h
gui/iconcache.h
multimc_pragma.h
@ -200,6 +200,7 @@ gui/aboutdialog.cpp
gui/consolewindow.cpp
gui/instancemodel.cpp
gui/instancedelegate.cpp
gui/iconcache.cpp
java/javautils.cpp
java/annotations.cpp

127
gui/iconcache.cpp Normal file
View File

@ -0,0 +1,127 @@
#include "iconcache.h"
#include <QMap>
#include <QWebView>
#include <QWebFrame>
#include <QEventLoop>
#include <QWebElement>
IconCache* IconCache::m_Instance = 0;
QMutex IconCache::mutex;
#define MAX_SIZE 1024
class Private : public QWebView
{
Q_OBJECT
public:
QString name;
QSize size;
QMap<QString, QIcon> icons;
public:
Private()
{
connect(this, SIGNAL(loadFinished(bool)), this, SLOT(svgLoaded(bool)));
setFixedSize(MAX_SIZE, MAX_SIZE);
QPalette pal = palette();
pal.setColor(QPalette::Base, Qt::transparent);
setPalette(pal);
setAttribute(Qt::WA_OpaquePaintEvent, false);
size = QSize(128,128);
}
void renderSVGIcon(QString name);
signals:
void svgRendered();
private slots:
void svgLoaded(bool ok);
};
void Private::svgLoaded(bool ok)
{
if (!ok)
{
emit svgRendered();
return;
}
// check for SVG root tag
QString root = page()->currentFrame()->documentElement().tagName();
if (root.compare("svg", Qt::CaseInsensitive) != 0)
{
emit svgRendered();
return;
}
// get the size of the svg image, check if it's valid
auto elem = page()->currentFrame()->documentElement();
double width = elem.attribute("width").toDouble();
double height = elem.attribute("height").toDouble();
if (width == 0.0 || height == 0.0 || width == MAX_SIZE || height == MAX_SIZE)
{
emit svgRendered();
return;
}
// create the target surface
QSize t = size.isValid() ? size : QSize(width, height);
QImage img(t, QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::transparent);
// prepare the painter, scale to required size
QPainter p(&img);
if(size.isValid())
{
p.scale(size.width() / width, size.height() / height);
}
// the best quality
p.setRenderHint(QPainter::Antialiasing);
p.setRenderHint(QPainter::TextAntialiasing);
p.setRenderHint(QPainter::SmoothPixmapTransform);
page()->mainFrame()->render(&p,QWebFrame::ContentsLayer);
p.end();
icons[name] = QIcon(QPixmap::fromImage(img));
emit svgRendered();
}
void Private::renderSVGIcon ( QString name )
{
// use event loop to wait for signal
QEventLoop loop;
this->name = name;
QString prefix = "qrc:/icons/instances/";
QObject::connect(this, SIGNAL(svgRendered()), &loop, SLOT(quit()));
load(QUrl(prefix + name));
loop.exec();
}
IconCache::IconCache():d(new Private())
{
}
QIcon IconCache::getIcon ( QString name )
{
if(name == "default")
name = "infinity";
{
auto iter = d->icons.find(name);
if(iter != d->icons.end())
return *iter;
}
d->renderSVGIcon(name);
auto iter = d->icons.find(name);
if(iter != d->icons.end())
return *iter;
// Fallback for icons that don't exist.
QString path = ":/icons/instances/infinity";
//path += name;
d->icons[name] = QIcon(path);
return d->icons[name];
}
#include "iconcache.moc"

43
gui/iconcache.h Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#include <QMutex>
#include <QtGui/QIcon>
class Private;
class IconCache
{
public:
static IconCache* instance()
{
if (!m_Instance)
{
mutex.lock();
if (!m_Instance)
m_Instance = new IconCache;
mutex.unlock();
}
return m_Instance;
}
static void drop()
{
mutex.lock();
delete m_Instance;
m_Instance = 0;
mutex.unlock();
}
QIcon getIcon(QString name);
private:
IconCache();
// hide copy constructor
IconCache(const IconCache &);
// hide assign op
IconCache& operator=(const IconCache &);
static IconCache* m_Instance;
static QMutex mutex;
Private* d;
};

View File

@ -1,6 +1,7 @@
#include "instancemodel.h"
#include <instance.h>
#include <QIcon>
#include "iconcache.h"
InstanceModel::InstanceModel ( const InstanceList& instances, QObject *parent )
: QAbstractListModel ( parent ), m_instances ( &instances )
@ -70,11 +71,15 @@ QVariant InstanceModel::data ( const QModelIndex& index, int role ) const
}
case Qt::DecorationRole:
{
IconCache * ic = IconCache::instance();
// FIXME: replace with an icon cache/renderer
/*
QString path = ":/icons/instances/";
path += pdata->iconKey();
QIcon icon(path);
return icon;
*/
QString key = pdata->iconKey();
return ic->getIcon(key);
//else return QIcon(":/icons/multimc/scalable/apps/multimc.svg");
}
// for now.

View File

@ -71,6 +71,7 @@ MainWindow::MainWindow ( QWidget *parent ) :
pal.setBrush(QPalette::Base, QBrush(QPixmap(QString::fromUtf8(":/backgrounds/kitteh"))));
view->setPalette(pal);
*/
view->setStyleSheet(
"QListView\
{\

View File

@ -13,26 +13,13 @@
height="32"
id="svg2"
version="1.1"
inkscape:version="0.48.3.1 r9886"
inkscape:version="0.48.4 r9939"
sodipodi:docname="skeleton.svg"
inkscape:export-filename="/home/peterix/projects/MultiMC4/src/resources/insticons/skeleton128.png"
inkscape:export-xdpi="360"
inkscape:export-ydpi="360">
<defs
id="defs4">
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
id="filter5719"
x="-0.18000001"
width="1.36"
y="-0.36000001"
height="1.72">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.15"
id="feGaussianBlur5721" />
</filter>
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
@ -46,19 +33,6 @@
stdDeviation="0.35"
id="feGaussianBlur5725" />
</filter>
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
id="filter5711"
x="-0.1728"
width="1.3456"
y="-0.34560001"
height="1.6912">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.144"
id="feGaussianBlur5713" />
</filter>
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
@ -103,12 +77,12 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.313708"
inkscape:cx="17.044214"
inkscape:cy="19.500236"
inkscape:cx="-18.309169"
inkscape:cy="22.958832"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1607"
inkscape:window-width="1614"
inkscape:window-height="1030"
inkscape:window-x="1676"
inkscape:window-y="-3"
@ -129,7 +103,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -612,7 +586,7 @@
x="7.9999995"
y="1036.3622" />
<rect
style="fill:#00ffff;fill-opacity:1;stroke:none;filter:url(#filter5711)"
style="fill:#00ffff;fill-opacity:1;stroke:none;"
id="rect4084-3"
width="2"
height="1"
@ -626,7 +600,7 @@
x="20"
y="1036.3622" />
<rect
style="fill:#00ffff;fill-opacity:1;stroke:none;filter:url(#filter5719)"
style="fill:#00ffff;fill-opacity:1;stroke:none;"
id="rect4086-7"
width="2"
height="1"

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 15 KiB