• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KStyles

pixmaploader.cpp

Go to the documentation of this file.
00001 /*
00002    Copyright (c) 2002 Malte Starostik <malte@kde.org>
00003              (c) 2002,2003 Maksim Orlovich <maksim@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
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     //size of 100? m_pixmapCache.
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     //m_cache.clear();
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     //Like getColored, but desaturate a bit, and lower gamma..
00063 
00064     //Create a real image...
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     //OK, now, fill it in, using the color..
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     //Create a real image...
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     //OK, now, fill it in, using the color..
00158     quint32 r, g,b;
00159     r = color.red() + 2;
00160     g = color.green() + 2;
00161     b = color.blue() + 2;
00162 
00163 //  int i = qGray(color.rgb());
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) //True match!
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     //Qt::IgnoreAspectRatio,
00283     //Qt::SmoothTransformation));
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     //scaleWidth, scaleHeight are calculated to contain the area available
00320     //for all tiled and stretched columns/rows respectively.
00321     //This is need to redistribute the area remaining after painting
00322     //the "fixed" elements. We also keep track of the last col and row
00323     //being scaled so rounding errors don't cause us to be short a pixel or so.
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     //Center vertically if everything is fixed but there is extra room remaining
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         //Center horizontally if extra space and no where to redistribute it to...
00356         if ( scaleWidth && !scaledColumns )
00357             xpos += scaleWidth / 2;
00358 
00359         //If not fixed vertically, calculate our share of space available
00360         //for scalable rows.
00361         int h = rowMode( row ) == Fixed ? 0 : scaleHeight / scaledRows;
00362 
00363         //Redistribute any "extra" pixels to the last scaleable row.
00364         if ( scaledRows && row == lastScaledRow )
00365         {
00366             int allocatedEvenly = scaleHeight / scaledRows * scaledRows;
00367             h += scaleHeight - allocatedEvenly;
00368         }
00369 
00370 
00371         //If we're fixed, get the height from the pixmap itself.
00372         int realH = h ? h : PixmapLoader::the().size (absTileName( 0, row ) ).height();
00373 
00374         //Skip non-fitting stretched/tiled rows, too.
00375         if (rowMode( row ) != Fixed && h == 0)
00376             continue;
00377 
00378 
00379         //Set h to 0 to denote that we aren't scaling
00380         if ( rowMode( row ) == Tiled )
00381             h = 0;
00382 
00383         for ( unsigned int col = 0; col < columns(); ++col )
00384         {
00385             //Calculate width for rows that aren't fixed.
00386             int w = columnMode( col ) == Fixed ? 0 : scaleWidth / scaledColumns;
00387 
00388             //Get the width of the pixmap..
00389             int tileW = PixmapLoader::the().size (absTileName( col, row ) ).width();
00390 
00391             //Redistribute any extra pixels..
00392             if ( scaledColumns && col == lastScaledColumn ) w += scaleWidth - scaleWidth / scaledColumns * scaledColumns;
00393 
00394             //The width to use...
00395             int realW = w ? w : tileW;
00396 
00397             //Skip any non-fitting stretched/tiled columns
00398             if (columnMode( col ) != Fixed && w == 0)
00399                 continue;
00400 
00401             //Set w to 0 to denote that we aren't scaling
00402             if ( columnMode( col ) == Tiled )
00403                 w = 0;
00404 
00405             //If we do indeed have a pixmap..
00406             if ( tileW )
00407             {
00408                 //If scaling in either direction.
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 /*                  else
00416                     {
00417                         const QBitmap* mask  = scale( col, row, w, h, color,  bg, disabled, false ).mask();
00418                         if (mask)
00419                         {
00420                             //### ?p->setBackgroundColor(Qt::color0);
00421                             p->setPen(Qt::color1);
00422                             p->drawTiledPixmap( xpos, ypos, realW, realH, *mask);
00423                         }
00424                         else
00425                             p->fillRect ( xpos, ypos, realW, realH, Qt::color1);
00426                     }*/
00427                 }
00428                 else
00429                 {
00430                     //Tiling (or fixed, the same really)
00431                     if (mode != PaintMask)
00432                     {
00433                         p->drawTiledPixmap( xpos, ypos, realW, realH, tile( col, row, color, bg, disabled, swBlend ) );
00434                     }
00435 /*                  else
00436                     {
00437                         const QBitmap* mask = tile( col, row, color, bg, disabled, false ).mask();
00438                         if (mask)
00439                         {
00440                             // ### ? p->setBackgroundColor(Qt::color0);
00441                             p->setPen(Qt::color1);
00442                             p->drawTiledPixmap( xpos, ypos, realW, realH, *mask);
00443                         }
00444                         else
00445                             p->fillRect ( xpos, ypos, realW, realH, Qt::color1);
00446 
00447                     }*/
00448                 }
00449             }
00450 
00451             //Advance horizontal position
00452             xpos += realW;
00453         }
00454 
00455         //Advance vertical position
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     //Mode rightMost = QApplication::isRightToLeft() ? First : Last;
00567     //### RTL?
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     //### RTL?
00576     //Mode leftMost = QApplication::isRightToLeft() ? Last : First;
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 // vim: ts=4 sw=4 noet
00629 // kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;

KStyles

Skip menu "KStyles"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KCMShell
  • KNotify
  • KStyles
  • Nepomuk Daemons
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal