00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "pixmaploader.h"
00022
00023 #include <QtGui/QApplication>
00024 #include <QtGui/QBitmap>
00025 #include <QtCore/QBool>
00026 #include <QtGui/QImage>
00027 #include <QtGui/QPainter>
00028 #include <QtGui/QPixmap>
00029 #include <QtGui/QPixmapCache>
00030
00031
00032 #include "pixmaps.keramik"
00033
00034 using namespace Keramik;
00035
00036 PixmapLoader* PixmapLoader::s_instance = 0;
00037
00038 PixmapLoader::PixmapLoader()
00039
00040 {
00041 m_pixmapCache.setMaxCost(327680);
00042
00043 for (int c=0; c<256; c++)
00044 clamp[c]=static_cast<unsigned char>(c);
00045
00046 for (int c=256; c<540; c++)
00047 clamp[c] = 255;
00048
00049 }
00050
00051 void PixmapLoader::clear()
00052 {
00053
00054 }
00055
00056 QImage* PixmapLoader::getDisabled(int name, const QColor& color, const QColor& back, bool blend)
00057 {
00058 const KeramikEmbedImage* edata = KeramikGetDbImage(name);
00059 if (!edata)
00060 return 0;
00061
00062
00063
00064
00065 QImage::Format format = ( edata->haveAlpha && !blend ? QImage::Format_ARGB32 : QImage::Format_RGB32 );
00066 QImage* img = new QImage(edata->width, edata->height, format);
00067
00068
00069
00070
00071 quint32 r, g,b;
00072 quint32 i = qGray(color.rgb());
00073 r = (3*color.red()+i)>>2;
00074 g = (3*color.green()+i)>>2;
00075 b = (3*color.blue()+i)>>2;
00076
00077 quint32 br = back.red(), bg = back.green(), bb = back.blue();
00078
00079
00080 if (edata->haveAlpha)
00081 {
00082 if (blend)
00083 {
00084 quint32* write = reinterpret_cast< quint32* >(img->bits() );
00085 int size = img->width()*img->height() * 3;
00086
00087 for (int pos = 0; pos < size; pos+=3)
00088 {
00089 quint32 scale = edata->data[pos];
00090 quint32 add = (edata->data[pos+1]*i+127)>>8;
00091 quint32 alpha = edata->data[pos+2];
00092 quint32 destAlpha = 256 - alpha;
00093
00094 quint32 rr = clamp[((r*scale+127)>>8) + add];
00095 quint32 rg = clamp[((g*scale+127)>>8) + add];
00096 quint32 rb = clamp[((b*scale+127)>>8) + add];
00097
00098 *write =qRgb(((rr*alpha+127)>>8) + ((br*destAlpha+127)>>8),
00099 ((rg*alpha+127)>>8) + ((bg*destAlpha+127)>>8),
00100 ((rb*alpha+127)>>8) + ((bb*destAlpha+127)>>8));
00101
00102 write++;
00103 }
00104 }
00105 else
00106 {
00107 quint32* write = reinterpret_cast< quint32* >(img->bits() );
00108 int size = img->width()*img->height() * 3;
00109
00110 for (int pos = 0; pos < size; pos+=3)
00111 {
00112 quint32 scale = edata->data[pos];
00113 quint32 add = (edata->data[pos+1]*i+127)>>8;
00114 quint32 alpha = edata->data[pos+2];
00115
00116 quint32 rr = clamp[((r*scale+127)>>8) + add];
00117 quint32 rg = clamp[((g*scale+127)>>8) + add];
00118 quint32 rb = clamp[((b*scale+127)>>8) + add];
00119
00120 *write =qRgba(rr, rg, rb, alpha);
00121
00122 write++;
00123 }
00124
00125 }
00126 }
00127 else
00128 {
00129 quint32* write = reinterpret_cast< quint32* >(img->bits() );
00130 int size = img->width()*img->height() * 2;
00131
00132 for (int pos = 0; pos < size; pos+=2)
00133 {
00134 quint32 scale = edata->data[pos];
00135 quint32 add = (edata->data[pos+1]*i+127)>>8;
00136 quint32 rr = clamp[((r*scale+127)>>8) + add];
00137 quint32 rg = clamp[((g*scale+127)>>8) + add];
00138 quint32 rb = clamp[((b*scale+127)>>8) + add];
00139 *write =qRgb(rr, rg, rb);
00140 write++;
00141 }
00142 }
00143
00144 return img;
00145 }
00146
00147 QImage* PixmapLoader::getColored(int name, const QColor& color, const QColor& back, bool blend)
00148 {
00149 const KeramikEmbedImage* edata = KeramikGetDbImage(name);
00150 if (!edata)
00151 return 0;
00152
00153
00154 QImage::Format format = ( edata->haveAlpha && !blend ? QImage::Format_ARGB32 : QImage::Format_RGB32 );
00155 QImage* img = new QImage(edata->width, edata->height, format);
00156
00157
00158 quint32 r, g,b;
00159 r = color.red() + 2;
00160 g = color.green() + 2;
00161 b = color.blue() + 2;
00162
00163
00164
00165 quint32 br = back.red(), bg = back.green(), bb = back.blue();
00166
00167 if (edata->haveAlpha)
00168 {
00169 if (blend)
00170 {
00171 quint32* write = reinterpret_cast< quint32* >(img->bits() );
00172 int size = img->width()*img->height() * 3;
00173 for (int pos = 0; pos < size; pos+=3)
00174 {
00175 quint32 scale = edata->data[pos];
00176 quint32 add = edata->data[pos+1];
00177 quint32 alpha = edata->data[pos+2];
00178 quint32 destAlpha = 256 - alpha;
00179
00180 if (scale != 0)
00181 add = add*5/4;
00182
00183 quint32 rr = clamp[((r*scale+127)>>8) + add];
00184 quint32 rg = clamp[((g*scale+127)>>8) + add];
00185 quint32 rb = clamp[((b*scale+127)>>8) + add];
00186
00187 *write =qRgb(((rr*alpha+127)>>8) + ((br*destAlpha+127)>>8),
00188 ((rg*alpha+127)>>8) + ((bg*destAlpha+127)>>8),
00189 ((rb*alpha+127)>>8) + ((bb*destAlpha+127)>>8));
00190
00191 write++;
00192 }
00193 }
00194 else
00195 {
00196 quint32* write = reinterpret_cast< quint32* >(img->bits() );
00197 int size = img->width()*img->height() * 3;
00198
00199 for (int pos = 0; pos < size; pos+=3)
00200 {
00201 quint32 scale = edata->data[pos];
00202 quint32 add = edata->data[pos+1];
00203 quint32 alpha = edata->data[pos+2];
00204 if (scale != 0)
00205 add = add*5/4;
00206
00207 quint32 rr = clamp[((r*scale+127)>>8) + add];
00208 quint32 rg = clamp[((g*scale+127)>>8) + add];
00209 quint32 rb = clamp[((b*scale+127)>>8) + add];
00210
00211 *write =qRgba(rr, rg, rb, alpha);
00212 write++;
00213 }
00214 }
00215 }
00216 else
00217 {
00218 quint32* write = reinterpret_cast< quint32* >(img->bits() );
00219 int size = img->width()*img->height() * 2;
00220
00221 for (int pos = 0; pos < size; pos+=2)
00222 {
00223 quint32 scale = edata->data[pos];
00224 quint32 add = edata->data[pos+1];
00225 if (scale != 0)
00226 add = add*5/4;
00227
00228 quint32 rr = clamp[((r*scale+127)>>8) + add];
00229 quint32 rg = clamp[((g*scale+127)>>8) + add];
00230 quint32 rb = clamp[((b*scale+127)>>8) + add];
00231
00232
00233 *write = qRgb(rr, rg, rb);
00234 write++;
00235 }
00236 }
00237
00238 return img;
00239 }
00240
00241 QPixmap PixmapLoader::pixmap( int name, const QColor& color, const QColor& bg, bool disabled, bool blend )
00242 {
00243 return scale(name, 0, 0, color, bg, disabled, blend);
00244 }
00245
00246
00247 QPixmap PixmapLoader::scale( int name, int width, int height, const QColor& color, const QColor& bg, bool disabled, bool blend )
00248 {
00249 KeramikCacheEntry entry(name, color, bg, disabled, blend, width, height);
00250 KeramikCacheEntry* cacheEntry;
00251
00252 int key = entry.key();
00253
00254 if ((cacheEntry = m_pixmapCache.take(key)))
00255 {
00256 if (entry == *cacheEntry)
00257 return *cacheEntry->m_pixmap;
00258 }
00259
00260
00261 QImage* img = 0;
00262 QPixmap* result = 0;
00263
00264 if (disabled)
00265 img = getDisabled(name, color, bg, blend);
00266 else
00267 img = getColored(name, color, bg, blend);
00268
00269 if (!img)
00270 {
00271 KeramikCacheEntry* toAdd = new KeramikCacheEntry(entry);
00272 toAdd->m_pixmap = new QPixmap();
00273 m_pixmapCache.insert(key, toAdd, 16);
00274 return QPixmap();
00275 }
00276
00277 if (width == 0 && height == 0)
00278 result = new QPixmap(QPixmap::fromImage(*img));
00279 else
00280 result = new QPixmap(QPixmap::fromImage(img->scaled(width ? width : img->width(),
00281 height ? height : img->height())));
00282
00283
00284
00285 KeramikCacheEntry* toAdd = new KeramikCacheEntry(entry);
00286 toAdd->m_pixmap = result;
00287 delete img;
00288
00289 if (!m_pixmapCache.insert(key, toAdd, result->width()*result->height()*result->depth()/8)) {
00290
00291 QPixmap toRet = *result;
00292 delete toAdd;
00293 return toRet;
00294 }
00295
00296 return *result;
00297 }
00298
00299 QSize PixmapLoader::size( int id )
00300 {
00301 const KeramikEmbedImage* edata = KeramikGetDbImage(id);
00302 if (!edata)
00303 return QSize(0,0);
00304 return QSize(edata->width, edata->height);
00305 }
00306
00307 void TilePainter::draw( QPainter *p, int x, int y, int width, int height, const QColor& color, const QColor& bg, bool disabled, PaintMode mode )
00308 {
00309 if (mode == PaintTrivialMask)
00310 {
00311 p->fillRect(x, y, width, height, Qt::color1);
00312 return;
00313 }
00314
00315 bool swBlend = (mode != PaintFullBlend);
00316 unsigned int scaledColumns = 0, scaledRows = 0, lastScaledColumn = 0, lastScaledRow = 0;
00317 int scaleWidth = width, scaleHeight = height;
00318
00319
00320
00321
00322
00323
00324 for ( unsigned int col = 0; col < columns(); ++col )
00325 if ( columnMode( col ) != Fixed )
00326 {
00327 scaledColumns++;
00328 lastScaledColumn = col;
00329 }
00330 else scaleWidth -= PixmapLoader::the().size (absTileName( col, 0 ) ).width();
00331
00332 for ( unsigned int row = 0; row < rows(); ++row )
00333 if ( rowMode( row ) != Fixed )
00334 {
00335 scaledRows++;
00336 lastScaledRow = row;
00337 }
00338 else scaleHeight -= PixmapLoader::the().size (absTileName( 0, row ) ).height();
00339
00340
00341 if ( scaleWidth < 0 ) scaleWidth = 0;
00342 if ( scaleHeight < 0 ) scaleHeight = 0;
00343
00344
00345 int ypos = y;
00346
00347
00348 if ( scaleHeight && !scaledRows )
00349 ypos += scaleHeight / 2;
00350
00351 for ( unsigned int row = 0; row < rows(); ++row )
00352 {
00353 int xpos = x;
00354
00355
00356 if ( scaleWidth && !scaledColumns )
00357 xpos += scaleWidth / 2;
00358
00359
00360
00361 int h = rowMode( row ) == Fixed ? 0 : scaleHeight / scaledRows;
00362
00363
00364 if ( scaledRows && row == lastScaledRow )
00365 {
00366 int allocatedEvenly = scaleHeight / scaledRows * scaledRows;
00367 h += scaleHeight - allocatedEvenly;
00368 }
00369
00370
00371
00372 int realH = h ? h : PixmapLoader::the().size (absTileName( 0, row ) ).height();
00373
00374
00375 if (rowMode( row ) != Fixed && h == 0)
00376 continue;
00377
00378
00379
00380 if ( rowMode( row ) == Tiled )
00381 h = 0;
00382
00383 for ( unsigned int col = 0; col < columns(); ++col )
00384 {
00385
00386 int w = columnMode( col ) == Fixed ? 0 : scaleWidth / scaledColumns;
00387
00388
00389 int tileW = PixmapLoader::the().size (absTileName( col, row ) ).width();
00390
00391
00392 if ( scaledColumns && col == lastScaledColumn ) w += scaleWidth - scaleWidth / scaledColumns * scaledColumns;
00393
00394
00395 int realW = w ? w : tileW;
00396
00397
00398 if (columnMode( col ) != Fixed && w == 0)
00399 continue;
00400
00401
00402 if ( columnMode( col ) == Tiled )
00403 w = 0;
00404
00405
00406 if ( tileW )
00407 {
00408
00409 if ( w || h )
00410 {
00411 if (mode != PaintMask)
00412 {
00413 p->drawTiledPixmap( xpos, ypos, realW, realH, scale( col, row, w, h, color, bg, disabled, swBlend ) );
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 }
00428 else
00429 {
00430
00431 if (mode != PaintMask)
00432 {
00433 p->drawTiledPixmap( xpos, ypos, realW, realH, tile( col, row, color, bg, disabled, swBlend ) );
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 }
00449 }
00450
00451
00452 xpos += realW;
00453 }
00454
00455
00456 ypos += realH;
00457 }
00458 }
00459
00460 RectTilePainter::RectTilePainter( int name,
00461 bool scaleH, bool scaleV,
00462 unsigned int columns, unsigned int rows )
00463 : TilePainter( name ),
00464 m_scaleH( scaleH ),
00465 m_scaleV( scaleV )
00466 {
00467 m_columns = columns;
00468 m_rows = rows;
00469
00470 TileMode mh = m_scaleH ? Scaled : Tiled;
00471 TileMode mv = m_scaleV ? Scaled : Tiled;
00472 for (int c=0; c<4; c++)
00473 {
00474 if (c != 1)
00475 colMde[c] = Fixed;
00476 else
00477 colMde[c] = mh;
00478 }
00479
00480 for (int c=0; c<4; c++)
00481 {
00482 if (c != 1)
00483 rowMde[c] = Fixed;
00484 else
00485 rowMde[c] = mv;
00486 }
00487
00488 }
00489
00490 int RectTilePainter::tileName( unsigned int column, unsigned int row ) const
00491 {
00492 return row *3 + column;
00493 }
00494
00495 ActiveTabPainter::ActiveTabPainter( bool bottom )
00496 : RectTilePainter( bottom? keramik_tab_bottom_active: keramik_tab_top_active, false),
00497 m_bottom( bottom )
00498 {
00499 m_rows = 2;
00500 if (m_bottom)
00501 {
00502 rowMde[0] = rowMde[2] = rowMde[3] = Scaled;
00503 rowMde[1] = Fixed;
00504 }
00505 else
00506 {
00507 rowMde[0] = rowMde[2] = rowMde[3] = Fixed;
00508 rowMde[1] = Scaled;
00509 }
00510 }
00511
00512 int ActiveTabPainter::tileName( unsigned int column, unsigned int row ) const
00513 {
00514 if ( m_bottom )
00515 return RectTilePainter::tileName( column, row + 1 );
00516 return RectTilePainter::tileName( column, row );
00517 }
00518
00519
00520 InactiveTabPainter::InactiveTabPainter( QStyleOptionTab::TabPosition mode, bool bottom )
00521 : RectTilePainter( bottom? keramik_tab_bottom_inactive: keramik_tab_top_inactive, false),
00522 m_mode( mode ), m_bottom( bottom )
00523 {
00524 m_rows = 2;
00525 if (m_bottom)
00526 {
00527 rowMde[0] = Scaled;
00528 rowMde[1] = Fixed;
00529 }
00530 else
00531 {
00532 rowMde[0] = Fixed;
00533 rowMde[1] = Scaled;
00534 }
00535
00566
00567
00568 m_columns = (m_mode == QStyleOptionTab::End ? 3 : 2);
00569 }
00570
00571
00572
00573 int InactiveTabPainter::tileName( unsigned int column, unsigned int row ) const
00574 {
00575
00576
00577 if ( column == 0 && m_mode != QStyleOptionTab::Beginning)
00578 return KeramikTileSeparator;
00579 if ( m_bottom )
00580 return RectTilePainter::tileName( column, row + 1 );
00581 return RectTilePainter::tileName( column, row );
00582 }
00583
00584
00585 ScrollBarPainter::ScrollBarPainter( int type, int count, bool horizontal )
00586 : TilePainter( name( horizontal ) ),
00587 m_type( type ),
00588 m_count( count ),
00589 m_horizontal( horizontal )
00590 {
00591 for (int c=0; c<5; c++)
00592 {
00593 if ( !m_horizontal || !( c % 2 ) ) colMde[c] = Fixed;
00594 else colMde[c] = Tiled;
00595
00596 if ( m_horizontal || !( c % 2 ) ) rowMde[c] = Fixed;
00597 else rowMde[c] = Tiled;
00598 }
00599
00600 m_columns = m_horizontal ? m_count : 1;
00601 m_rows = m_horizontal ? 1 : m_count;
00602
00603 }
00604
00605
00606
00607 int ScrollBarPainter::name( bool horizontal )
00608 {
00609 return horizontal? keramik_scrollbar_hbar: keramik_scrollbar_vbar;
00610 }
00611
00612 int ScrollBarPainter::tileName( unsigned int column, unsigned int row ) const
00613 {
00614 unsigned int num = ( column ? column : row ) + 1;
00615 if ( m_count == 5 )
00616 if ( num == 3 ) num = 4;
00617 else if ( num == 4 ) num = 2;
00618 else if ( num == 5 ) num = 3;
00619
00620 return m_type + (num-1)*16;
00621 }
00622
00623 int SpinBoxPainter::tileName( unsigned int column, unsigned int ) const
00624 {
00625 return column + 1;
00626 }
00627
00628
00629