File indexing completed on 2024-12-15 03:48:05
0001 /* 0002 SPDX-FileCopyrightText: 2008 Sascha Peilicke <sasch.pe@gmx.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "themerenderer.h" 0008 #include "preferences.h" 0009 0010 #include <KGameThemeProvider> 0011 0012 #include <QSvgRenderer> 0013 #include <QPixmapCache> 0014 #include <QPixmap> 0015 #include <QPainter> 0016 0017 namespace Kigo { 0018 0019 ThemeRenderer::ThemeRenderer() 0020 : m_themeProvider(new KGameThemeProvider(QByteArray(), this)) // empty config key to disable internal config storage 0021 , m_renderer(new QSvgRenderer) 0022 { 0023 QPixmapCache::setCacheLimit(3 * 1024); 0024 m_themeProvider->discoverThemes( 0025 QStringLiteral("themes"), // theme file location 0026 QStringLiteral("default") // default theme file name 0027 ); 0028 const QByteArray themeIdentifier = Preferences::theme().toUtf8(); 0029 KGameThemeProvider *provider = themeProvider(); 0030 const QList<const KGameTheme *> themes = provider->themes(); 0031 for (auto* theme : themes) { 0032 if (theme->identifier() == themeIdentifier) { 0033 provider->setCurrentTheme(theme); 0034 break; 0035 } 0036 } 0037 loadTheme(provider->currentTheme()); 0038 connect(m_themeProvider, &KGameThemeProvider::currentThemeChanged, 0039 this, &ThemeRenderer::loadTheme); 0040 } 0041 0042 ThemeRenderer::~ThemeRenderer() 0043 { 0044 delete m_renderer; 0045 } 0046 0047 KGameThemeProvider *ThemeRenderer::themeProvider() const 0048 { 0049 return m_themeProvider; 0050 } 0051 0052 void ThemeRenderer::loadTheme(const KGameTheme *theme) 0053 { 0054 //qCDebug(KIGO_LOG) << "Loading" << theme.graphics(); 0055 if (!m_renderer->load(theme->graphicsPath())) { 0056 return; 0057 } 0058 0059 Preferences::setTheme(QString::fromUtf8(theme->identifier())); 0060 Preferences::self()->save(); 0061 0062 QPixmapCache::clear(); 0063 0064 Q_EMIT themeChanged(); 0065 } 0066 0067 void ThemeRenderer::renderElement(Element element, QPainter *painter, const QRectF &rect) const 0068 { 0069 if (!m_renderer->isValid() || rect.isEmpty() || painter == nullptr) { 0070 return; 0071 } 0072 0073 const QPixmap pixmap = renderElement(element, rect.size().toSize()); 0074 0075 // Draw pixmap with the parameter provided painter 0076 painter->drawPixmap(static_cast<int>(rect.x()), static_cast<int>(rect.y()), pixmap); 0077 } 0078 0079 QPixmap ThemeRenderer::renderElement(Element element, const QSize &size) const 0080 { 0081 if (!m_renderer->isValid() || size.isEmpty()) { 0082 return QPixmap(); 0083 } 0084 0085 // Determine which board element we have to render and set the cache item name 0086 QString cacheName; 0087 switch (element) { 0088 case Element::Background: 0089 cacheName = QStringLiteral("background_%1x%2").arg(size.width()).arg(size.height()); 0090 break; 0091 case Element::Board: 0092 cacheName = QStringLiteral("board_%1x%2").arg(size.width()).arg(size.height()); 0093 break; 0094 case Element::HandicapMark: 0095 cacheName = QStringLiteral("handicap_mark_%1x%2").arg(size.width()).arg(size.height()); 0096 break; 0097 case Element::WhiteStone: 0098 cacheName = QStringLiteral("white_stone_%1x%2").arg(size.width()).arg(size.height()); 0099 break; 0100 case Element::WhiteStoneLast: 0101 cacheName = QStringLiteral("white_stone_last_%1x%2").arg(size.width()).arg(size.height()); 0102 break; 0103 case Element::WhiteStoneTransparent: 0104 cacheName = QStringLiteral("white_stone_%1x%2_trans").arg(size.width()).arg(size.height()); 0105 break; 0106 case Element::WhiteTerritory: 0107 cacheName = QStringLiteral("white_territory_%1x%2").arg(size.width()).arg(size.height()); 0108 break; 0109 case Element::BlackStone: 0110 cacheName = QStringLiteral("black_stone_%1x%2").arg(size.width()).arg(size.height()); 0111 break; 0112 case Element::BlackStoneLast: 0113 cacheName = QStringLiteral("black_stone_last_%1x%2").arg(size.width()).arg(size.height()); 0114 break; 0115 case Element::BlackStoneTransparent: 0116 cacheName = QStringLiteral("black_stone_%1x%2_trans").arg(size.width()).arg(size.height()); 0117 break; 0118 case Element::BlackTerritory: 0119 cacheName = QStringLiteral("black_territory_%1x%2").arg(size.width()).arg(size.height()); 0120 break; 0121 case Element::PlacementMarker: 0122 cacheName = QStringLiteral("placement_marker_%1x%2").arg(size.width()).arg(size.height()); 0123 break; 0124 } 0125 0126 // Check if board element is already in cache, if not render it 0127 QPixmap pixmap; 0128 if (!QPixmapCache::find(cacheName, &pixmap)) { 0129 pixmap = QPixmap(size); 0130 pixmap.fill(Qt::transparent); 0131 QPainter p(&pixmap); 0132 switch (element) { 0133 case Element::Background: 0134 m_renderer->render(&p, QStringLiteral("background")); 0135 break; 0136 case Element::Board: 0137 m_renderer->render(&p, QStringLiteral("board")); 0138 break; 0139 case Element::HandicapMark: 0140 m_renderer->render(&p, QStringLiteral("handicap_mark")); 0141 break; 0142 case Element::WhiteStone: 0143 m_renderer->render(&p, QStringLiteral("white_stone")); 0144 break; 0145 case Element::WhiteStoneLast: 0146 m_renderer->render(&p, QStringLiteral("white_stone_last")); 0147 break; 0148 case Element::WhiteStoneTransparent: 0149 p.setOpacity(0.5); 0150 m_renderer->render(&p, QStringLiteral("white_stone")); 0151 break; 0152 case Element::WhiteTerritory: 0153 m_renderer->render(&p, QStringLiteral("white_territory")); 0154 break; 0155 case Element::BlackStone: 0156 m_renderer->render(&p, QStringLiteral("black_stone")); 0157 break; 0158 case Element::BlackStoneLast: 0159 m_renderer->render(&p, QStringLiteral("black_stone_last")); 0160 break; 0161 case Element::BlackStoneTransparent: 0162 p.setOpacity(0.5); 0163 m_renderer->render(&p, QStringLiteral("black_stone")); 0164 break; 0165 case Element::BlackTerritory: 0166 m_renderer->render(&p, QStringLiteral("black_territory")); 0167 break; 0168 case Element::PlacementMarker: 0169 m_renderer->render(&p, QStringLiteral("placement_marker")); 0170 break; 0171 } 0172 QPixmapCache::insert(cacheName, pixmap); 0173 } 0174 return pixmap; 0175 } 0176 0177 QSize ThemeRenderer::elementSize(Element element) const 0178 { 0179 QRectF sizeRect; 0180 switch(element) { 0181 case Element::Background: 0182 sizeRect = m_renderer->boundsOnElement(QStringLiteral("background")); 0183 break; 0184 case Element::Board: 0185 sizeRect = m_renderer->boundsOnElement(QStringLiteral("board")); 0186 break; 0187 case Element::HandicapMark: 0188 sizeRect = m_renderer->boundsOnElement(QStringLiteral("handicap_mark")); 0189 break; 0190 case Element::WhiteStone: 0191 sizeRect = m_renderer->boundsOnElement(QStringLiteral("white_stone")); 0192 break; 0193 case Element::WhiteStoneLast: 0194 sizeRect = m_renderer->boundsOnElement(QStringLiteral("white_stone")); 0195 break; 0196 case Element::WhiteStoneTransparent: 0197 sizeRect = m_renderer->boundsOnElement(QStringLiteral("white_stone")); 0198 break; 0199 case Element::WhiteTerritory: 0200 sizeRect = m_renderer->boundsOnElement(QStringLiteral("white_territory")); 0201 break; 0202 case Element::BlackStone: 0203 sizeRect = m_renderer->boundsOnElement(QStringLiteral("black_stone")); 0204 break; 0205 case Element::BlackStoneLast: 0206 sizeRect = m_renderer->boundsOnElement(QStringLiteral("black_stone")); 0207 break; 0208 case Element::BlackStoneTransparent: 0209 sizeRect = m_renderer->boundsOnElement(QStringLiteral("black_stone")); 0210 break; 0211 case Element::BlackTerritory: 0212 sizeRect = m_renderer->boundsOnElement(QStringLiteral("black_territory")); 0213 break; 0214 case Element::PlacementMarker: 0215 sizeRect = m_renderer->boundsOnElement(QStringLiteral("placement_marker")); 0216 break; 0217 } 0218 return QSize(static_cast<int>(sizeRect.width()), static_cast<int>(sizeRect.height())); 0219 } 0220 0221 } // End of namespace Kigo 0222 0223 #include "moc_themerenderer.cpp"