round to 1.778
[enigma2.git] / lib / gdi / grc.cpp
1 #include <unistd.h>
2 #include <lib/gdi/grc.h>
3 #include <lib/gdi/font.h>
4 #include <lib/base/init.h>
5 #include <lib/base/init_num.h>
6
7 #ifndef SYNC_PAINT
8 void *gRC::thread_wrapper(void *ptr)
9 {
10         return ((gRC*)ptr)->thread();
11 }
12 #endif
13
14 gRC *gRC::instance=0;
15
16 gRC::gRC(): rp(0), wp(0)
17 #ifdef SYNC_PAINT
18 ,m_notify_pump(eApp, 0)
19 #else
20 ,m_notify_pump(eApp, 1)
21 #endif
22 {
23         ASSERT(!instance);
24         instance=this;
25         CONNECT(m_notify_pump.recv_msg, gRC::recv_notify);
26 #ifndef SYNC_PAINT
27         pthread_mutex_init(&mutex, 0);
28         pthread_cond_init(&cond, 0);
29         int res = pthread_create(&the_thread, 0, thread_wrapper, this);
30         if (res)
31                 eFatal("RC thread couldn't be created");
32         else
33                 eDebug("RC thread created successfully");
34 #endif
35         m_spinner_enabled = 0;
36 }
37
38 DEFINE_REF(gRC);
39
40 gRC::~gRC()
41 {
42         instance=0;
43
44         gOpcode o;
45         o.opcode=gOpcode::shutdown;
46         submit(o);
47 #ifndef SYNC_PAINT
48         eDebug("waiting for gRC thread shutdown");
49         pthread_join(the_thread, 0);
50         eDebug("gRC thread has finished");
51 #endif
52 }
53
54 void gRC::submit(const gOpcode &o)
55 {
56         while(1)
57         {
58 #ifndef SYNC_PAINT
59                 pthread_mutex_lock(&mutex);
60 #endif
61                 int tmp=wp+1;
62                 if ( tmp == MAXSIZE )
63                         tmp=0;
64                 if ( tmp == rp )
65                 {
66 #ifndef SYNC_PAINT
67                         pthread_cond_signal(&cond);  // wakeup gdi thread
68                         pthread_mutex_unlock(&mutex);
69 #else
70                         thread();
71 #endif
72                         //printf("render buffer full...\n");
73                         //fflush(stdout);
74                         usleep(1000);  // wait 1 msec
75                         continue;
76                 }
77                 int free=rp-wp;
78                 if ( free <= 0 )
79                         free+=MAXSIZE;
80                 queue[wp++]=o;
81                 if ( wp == MAXSIZE )
82                         wp = 0;
83                 if (o.opcode==gOpcode::flush||o.opcode==gOpcode::shutdown||o.opcode==gOpcode::notify)
84 #ifndef SYNC_PAINT
85                         pthread_cond_signal(&cond);  // wakeup gdi thread
86                 pthread_mutex_unlock(&mutex);
87 #else
88                         thread(); // paint
89 #endif
90                 break;
91         }
92 }
93
94 void *gRC::thread()
95 {
96         int need_notify = 0;
97 #ifndef SYNC_PAINT
98         while (1)
99         {
100 #else
101         while (rp != wp)
102         {
103 #endif
104 #ifndef SYNC_PAINT
105                 pthread_mutex_lock(&mutex);
106 #endif
107                 if ( rp != wp )
108                 {
109                                 /* make sure the spinner is not displayed when we something is painted */
110                         disableSpinner();
111
112                         gOpcode o(queue[rp++]);
113                         if ( rp == MAXSIZE )
114                                 rp=0;
115 #ifndef SYNC_PAINT
116                         pthread_mutex_unlock(&mutex);
117 #endif
118                         if (o.opcode==gOpcode::shutdown)
119                                 break;
120                         else if (o.opcode==gOpcode::notify)
121                                 need_notify = 1;
122                         else
123                         {
124                                 o.dc->exec(&o);
125                                 // o.dc is a gDC* filled with grabref... so we must release it here
126                                 o.dc->Release();
127                         }
128                 }
129                 else
130                 {
131                         if (need_notify)
132                         {
133                                 need_notify = 0;
134                                 m_notify_pump.send(1);
135                         }
136 #ifndef SYNC_PAINT
137                         while(rp == wp)
138                         {
139                         
140                                         /* when the main thread is non-idle for a too long time without any display output,
141                                            we want to display a spinner. */
142
143                                 struct timeval time;
144                                 struct timespec timeout;
145                                 gettimeofday(&time, NULL);
146                                 timeout.tv_sec = time.tv_sec;
147                                 timeout.tv_nsec = time.tv_usec * 1000;
148                                 
149                                 if (m_spinner_enabled)
150                                         timeout.tv_nsec += 100*1000*1000;
151                                 else
152                                         timeout.tv_sec += 2;
153
154                                         /* yes, this is required. */
155                                 if (timeout.tv_nsec > 1000*1000*1000)
156                                 {
157                                         timeout.tv_nsec -= 1000*1000*1000;
158                                         timeout.tv_sec++;
159                                 }
160
161                                 int idle = 1;
162
163                                 if (pthread_cond_timedwait(&cond, &mutex, &timeout) == ETIMEDOUT)
164                                 {
165                                         if (eApp && !eApp->isIdle())
166                                                 idle = 0;
167                                 }
168                                 
169                                 pthread_mutex_unlock(&mutex);
170
171                                 if (!idle)
172                                 {
173                                         if (!m_spinner_enabled)
174                                                 eDebug("main thread is non-idle! display spinner!");
175                                         enableSpinner();
176                                 } else
177                                         disableSpinner();
178                         }
179 #endif
180                 }
181         }
182 #ifndef SYNC_PAINT
183         pthread_exit(0);
184 #endif
185         return 0;
186 }
187
188 void gRC::recv_notify(const int &i)
189 {
190         notify();
191 }
192
193 gRC *gRC::getInstance()
194 {
195         return instance;
196 }
197
198 void gRC::enableSpinner()
199 {
200         if (!m_spinner_dc)
201         {
202                 eDebug("no spinner DC!");
203                 return;
204         }
205
206         gOpcode o;
207         o.opcode = m_spinner_enabled ? gOpcode::incrementSpinner : gOpcode::enableSpinner;
208         m_spinner_dc->exec(&o);
209         m_spinner_enabled = 1;
210
211 }
212
213 void gRC::disableSpinner()
214 {
215         if (!m_spinner_enabled)
216                 return;
217
218         if (!m_spinner_dc)
219         {
220                 eDebug("no spinner DC!");
221                 return;
222         }
223
224         m_spinner_enabled = 0;
225         
226         gOpcode o;
227         o.opcode = gOpcode::disableSpinner;
228         m_spinner_dc->exec(&o);
229 }
230
231 static int gPainter_instances;
232
233 gPainter::gPainter(gDC *dc, eRect rect): m_dc(dc), m_rc(gRC::getInstance())
234 {
235 //      ASSERT(!gPainter_instances);
236         gPainter_instances++;
237 //      begin(rect);
238 }
239
240 gPainter::~gPainter()
241 {
242         end();
243         gPainter_instances--;
244 }
245
246 void gPainter::setBackgroundColor(const gColor &color)
247 {
248         if ( m_dc->islocked() )
249                 return;
250         gOpcode o;
251         o.opcode = gOpcode::setBackgroundColor;
252         o.dc = m_dc.grabRef();
253         o.parm.setColor = new gOpcode::para::psetColor;
254         o.parm.setColor->color = color;
255
256         m_rc->submit(o);
257 }
258
259 void gPainter::setForegroundColor(const gColor &color)
260 {
261         if ( m_dc->islocked() )
262                 return;
263         gOpcode o;
264         o.opcode = gOpcode::setForegroundColor;
265         o.dc = m_dc.grabRef();
266         o.parm.setColor = new gOpcode::para::psetColor;
267         o.parm.setColor->color = color;
268
269         m_rc->submit(o);
270 }
271
272 void gPainter::setBackgroundColor(const gRGB &color)
273 {
274         if ( m_dc->islocked() )
275                 return;
276         gOpcode o;
277         o.opcode = gOpcode::setBackgroundColorRGB;
278         o.dc = m_dc.grabRef();
279         o.parm.setColorRGB = new gOpcode::para::psetColorRGB;
280         o.parm.setColorRGB->color = color;
281
282         m_rc->submit(o);
283 }
284
285 void gPainter::setForegroundColor(const gRGB &color)
286 {
287         if ( m_dc->islocked() )
288                 return;
289         gOpcode o;
290         o.opcode = gOpcode::setForegroundColorRGB;
291         o.dc = m_dc.grabRef();
292         o.parm.setColorRGB = new gOpcode::para::psetColorRGB;
293         o.parm.setColorRGB->color = color;
294
295         m_rc->submit(o);
296 }
297
298 void gPainter::setFont(gFont *font)
299 {
300         if ( m_dc->islocked() )
301                 return;
302         gOpcode o;
303         o.opcode = gOpcode::setFont;
304         o.dc = m_dc.grabRef();
305         font->AddRef();
306         o.parm.setFont = new gOpcode::para::psetFont;
307         o.parm.setFont->font = font;
308
309         m_rc->submit(o);
310 }
311
312 void gPainter::renderText(const eRect &pos, const std::string &string, int flags)
313 {
314         if ( m_dc->islocked() )
315                 return;
316         gOpcode o;
317         o.opcode=gOpcode::renderText;
318         o.dc = m_dc.grabRef();
319         o.parm.renderText = new gOpcode::para::prenderText;
320         o.parm.renderText->area = pos;
321         o.parm.renderText->text = string.empty()?0:strdup(string.c_str());
322         o.parm.renderText->flags = flags;
323         m_rc->submit(o);
324 }
325
326 void gPainter::renderPara(eTextPara *para, ePoint offset)
327 {
328         if ( m_dc->islocked() )
329                 return;
330         gOpcode o;
331         o.opcode=gOpcode::renderPara;
332         o.dc = m_dc.grabRef();
333         o.parm.renderPara = new gOpcode::para::prenderPara;
334         o.parm.renderPara->offset = offset;
335
336         para->AddRef();
337         o.parm.renderPara->textpara = para;
338         m_rc->submit(o);
339 }
340
341 void gPainter::fill(const eRect &area)
342 {
343         if ( m_dc->islocked() )
344                 return;
345         gOpcode o;
346         o.opcode=gOpcode::fill;
347
348         o.dc = m_dc.grabRef();
349         o.parm.fill = new gOpcode::para::pfillRect;
350         o.parm.fill->area = area;
351         m_rc->submit(o);
352 }
353
354 void gPainter::fill(const gRegion &region)
355 {
356         if ( m_dc->islocked() )
357                 return;
358         gOpcode o;
359         o.opcode=gOpcode::fillRegion;
360
361         o.dc = m_dc.grabRef();
362         o.parm.fillRegion = new gOpcode::para::pfillRegion;
363         o.parm.fillRegion->region = region;
364         m_rc->submit(o);
365 }
366
367 void gPainter::clear()
368 {
369         if ( m_dc->islocked() )
370                 return;
371         gOpcode o;
372         o.opcode=gOpcode::clear;
373         o.dc = m_dc.grabRef();
374         o.parm.fill = new gOpcode::para::pfillRect;
375         o.parm.fill->area = eRect();
376         m_rc->submit(o);
377 }
378
379 void gPainter::blit(gPixmap *pixmap, ePoint pos, const eRect &clip, int flags)
380 {
381         if ( m_dc->islocked() )
382                 return;
383         gOpcode o;
384
385         ASSERT(pixmap);
386
387         o.opcode=gOpcode::blit;
388         o.dc = m_dc.grabRef();
389         pixmap->AddRef();
390         o.parm.blit  = new gOpcode::para::pblit;
391         o.parm.blit->pixmap = pixmap;
392         o.parm.blit->position = pos;
393         o.parm.blit->clip = clip;
394         o.parm.blit->flags=flags;
395         m_rc->submit(o);
396 }
397
398
399 void gPainter::setPalette(gRGB *colors, int start, int len)
400 {
401         if ( m_dc->islocked() )
402                 return;
403         gOpcode o;
404         o.opcode=gOpcode::setPalette;
405         o.dc = m_dc.grabRef();
406         gPalette *p=new gPalette;
407
408         o.parm.setPalette = new gOpcode::para::psetPalette;
409         p->data=new gRGB[len];
410
411         memcpy(p->data, colors, len*sizeof(gRGB));
412         p->start=start;
413         p->colors=len;
414         o.parm.setPalette->palette = p;
415         m_rc->submit(o);
416 }
417
418 void gPainter::setPalette(gPixmap *source)
419 {
420         ASSERT(source);
421         setPalette(source->surface->clut.data, source->surface->clut.start, source->surface->clut.colors);
422 }
423
424 void gPainter::mergePalette(gPixmap *target)
425 {
426         if ( m_dc->islocked() )
427                 return;
428         gOpcode o;
429         o.opcode = gOpcode::mergePalette;
430         o.dc = m_dc.grabRef();
431         target->AddRef();
432         o.parm.mergePalette = new gOpcode::para::pmergePalette;
433         o.parm.mergePalette->target = target;
434         m_rc->submit(o);
435 }
436
437 void gPainter::line(ePoint start, ePoint end)
438 {
439         if ( m_dc->islocked() )
440                 return;
441         gOpcode o;
442         o.opcode=gOpcode::line;
443         o.dc = m_dc.grabRef();
444         o.parm.line = new gOpcode::para::pline;
445         o.parm.line->start = start;
446         o.parm.line->end = end;
447         m_rc->submit(o);
448 }
449
450 void gPainter::setOffset(ePoint val)
451 {
452         if ( m_dc->islocked() )
453                 return;
454         gOpcode o;
455         o.opcode=gOpcode::setOffset;
456         o.dc = m_dc.grabRef();
457         o.parm.setOffset = new gOpcode::para::psetOffset;
458         o.parm.setOffset->rel = 0;
459         o.parm.setOffset->value = val;
460         m_rc->submit(o);
461 }
462
463 void gPainter::moveOffset(ePoint rel)
464 {
465         if ( m_dc->islocked() )
466                 return;
467         gOpcode o;
468         o.opcode=gOpcode::setOffset;
469         o.dc = m_dc.grabRef();
470         o.parm.setOffset = new gOpcode::para::psetOffset;
471         o.parm.setOffset->rel = 1;
472         o.parm.setOffset->value = rel;
473         m_rc->submit(o);
474 }
475
476 void gPainter::resetOffset()
477 {
478         if ( m_dc->islocked() )
479                 return;
480         gOpcode o;
481         o.opcode=gOpcode::setOffset;
482         o.dc = m_dc.grabRef();
483         o.parm.setOffset = new gOpcode::para::psetOffset;
484         o.parm.setOffset->rel = 0;
485         o.parm.setOffset->value = ePoint(0, 0);
486         m_rc->submit(o);
487 }
488
489 void gPainter::resetClip(const gRegion &region)
490 {
491         if ( m_dc->islocked() )
492                 return;
493         gOpcode o;
494         o.opcode = gOpcode::setClip;
495         o.dc = m_dc.grabRef();
496         o.parm.clip = new gOpcode::para::psetClip;
497         o.parm.clip->region = region;
498         m_rc->submit(o);
499 }
500
501 void gPainter::clip(const gRegion &region)
502 {
503         if ( m_dc->islocked() )
504                 return;
505         gOpcode o;
506         o.opcode = gOpcode::addClip;
507         o.dc = m_dc.grabRef();
508         o.parm.clip = new gOpcode::para::psetClip;
509         o.parm.clip->region = region;
510         m_rc->submit(o);
511 }
512
513 void gPainter::clippop()
514 {
515         if ( m_dc->islocked() )
516                 return;
517         gOpcode o;
518         o.opcode = gOpcode::popClip;
519         o.dc = m_dc.grabRef();
520         m_rc->submit(o);
521 }
522
523 void gPainter::flush()
524 {
525         if ( m_dc->islocked() )
526                 return;
527         gOpcode o;
528         o.opcode = gOpcode::flush;
529         o.dc = m_dc.grabRef();
530         m_rc->submit(o);
531 }
532
533 void gPainter::waitVSync()
534 {
535         if ( m_dc->islocked() )
536                 return;
537         gOpcode o;
538         o.opcode = gOpcode::waitVSync;
539         o.dc = m_dc.grabRef();
540         m_rc->submit(o);
541 }
542
543 void gPainter::flip()
544 {
545         if ( m_dc->islocked() )
546                 return;
547         gOpcode o;
548         o.opcode = gOpcode::flip;
549         o.dc = m_dc.grabRef();
550         m_rc->submit(o);
551 }
552
553 void gPainter::notify()
554 {
555         if ( m_dc->islocked() )
556                 return;
557         gOpcode o;
558         o.opcode = gOpcode::notify;
559         o.dc = m_dc.grabRef();
560         m_rc->submit(o);
561 }
562
563 void gPainter::end()
564 {
565         if ( m_dc->islocked() )
566                 return;
567         gOpcode o;
568         o.opcode = gOpcode::flush;
569         o.dc = m_dc.grabRef();
570         m_rc->submit(o);
571 }
572
573 gDC::gDC()
574 {
575         m_spinner_pic = 0;
576 }
577
578 gDC::gDC(gPixmap *pixmap): m_pixmap(pixmap)
579 {
580         m_spinner_pic = 0;
581 }
582
583 gDC::~gDC()
584 {
585         delete[] m_spinner_pic;
586 }
587
588 void gDC::exec(gOpcode *o)
589 {
590         switch (o->opcode)
591         {
592         case gOpcode::setBackgroundColor:
593                 m_background_color = o->parm.setColor->color;
594                 m_background_color_rgb = getRGB(m_background_color);
595                 delete o->parm.setColor;
596                 break;
597         case gOpcode::setForegroundColor:
598                 m_foreground_color = o->parm.setColor->color;
599                 m_background_color_rgb = getRGB(m_foreground_color);
600                 delete o->parm.setColor;
601                 break;
602         case gOpcode::setBackgroundColorRGB:
603                 if (m_pixmap->needClut())
604                         m_background_color = m_pixmap->surface->clut.findColor(o->parm.setColorRGB->color);
605                 m_background_color_rgb = o->parm.setColorRGB->color;
606                 delete o->parm.setColorRGB;
607                 break;
608         case gOpcode::setForegroundColorRGB:
609                 if (m_pixmap->needClut())
610                         m_foreground_color = m_pixmap->surface->clut.findColor(o->parm.setColorRGB->color);
611                 m_foreground_color_rgb = o->parm.setColorRGB->color;
612                 delete o->parm.setColorRGB;
613                 break;
614         case gOpcode::setFont:
615                 m_current_font = o->parm.setFont->font;
616                 o->parm.setFont->font->Release();
617                 delete o->parm.setFont;
618                 break;
619         case gOpcode::renderText:
620         {
621                 ePtr<eTextPara> para = new eTextPara(o->parm.renderText->area);
622                 int flags = o->parm.renderText->flags;
623                 assert(m_current_font);
624                 para->setFont(m_current_font);
625                 para->renderString(o->parm.renderText->text, (flags & gPainter::RT_WRAP) ? RS_WRAP : 0);
626                 if (o->parm.renderText->text)
627                         free(o->parm.renderText->text);
628                 if (flags & gPainter::RT_HALIGN_RIGHT)
629                         para->realign(eTextPara::dirRight);
630                 else if (flags & gPainter::RT_HALIGN_CENTER)
631                         para->realign(eTextPara::dirCenter);
632                 else if (flags & gPainter::RT_HALIGN_BLOCK)
633                         para->realign(eTextPara::dirBlock);
634                 
635                 ePoint offset = m_current_offset;
636                 
637                 if (o->parm.renderText->flags & gPainter::RT_VALIGN_CENTER)
638                 {
639                         eRect bbox = para->getBoundBox();
640                         int vcentered_top = o->parm.renderText->area.top() + ((o->parm.renderText->area.height() - bbox.height()) / 2);
641                         int correction = vcentered_top - bbox.top();
642                         offset += ePoint(0, correction);
643                 }
644                 
645                 para->blit(*this, offset, m_background_color_rgb, m_foreground_color_rgb);
646                 delete o->parm.renderText;
647                 break;
648         }
649         case gOpcode::renderPara:
650         {
651                 o->parm.renderPara->textpara->blit(*this, o->parm.renderPara->offset + m_current_offset, m_background_color_rgb, m_foreground_color_rgb);
652                 o->parm.renderPara->textpara->Release();
653                 delete o->parm.renderPara;
654                 break;
655         }
656         case gOpcode::fill:
657         {
658                 eRect area = o->parm.fill->area;
659                 area.moveBy(m_current_offset);
660                 gRegion clip = m_current_clip & area;
661                 if (m_pixmap->needClut())
662                         m_pixmap->fill(clip, m_foreground_color);
663                 else
664                         m_pixmap->fill(clip, m_foreground_color_rgb);
665                 delete o->parm.fill;
666                 break;
667         }
668         case gOpcode::fillRegion:
669         {
670                 o->parm.fillRegion->region.moveBy(m_current_offset);
671                 gRegion clip = m_current_clip & o->parm.fillRegion->region;
672                 if (m_pixmap->needClut())
673                         m_pixmap->fill(clip, m_foreground_color);
674                 else
675                         m_pixmap->fill(clip, m_foreground_color_rgb);
676                 delete o->parm.fillRegion;
677                 break;
678         }
679         case gOpcode::clear:
680                 if (m_pixmap->needClut())
681                         m_pixmap->fill(m_current_clip, m_background_color);
682                 else
683                         m_pixmap->fill(m_current_clip, m_background_color_rgb);
684                 delete o->parm.fill;
685                 break;
686         case gOpcode::blit:
687         {
688                 gRegion clip;
689                                 // this code should be checked again but i'm too tired now
690                 
691                 o->parm.blit->position += m_current_offset;
692                 
693                 if (o->parm.blit->clip.valid())
694                 {
695                         o->parm.blit->clip.moveBy(m_current_offset);
696                         clip.intersect(gRegion(o->parm.blit->clip), m_current_clip);
697                 } else
698                         clip = m_current_clip;
699                 
700                 m_pixmap->blit(*o->parm.blit->pixmap, o->parm.blit->position, clip, o->parm.blit->flags);
701                 o->parm.blit->pixmap->Release();
702                 delete o->parm.blit;
703                 break;
704         }
705         case gOpcode::setPalette:
706                 if (o->parm.setPalette->palette->start > m_pixmap->surface->clut.colors)
707                         o->parm.setPalette->palette->start = m_pixmap->surface->clut.colors;
708                 if (o->parm.setPalette->palette->colors > (m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start))
709                         o->parm.setPalette->palette->colors = m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start;
710                 if (o->parm.setPalette->palette->colors)
711                         memcpy(m_pixmap->surface->clut.data+o->parm.setPalette->palette->start, o->parm.setPalette->palette->data, o->parm.setPalette->palette->colors*sizeof(gRGB));
712                 
713                 delete[] o->parm.setPalette->palette->data;
714                 delete o->parm.setPalette->palette;
715                 delete o->parm.setPalette;
716                 break;
717         case gOpcode::mergePalette:
718                 m_pixmap->mergePalette(*o->parm.mergePalette->target);
719                 o->parm.mergePalette->target->Release();
720                 delete o->parm.mergePalette;
721                 break; 
722         case gOpcode::line:
723         {
724                 ePoint start = o->parm.line->start + m_current_offset, end = o->parm.line->end + m_current_offset;
725                 m_pixmap->line(m_current_clip, start, end, m_foreground_color);
726                 delete o->parm.line;
727                 break;
728         }
729         case gOpcode::addClip:
730                 m_clip_stack.push(m_current_clip);
731                 o->parm.clip->region.moveBy(m_current_offset);
732                 m_current_clip &= o->parm.clip->region;
733                 delete o->parm.clip;
734                 break;
735         case gOpcode::setClip:
736                 o->parm.clip->region.moveBy(m_current_offset);
737                 m_current_clip = o->parm.clip->region & eRect(ePoint(0, 0), m_pixmap->size());
738                 delete o->parm.clip;
739                 break;
740         case gOpcode::popClip:
741                 if (!m_clip_stack.empty())
742                 {
743                         m_current_clip = m_clip_stack.top();
744                         m_clip_stack.pop();
745                 }
746                 break;
747         case gOpcode::setOffset:
748                 if (o->parm.setOffset->rel)
749                         m_current_offset += o->parm.setOffset->value;
750                 else
751                         m_current_offset  = o->parm.setOffset->value;
752                 delete o->parm.setOffset;
753                 break;
754         case gOpcode::waitVSync:
755                 break;
756         case gOpcode::flip:
757                 break;
758         case gOpcode::flush:
759                 break;
760         case gOpcode::enableSpinner:
761                 enableSpinner();
762                 break;
763         case gOpcode::disableSpinner:
764                 disableSpinner();
765                 break;
766         case gOpcode::incrementSpinner:
767                 incrementSpinner();
768                 break;
769         default:
770                 eFatal("illegal opcode %d. expect memory leak!", o->opcode);
771         }
772 }
773
774 gRGB gDC::getRGB(gColor col)
775 {
776         if ((!m_pixmap) || (!m_pixmap->surface->clut.data))
777                 return gRGB(col, col, col);
778         if (col<0)
779         {
780                 eFatal("bla transp");
781                 return gRGB(0, 0, 0, 0xFF);
782         }
783         return m_pixmap->surface->clut.data[col];
784 }
785
786 void gDC::enableSpinner()
787 {
788         ASSERT(m_spinner_saved);
789         
790                 /* save the background to restore it later. We need to negative position because we want to blit from the middle of the screen. */
791         m_spinner_saved->blit(*m_pixmap, -m_spinner_pos.topLeft(), gRegion(eRect(ePoint(0, 0), m_spinner_saved->size())), 0);
792         
793         incrementSpinner();
794 }
795
796 void gDC::disableSpinner()
797 {
798         ASSERT(m_spinner_saved);
799
800                 /* restore background */
801         m_pixmap->blit(*m_spinner_saved, m_spinner_pos.topLeft(), gRegion(m_spinner_pos), 0);
802 }
803
804 void gDC::incrementSpinner()
805 {
806         ASSERT(m_spinner_saved);
807         
808         static int blub;
809         blub++;
810
811 #if 0
812         int i;
813         
814         for (i = 0; i < 5; ++i)
815         {
816                 int x = i * 20 + m_spinner_pos.left();
817                 int y = m_spinner_pos.top();
818                 
819                 int col = ((blub - i) * 30) % 256;
820
821                 m_pixmap->fill(eRect(x, y, 10, 10), gRGB(col, col, col));
822         }
823 #endif
824
825         m_spinner_temp->blit(*m_spinner_saved, ePoint(0, 0), eRect(ePoint(0, 0), m_spinner_pos.size()));
826
827         if (m_spinner_pic[m_spinner_i])
828                 m_spinner_temp->blit(*m_spinner_pic[m_spinner_i], ePoint(0, 0), eRect(ePoint(0, 0), m_spinner_pos.size()), gPixmap::blitAlphaTest);
829
830         m_pixmap->blit(*m_spinner_temp, m_spinner_pos.topLeft(), gRegion(m_spinner_pos), 0);
831         m_spinner_i++;
832         m_spinner_i %= m_spinner_num;
833 }
834
835 void gDC::setSpinner(eRect pos, ePtr<gPixmap> *pic, int len)
836 {
837         ASSERT(m_pixmap);
838         ASSERT(m_pixmap->surface);
839         m_spinner_saved = new gPixmap(pos.size(), m_pixmap->surface->bpp);
840         m_spinner_temp = new gPixmap(pos.size(), m_pixmap->surface->bpp);
841         m_spinner_pos = pos;
842         
843         m_spinner_i = 0;
844         m_spinner_num = len;
845         
846         int i;
847         if (m_spinner_pic)
848                 delete[] m_spinner_pic;
849         
850         m_spinner_pic = new ePtr<gPixmap>[len];
851         
852         for (i = 0; i < len; ++i)
853                 m_spinner_pic[i] = pic[i];
854 }
855
856 DEFINE_REF(gDC);
857
858 eAutoInitPtr<gRC> init_grc(eAutoInitNumbers::graphic, "gRC");