Back to index

kdeartwork  4.3.2
frame.cpp
Go to the documentation of this file.
00001 /*
00002  * Asciiquarium - Native KDE Screensaver based on the Asciiquarium program
00003  *    (c) Kirk Baucom <kbaucom@schizoid.com>, which you can find at
00004  *    http://www.robobunny.com/projects/asciiquarium/
00005  *
00006  * Ported to KDE by Maksim Orlovich <maksim@kde.org> and
00007  * Michael Pyne <michael.pyne@kdemail.net>.
00008  *
00009  * Copyright (c) 2003 Kirk Baucom     <kbaucom@schizoid.com>
00010  * Copyright (c) 2005 Maksim Orlovich <maksim@kde.org>
00011  * Copyright (c) 2005, 2008 Michael Pyne <michael.pyne@kdemail.net>
00012  *
00013  * This program is free software; you can redistribute it and/or
00014  * modify it under the terms of the GNU General Public License
00015  * as published by the Free Software Foundation; either version 2
00016  * of the License, or (at your option) any later version.
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License along with
00024  * this program; if not, write to the Free Software Foundation, Inc., 51
00025  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00026  */
00027 
00028 #include "frame.h"
00029 
00030 #include <kglobalsettings.h>
00031 #include <kdebug.h>
00032 
00033 #include <QtCore/QStringList>
00034 #include <QtGui/QImage>
00035 #include <QtGui/QFontMetrics>
00036 #include <QtGui/QPainter>
00037 #include <QtGui/QBitmap>
00038 
00039 void Frame::convertDataToPixmap(const Screen *screen)
00040 {
00041     if(!height() || !width()) {
00042         // Assume we're not ready to go.
00043         return;
00044     }
00045 
00046     int w = screen->cellWidth(), h = screen->cellHeight();
00047     QImage pix(width() * w, height() * h, QImage::Format_RGB32);
00048     pix.fill(Qt::white);
00049 
00050     QPainter p;
00051 
00052     p.begin(&pix);
00053 
00054     p.setCompositionMode(QPainter::CompositionMode_Source);
00055     p.setRenderHint(QPainter::TextAntialiasing);
00056     p.setFont(KGlobalSettings::fixedFont());
00057 
00058     QFontMetrics fm(p.fontMetrics());
00059 
00060     for(int j = 0; j < m_data.count(); ++j) {
00061         QVector<Screen::Pixel> row = m_data[j];
00062         if(row.isEmpty())
00063             continue;
00064 
00065         int first, last;
00066         for (first = 0; first < row.count() && row[first].letter == ' '; ++first)
00067             ;
00068 
00069         last = row.count() - 1; // Assume the end is already stripped.
00070 
00071         for(int i = first; i <= last; ++i) {
00072             if(row[i].letter == m_transparentChar)
00073                 continue;
00074 
00075             QRect r(i * w, j * h, w, h);
00076 
00077             p.setPen(row[i].color);
00078             p.fillRect(r, Qt::black); // Completely fill since drawText won't even in Opaque.
00079             p.drawText(r, Qt::AlignCenter, QString(row[i].letter));
00080         }
00081     }
00082 
00083     p.end();
00084 
00085     QImage eraseImage(pix.size(), QImage::Format_RGB32);
00086     eraseImage.fill(qRgb(0, 0, 0));
00087 
00088     // Since QPixmap::fill() seems broken on some nVidia drivers????
00089     m_erasePixmap = QPixmap::fromImage(eraseImage);
00090     QBitmap mask = QBitmap::fromImage(pix.createHeuristicMask());
00091     m_pixmap = QPixmap::fromImage(pix);
00092     m_pixmap.setMask(mask);
00093 
00094     // Clear m_data to save a wee bit of memory.
00095     m_data.clear();
00096 }
00097 
00098 Frame::Frame (const QString& text, const QString& mask, const QRgb& defaultColor, QChar transparent)
00099 {
00100     //First, process the pixels.
00101 
00102     QStringList rows = text.split('\n');
00103     m_height = rows.size();
00104     m_width  = 0;
00105     m_transparentChar = transparent;
00106 
00107     // curRow is deliberately not const& as we must modify it a bit in the loop.  It does
00108     // not alias strings in rows however otherwise we would have to manually make a copy.
00109     foreach(QString curRow, rows) { //krazy:exclude=foreach
00110         QVector<Screen::Pixel> row;
00111         int strLen = curRow.length(); // make sure this is cached.
00112 
00113         // ?? is changed to {} for trigraph purposes, change it back.
00114         curRow.replace("{}", "??");
00115 
00116         for (int pos = 0; pos < strLen; ++pos)
00117         {
00118             Screen::Pixel p;
00119             p.letter = curRow.at(pos).unicode();
00120             p.color  = defaultColor;
00121             row.append(p);
00122         }
00123 
00124         m_width = qMax(m_width, row.size());
00125         m_data.append(row);
00126     }
00127 
00128     // Now, the colors.
00129     QStringList cols = mask.split('\n');
00130     int y = 0;
00131 
00132     foreach(const QString &curCol, cols) {
00133         if (y >= m_data.size())
00134             break;
00135 
00136         for (int pos = 0; pos < curCol.length() && pos < m_data[y].size(); ++pos)
00137         {
00138             switch (curCol.at(pos).unicode())
00139             {
00140                 //Colors stolen from konsole, TEWidget.cpp
00141                 case 'R':
00142                     m_data[y][pos].color = 0xFF5454;
00143                     break;
00144                 case 'r':
00145                     m_data[y][pos].color = 0xB21818;
00146                     break;
00147                 case 'C':
00148                     m_data[y][pos].color = 0x54FFFF;
00149                     break;
00150                 case 'c':
00151                     m_data[y][pos].color = 0x18B2B2;
00152                     break;
00153                 case 'Y':
00154                     m_data[y][pos].color = 0xFFFF54;
00155                     break;
00156                 case 'y':
00157                     m_data[y][pos].color = 0xB26818;
00158                     break;
00159                 case 'G':
00160                     m_data[y][pos].color = 0x54FF54;
00161                     break;
00162                 case 'g':
00163                     m_data[y][pos].color = 0x18B218;
00164                     break;
00165                 case 'B':
00166                     m_data[y][pos].color = 0x5454FF;
00167                     break;
00168                 case 'b':
00169                     m_data[y][pos].color = 0x1818B2;
00170                     break;
00171                 case 'M':
00172                     m_data[y][pos].color = 0xFF54FF;
00173                     break;
00174                 case 'm':
00175                     m_data[y][pos].color = 0xB218B2;
00176                     break;
00177                 case 'W':
00178                     m_data[y][pos].color = 0xFFFFFF;
00179                     break;
00180                 case 'w':
00181                     m_data[y][pos].color = 0xB2B2B2;
00182                     break;
00183                 case ' ':
00184                     break;
00185                 default:
00186                     kDebug() << "dunno about color code:" << curCol.at(pos);
00187                     m_data[y][pos].color = 0xFFFFFF;
00188             }
00189         }
00190 
00191         ++y;
00192     } // foreach
00193 }
00194 
00195 void Frame::paint(Screen* scr, int x, int y)
00196 {
00197     if(m_pixmap.isNull())
00198         convertDataToPixmap(scr);
00199 
00200     scr->updateSpan(x, y, m_pixmap);
00201 }
00202 
00203 void Frame::erase(Screen* scr, int x, int y)
00204 {
00205     if(m_erasePixmap.isNull())
00206         convertDataToPixmap(scr);
00207 
00208     scr->clearSpan(x, y, m_erasePixmap);
00209 }
00210 
00211 // vim: set et ts=8 sw=4: