Qt3to4
[kdeartwork.git] / kscreensaver / kdesavers / firesaverwriter.cpp
blob994f10730bb14b308930a90985a346bcd30f890c
1 /***************************************************************************
2 * Copyright (C) 2004 by E.Ros *
3 * rosenric@dei.unipd.it *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 ***************************************************************************/
12 #include <math.h>
13 #include <stdlib.h>
14 #include <qimage.h>
15 #include <qgl.h>
16 #include <qfile.h>
17 #include <qstring.h>
18 //Added by qt3to4:
19 #include <Q3PtrList>
20 #include <kdebug.h>
21 #include <kstandarddirs.h>
22 #include <kdeversion.h>
23 #include <klocale.h>
24 #include "firesaverwriter.h"
27 /* Word: SINGLE WORD */
29 Word::Word( const char * _text, QMap<char, Symbol *> * sMap, float _scale )
30 : width(0), scale(_scale), cX(0), cY(0), vScale(0), vX(0), vY(0),
31 activateTime(0.0), lifeTime(2), currentTime(0)
33 for ( ; *_text != 0 && *_text != ' '; _text++ )
35 char c = *_text;
36 if ( !sMap->contains(c) ) //search for a symbol in the map
37 continue;
38 Symbol * symbol = (*sMap)[c]; //get the symbol*
39 width += symbol->scale; //increase word's half-width
40 symbolList.append( symbol ); //insert it to the list
42 color[0] = 0;
43 color[1] = 0.8 * drand48();
44 color[2] = 0.2 + 0.8 * drand48();
45 color[3] = 1;
48 inline void Word::renderWord( double dT )
50 if ( (currentTime += dT) < activateTime )
51 return;
53 //update coloring
54 if ( activateTime >= 0 ) {
55 if ( currentTime < activateTime + 0.4 )
56 color[3] = (currentTime - activateTime) / 0.4;
57 else
58 color[3] = 1 - (currentTime - activateTime - 0.4) / (lifeTime - 0.4);
59 } else
60 color[3] = 1 - currentTime / lifeTime;
62 //word's global transforms
63 glPushMatrix();
64 glTranslatef( cX - scale * width, cY, 0 );
65 glScalef( scale, scale, 1 );
66 glColor4fv( color );
68 //for each symbol draw it!
69 Symbol * symbol = symbolList.first();
70 for( ; symbol; symbol = symbolList.next() )
71 symbol->renderSymbol();
72 glPopMatrix();
74 //physical update to position and scale
75 cX += vX * dT;
76 cY += vY * dT;
77 scale += scale * vScale * dT;
80 inline bool Word::isDead()
82 if ( activateTime > 0 )
83 return (currentTime - activateTime) >= lifeTime;
84 return currentTime >= lifeTime;
89 /* Writer: engine that spawns and manages words */
91 Writer::Writer( QString descFileName )
92 : numTextures(0)
94 wordList.setAutoDelete( true );
96 if ( !loadMap( descFileName ) )
97 return;
99 QString welcomeString = i18n("Welcome to KDE %1.%2.%3")
100 .arg(KDE_VERSION_MAJOR)
101 .arg(KDE_VERSION_MINOR)
102 .arg(KDE_VERSION_RELEASE);
103 spawnWords(welcomeString, Fun1);
106 Writer::~ Writer()
108 glDeleteTextures( numTextures, texArray );
109 wordList.clear();
110 QMap<char, Symbol *>::Iterator it = symbolMap.begin();
111 for ( ; it != symbolMap.end(); ++it )
112 delete (Symbol *)it.data();
115 void Writer::spawnWords( QString phrase, effectType fX )
117 int wordCount = 0;
118 float xCenter = 0,
119 yCenter = drand48()*40 - 20,
120 wordsWidth = 0;
121 Q3PtrList<Word> localWords;
122 while ( phrase.length() > 0 )
124 QString letters = phrase.section(" ",0,0);
125 Word * word = new Word( letters.latin1(), &symbolMap );
126 wordList.append( word );
127 localWords.append( word );
128 word->cX = xCenter;
129 word->cY = yCenter;
130 switch ( fX ) {
131 case Fun1:{
132 float angle = 2*M_PI * drand48(),
133 module = 0.25 * (drand48() + drand48());
134 word->vX = module * cos( angle );
135 word->vY = module * sin( angle );
136 word->vScale = 0.6;
137 word->scale = 0.7 + 0.3*(drand48() + drand48());}
138 word->activateTime = 0.3 * wordCount;
139 //fall to the case below for word spacing
140 default:
141 case NoEffect:
142 wordsWidth += word->width;
143 word->cX += wordsWidth;
144 wordsWidth += word->width + 1;
145 break;
146 case Sequence:
147 word->lifeTime = 1.2;
148 word->activateTime = 0.6 + 0.9 * wordCount;
149 // word->vY = -5;
150 break;
152 wordCount ++;
153 phrase.remove(0, letters.length() + 1);
155 if ( localWords.count() < 1 )
156 return;
157 //some computations to 'center' the string
158 float displace = -(wordsWidth - 1) / 2;
159 Word * word = localWords.first();
160 for( ; word; word = localWords.next() )
161 word->cX += displace;
164 void Writer::render( double dT )
166 if ( !numTextures )
167 return;
169 glEnable( GL_TEXTURE_2D );
171 glPushMatrix();
172 glScalef( 0.6, 0.6, 1.0 );
173 Word * word = wordList.first();
174 while( word ) {
175 word->renderWord( dT );
176 if ( word->isDead() ) {
177 wordList.remove();
178 word = wordList.current();
179 } else
180 word = wordList.next();
182 glPopMatrix();
185 /* loadMap()
186 * parses the description file to create the internal symbols map.
187 * This map is then used when building words.
189 bool Writer::loadMap( QString descFile )
191 QFile desc( locate("data","kfiresaver/"+descFile) );
192 if ( !desc.open( QIODevice::ReadOnly ) )
193 return false;
195 unsigned int currentNumber;
196 float xres = 0, yres = 0;
197 bool generatedFirst = false;
199 while ( !desc.atEnd() )
201 QString line;
202 int count = desc.readLine( line, 100 );
203 //skip comments / invalid lines
204 if ( count < 6 || line.at(0) == '#')
205 continue;
206 //load texture maps
207 if ( line.at(0) == '"' && numTextures < 15 )
209 //load and generate texture
210 QString fileName = line.section("\"", 1,1 );
211 QImage tmp;
212 if ( !tmp.load( locate("data","kfiresaver/"+fileName) ) ) {
213 kdWarning() << "can't load filename:" << fileName << endl;
214 generatedFirst = false;
215 continue;
217 glGenTextures( 1, &currentNumber );
218 texArray[ numTextures++ ] = currentNumber;
219 glBindTexture(GL_TEXTURE_2D, currentNumber);
220 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
221 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
222 QImage texture = QGLWidget::convertToGLFormat( tmp );
223 xres = (float)texture.width();
224 yres = (float)texture.height();
225 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)xres, (int)yres, 0,
226 GL_RGBA, GL_UNSIGNED_BYTE, texture.bits());
227 generatedFirst = true;
228 continue;
230 if ( !generatedFirst )
231 continue;
232 if ( line.contains(' ') != 4 ) {
233 kdWarning() << "wrong line on symbols.desc (4 spaces expected):" << endl;
234 kdWarning() << " '" << line << "'" << endl;
235 continue;
237 //parse the line describing a symbol and create it
238 char p = *(line.latin1());
239 if ( symbolMap.contains(p) )
240 continue;
241 float left = (float)(line.section(" ",1,1).toInt())/xres,
242 top = (float)(line.section(" ",2,2).toInt())/yres,
243 right = (float)(line.section(" ",3,3).toInt() + 1)/xres,
244 bottom = (float)(line.section(" ",4,4).toInt() + 1)/yres;
245 symbolMap[p] = new Symbol( currentNumber, left,top,right,bottom );
248 return symbolMap.size() > 0;