/*
 * Asciiquarium - Native KDE Screensaver based on the Asciiquarium program
 *    (c) Kirk Baucom <kbaucom@schizoid.com>, which you can find at
 *    http://www.robobunny.com/projects/asciiquarium/
 *
 * Ported to KDE by Maksim Orlovich <maksim@kde.org> and
 * Michael Pyne <michael.pyne@kdemail.net>.
 *
 * Copyright (c) 2003 Kirk Baucom     <kbaucom@schizoid.com>
 * Copyright (c) 2005 Maksim Orlovich <maksim@kde.org>
 * Copyright (c) 2005 Michael Pyne    <michael.pyne@kdemail.net>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <kglobalsettings.h>
#include <kdebug.h>

#include <ntqvaluevector.h>
#include <ntqstringlist.h>
#include <ntqimage.h>
#include <ntqfontmetrics.h>
#include <ntqpainter.h>
#include <ntqbitmap.h>

#include "frame.h"

void Frame::convertDataToPixmap(const Screen *screen)
{
    if(!height() || !width()) {
        // Assume we're not ready to go.
        return;
    }

    int w = screen->cellWidth(), h = screen->cellHeight();
    TQPixmap pix(width() * w, height() * h);
    pix.fill();

    TQBitmap mask(pix.size(), true);

    TQPainter p, p2;

    p.begin(&pix, true);
    p2.begin(&mask, true);

    p.setFont(KGlobalSettings::fixedFont());
    TQFontMetrics fm(p.font());
    int leadHeight = fm.leading() + fm.descent();

    for(unsigned j = 0; j < m_data.count(); ++j) {
        TQValueVector<Screen::Pixel> row = m_data[j];
        if(row.isEmpty())
            continue;

        unsigned first, last;
        for (first = 0; first < row.count() && row[first].letter == ' '; ++first)
            ;
        
        last = row.count() - 1; // Assume the end is already stripped.

        for(unsigned i = first; i <= last; ++i) {
            if(row[i].letter == m_transparentChar)
                continue;

            p2.fillRect(i * w, j * h, w, h, TQt::color1);

            p.setPen(row[i].color);
            p.fillRect(i * w, j * h, w, h, TQt::black);
            p.drawText(i * w, j * h + (h - 1 - leadHeight), TQChar(row[i].letter));
        }
    }

    pix.setMask(mask);

    TQPixmap erase(pix);
    erase.fill(TQt::black);
    erase.setMask(mask);

    m_pixmap = pix;
    m_erasePixmap = erase;

    // Clear m_data to save a wee bit of memory.
    m_data.clear();
}

Frame::Frame (TQString text, TQString mask, TQRgb defaultColor, TQChar transparent)
{
    //First, process the pixels.
    
    TQStringList rows = TQStringList::split('\n',  text, true);
    m_height = rows.size();
    m_width  = 0;
    m_transparentChar = transparent;

    for (TQStringList::iterator i = rows.begin(); i != rows.end(); ++i)
    {
        TQValueVector<Screen::Pixel> row;
        for (int pos = 0; pos < (*i).length(); ++pos)
        {
            Screen::Pixel p;
            p.letter = (*i).at(pos).unicode();
            p.color  = defaultColor;
            row.append(p);
        }
        
        m_width = TQMAX(m_width, row.size());
        m_data.append(row);
    }
    
    //Now, the colors.
    TQStringList cols = TQStringList::split('\n', mask, true);
    int y = 0;
    for (TQStringList::iterator i = cols.begin(); i != cols.end(); ++i)
    {
        if (y >= m_data.size())
            break;
            
        for (int pos = 0; pos < (*i).length() && pos < m_data[y].size(); ++pos)
        {
            switch ((*i).at(pos).unicode())
            {
                //Colors stolen from konsole, TEWidget.cpp
                case 'R':
                    m_data[y][pos].color = 0xFF5454;
                    break;
                case 'r':
                    m_data[y][pos].color = 0xB21818;
                    break;
                case 'C':
                    m_data[y][pos].color = 0x54FFFF;
                    break;
                case 'c':
                    m_data[y][pos].color = 0x18B2B2;
                    break;
                case 'Y':
                    m_data[y][pos].color = 0xFFFF54;
                    break;
                case 'y':
                    m_data[y][pos].color = 0xB26818;
                    break;
                case 'G':
                    m_data[y][pos].color = 0x54FF54;
                    break;
                case 'g':
                    m_data[y][pos].color = 0x18B218;
                    break;
                case 'B':
                    m_data[y][pos].color = 0x5454FF;
                    break;
                case 'b':
                    m_data[y][pos].color = 0x1818B2;
                    break;
                case 'M':
                    m_data[y][pos].color = 0xFF54FF;
                    break;
                case 'm':
                    m_data[y][pos].color = 0xB218B2;
                    break;
                case 'W':
                    m_data[y][pos].color = 0xFFFFFF;
                    break;
                case 'w':
                    m_data[y][pos].color = 0xB2B2B2;
                    break;
                case ' ':
                    break;
                default:
                    tqDebug("dunno about color code:'%c'", (*i).at(pos).unicode());
                    m_data[y][pos].color = 0xFFFFFF;
            }
        }
        ++y;
    }
}

void Frame::paint(Screen* scr, int x, int y)
{
    if(m_pixmap.isNull())
        convertDataToPixmap(scr);

    scr->updateSpan(x, y, m_pixmap);
}

void Frame::erase(Screen* scr, int x, int y)
{
    if(m_erasePixmap.isNull())
        convertDataToPixmap(scr);

    scr->clearSpan(x, y, m_erasePixmap);
}

// vim: set et ts=8 sw=4: