summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/skin.cpp39
1 files changed, 35 insertions, 4 deletions
diff --git a/noncore/multimedia/opieplayer2/skin.cpp b/noncore/multimedia/opieplayer2/skin.cpp
index 5013bb4..0f49862 100644
--- a/noncore/multimedia/opieplayer2/skin.cpp
+++ b/noncore/multimedia/opieplayer2/skin.cpp
@@ -8,100 +8,103 @@
8 modify it under the terms of the GNU General Public 8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either 9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version. 10 version 2 of the License, or (at your option) any later version.
11 11
12 This program is distributed in the hope that it will be useful, 12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details. 15 General Public License for more details.
16 16
17 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to 18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. 20 Boston, MA 02111-1307, USA.
21*/ 21*/
22 22
23#include "skin.h" 23#include "skin.h"
24#include "singleton.h" 24#include "singleton.h"
25 25
26#include <qcache.h> 26#include <qcache.h>
27#include <qmap.h> 27#include <qmap.h>
28 28
29#include <qpe/resource.h> 29#include <qpe/resource.h>
30#include <qpe/config.h> 30#include <qpe/config.h>
31 31
32#include <assert.h> 32#include <assert.h>
33 33
34struct SkinData 34struct SkinData
35{ 35{
36 typedef QMap<QString, QImage> ButtonMaskImageMap; 36 typedef QMap<QString, QImage> ButtonMaskImageMap;
37 37
38 QImage backgroundImage; 38 QImage backgroundImage;
39 QImage buttonUpImage; 39 QImage buttonUpImage;
40 QImage buttonDownImage; 40 QImage buttonDownImage;
41 QImage buttonMask; 41 QImage buttonMask;
42 ButtonMaskImageMap buttonMasks; 42 ButtonMaskImageMap buttonMasks;
43}; 43};
44 44
45class SkinCache : public Singleton<SkinCache> 45class SkinCache : public Singleton<SkinCache>
46{ 46{
47public: 47public:
48 SkinCache(); 48 SkinCache();
49 49
50 SkinData *lookupAndTake( const QString &skinPath, const QString &fileNameInfix ); 50 SkinData *lookupAndTake( const QString &skinPath, const QString &fileNameInfix );
51 51
52 void store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ); 52 void store( const QString &skinPath, const QString &fileNameInfix, SkinData *data );
53 53
54private: 54private:
55 typedef QCache<SkinData> DataCache; 55 typedef QCache<SkinData> DataCache;
56 typedef QCache<QPixmap> BackgroundPixmapCache; 56 typedef QCache<QImage> BackgroundImageCache;
57
58 template <class CacheType>
59 void store( const QCache<CacheType> &cache, const QString &key, CacheType *data );
57 60
58 DataCache m_cache; 61 DataCache m_cache;
59 BackgroundPixmapCache m_backgroundPixmapCache; 62 BackgroundImageCache m_backgroundImageCache;
60}; 63};
61 64
62Skin::Skin( const QString &name, const QString &fileNameInfix ) 65Skin::Skin( const QString &name, const QString &fileNameInfix )
63 : m_fileNameInfix( fileNameInfix ) 66 : m_fileNameInfix( fileNameInfix )
64{ 67{
65 init( name ); 68 init( name );
66} 69}
67 70
68Skin::Skin( const QString &fileNameInfix ) 71Skin::Skin( const QString &fileNameInfix )
69 : m_fileNameInfix( fileNameInfix ) 72 : m_fileNameInfix( fileNameInfix )
70{ 73{
71 init( defaultSkinName() ); 74 init( defaultSkinName() );
72} 75}
73 76
74Skin::~Skin() 77Skin::~Skin()
75{ 78{
76 SkinCache::self().store( m_skinPath, m_fileNameInfix, d ); 79 SkinCache::self().store( m_skinPath, m_fileNameInfix, d );
77} 80}
78 81
79void Skin::init( const QString &name ) 82void Skin::init( const QString &name )
80{ 83{
81 m_skinPath = "opieplayer2/skins/" + name; 84 m_skinPath = "opieplayer2/skins/" + name;
82 d = SkinCache::self().lookupAndTake( m_skinPath, m_fileNameInfix ); 85 d = SkinCache::self().lookupAndTake( m_skinPath, m_fileNameInfix );
83} 86}
84 87
85void Skin::preload( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) 88void Skin::preload( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount )
86{ 89{
87 backgroundImage(); 90 backgroundImage();
88 buttonUpImage(); 91 buttonUpImage();
89 buttonDownImage(); 92 buttonDownImage();
90 ( void )buttonMask( skinButtonInfo, buttonCount ); 93 ( void )buttonMask( skinButtonInfo, buttonCount );
91} 94}
92 95
93QImage Skin::backgroundImage() const 96QImage Skin::backgroundImage() const
94{ 97{
95 if ( d->backgroundImage.isNull() ) 98 if ( d->backgroundImage.isNull() )
96 d->backgroundImage = loadImage( QString( "%1/background" ).arg( m_skinPath ) ); 99 d->backgroundImage = loadImage( QString( "%1/background" ).arg( m_skinPath ) );
97 return d->backgroundImage; 100 return d->backgroundImage;
98} 101}
99 102
100QImage Skin::buttonUpImage() const 103QImage Skin::buttonUpImage() const
101{ 104{
102 if ( d->buttonUpImage.isNull() ) 105 if ( d->buttonUpImage.isNull() )
103 d->buttonUpImage = loadImage( QString( "%1/skin%2_up" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); 106 d->buttonUpImage = loadImage( QString( "%1/skin%2_up" ).arg( m_skinPath ).arg( m_fileNameInfix ) );
104 return d->buttonUpImage; 107 return d->buttonUpImage;
105} 108}
106 109
107QImage Skin::buttonDownImage() const 110QImage Skin::buttonDownImage() const
@@ -121,90 +124,118 @@ QImage Skin::buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint
121 d->buttonMask = QImage( buttonAreaSize, 8, 255 ); 124 d->buttonMask = QImage( buttonAreaSize, 8, 255 );
122 d->buttonMask.fill( 0 ); 125 d->buttonMask.fill( 0 );
123 126
124 for ( uint i = 0; i < buttonCount; ++i ) 127 for ( uint i = 0; i < buttonCount; ++i )
125 addButtonToMask( skinButtonInfo[ i ].command + 1, buttonMaskImage( skinButtonInfo[ i ].fileName ) ); 128 addButtonToMask( skinButtonInfo[ i ].command + 1, buttonMaskImage( skinButtonInfo[ i ].fileName ) );
126 129
127 return d->buttonMask; 130 return d->buttonMask;
128} 131}
129 132
130void Skin::addButtonToMask( int tag, const QImage &maskImage ) const 133void Skin::addButtonToMask( int tag, const QImage &maskImage ) const
131{ 134{
132 if ( maskImage.isNull() ) 135 if ( maskImage.isNull() )
133 return; 136 return;
134 137
135 uchar **dest = d->buttonMask.jumpTable(); 138 uchar **dest = d->buttonMask.jumpTable();
136 for ( int y = 0; y < d->buttonMask.height(); y++ ) { 139 for ( int y = 0; y < d->buttonMask.height(); y++ ) {
137 uchar *line = dest[y]; 140 uchar *line = dest[y];
138 for ( int x = 0; x < d->buttonMask.width(); x++ ) 141 for ( int x = 0; x < d->buttonMask.width(); x++ )
139 if ( !qRed( maskImage.pixel( x, y ) ) ) 142 if ( !qRed( maskImage.pixel( x, y ) ) )
140 line[x] = tag; 143 line[x] = tag;
141 } 144 }
142} 145}
143 146
144QImage Skin::buttonMaskImage( const QString &fileName ) const 147QImage Skin::buttonMaskImage( const QString &fileName ) const
145{ 148{
146 SkinData::ButtonMaskImageMap::Iterator it = d->buttonMasks.find( fileName ); 149 SkinData::ButtonMaskImageMap::Iterator it = d->buttonMasks.find( fileName );
147 if ( it == d->buttonMasks.end() ) { 150 if ( it == d->buttonMasks.end() ) {
148 QString prefix = m_skinPath + QString::fromLatin1( "/skin%1_mask_" ).arg( m_fileNameInfix ); 151 QString prefix = m_skinPath + QString::fromLatin1( "/skin%1_mask_" ).arg( m_fileNameInfix );
149 QString path = prefix + fileName + ".png"; 152 QString path = prefix + fileName + ".png";
150 it = d->buttonMasks.insert( fileName, loadImage( path ) ); 153 it = d->buttonMasks.insert( fileName, loadImage( path ) );
151 } 154 }
152 return *it; 155 return *it;
153} 156}
154 157
155QString Skin::defaultSkinName() 158QString Skin::defaultSkinName()
156{ 159{
157 Config cfg( "OpiePlayer" ); 160 Config cfg( "OpiePlayer" );
158 cfg.setGroup( "Options" ); 161 cfg.setGroup( "Options" );
159 return cfg.readEntry( "Skin", "default" ); 162 return cfg.readEntry( "Skin", "default" );
160} 163}
161 164
162QImage Skin::loadImage( const QString &fileName ) 165QImage Skin::loadImage( const QString &fileName )
163{ 166{
164 return QImage( Resource::findPixmap( fileName ) ); 167 return QImage( Resource::findPixmap( fileName ) );
165} 168}
166 169
167SkinCache::SkinCache() 170SkinCache::SkinCache()
168{ 171{
172 // let's say we cache two skins (audio+video) at maximum
173 m_cache.setMaxCost( 2 );
174 // ... and one background pixmap
175 m_backgroundImageCache.setMaxCost( 1 );
169} 176}
170 177
171SkinData *SkinCache::lookupAndTake( const QString &skinPath, const QString &fileNameInfix ) 178SkinData *SkinCache::lookupAndTake( const QString &skinPath, const QString &fileNameInfix )
172{ 179{
173 return new SkinData; 180 QString key = skinPath + fileNameInfix;
181
182 SkinData *data = m_cache.take( key );
183 if ( !data )
184 data = new SkinData;
185
186 QImage *bgImage = m_backgroundImageCache.find( skinPath );
187 if ( bgImage )
188 data->backgroundImage = *bgImage;
189 else
190 data->backgroundImage = QImage();
191
192 return data;
174} 193}
175 194
176void SkinCache::store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ) 195void SkinCache::store( const QString &skinPath, const QString &fileNameInfix, SkinData *data )
177{ 196{
178 delete data; 197 QImage *backgroundImage = new QImage( data->backgroundImage );
198
199 data->backgroundImage = QImage();
200
201 QString key = skinPath + fileNameInfix;
202
203 if ( m_cache.find( key, false /*ref*/ ) != 0 ||
204 !m_cache.insert( key, data ) )
205 delete data;
206
207 if ( m_backgroundImageCache.find( skinPath, false /*ref*/ ) != 0 ||
208 !m_backgroundImageCache.insert( skinPath, backgroundImage ) )
209 delete backgroundImage;
179} 210}
180 211
181SkinLoader::SkinLoader() 212SkinLoader::SkinLoader()
182{ 213{
183} 214}
184 215
185void SkinLoader::schedule( const QString &skinName, const QString &fileNameInfix, 216void SkinLoader::schedule( const QString &skinName, const QString &fileNameInfix,
186 const MediaWidget::SkinButtonInfo *skinButtonInfo, const uint buttonCount ) 217 const MediaWidget::SkinButtonInfo *skinButtonInfo, const uint buttonCount )
187{ 218{
188 assert( isRunning() == false ); 219 assert( isRunning() == false );
189 220
190 pendingSkins << Info( skinName, fileNameInfix, skinButtonInfo, buttonCount ); 221 pendingSkins << Info( skinName, fileNameInfix, skinButtonInfo, buttonCount );
191} 222}
192 223
193void SkinLoader::run() 224void SkinLoader::run()
194{ 225{
195 qDebug( "SkinLoader::run()" ); 226 qDebug( "SkinLoader::run()" );
196 for ( InfoList::ConstIterator it = pendingSkins.begin(); it != pendingSkins.end(); ++it ) 227 for ( InfoList::ConstIterator it = pendingSkins.begin(); it != pendingSkins.end(); ++it )
197 load( *it ); 228 load( *it );
198 qDebug( "SkinLoader is done." ); 229 qDebug( "SkinLoader is done." );
199} 230}
200 231
201void SkinLoader::load( const Info &nfo ) 232void SkinLoader::load( const Info &nfo )
202{ 233{
203 qDebug( "preloading %s with infix %s", nfo.skinName.ascii(), nfo.fileNameInfix.ascii() ); 234 qDebug( "preloading %s with infix %s", nfo.skinName.ascii(), nfo.fileNameInfix.ascii() );
204 235
205 Skin skin( nfo.skinName, nfo.fileNameInfix ); 236 Skin skin( nfo.skinName, nfo.fileNameInfix );
206 skin.preload( nfo.skinButtonInfo, nfo.buttonCount ); 237 skin.preload( nfo.skinButtonInfo, nfo.buttonCount );
207} 238}
208 239
209/* vim: et sw=4 ts=4 240/* vim: et sw=4 ts=4
210 */ 241 */