b3ad2ccc13feb95dd5f6be25be319a5f47968314
[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                         gOpcode o(queue[rp++]);
110                         if ( rp == MAXSIZE )
111                                 rp=0;
112 #ifndef SYNC_PAINT
113                         pthread_mutex_unlock(&mutex);
114 #endif
115                         if (o.opcode==gOpcode::shutdown)
116                                 break;
117                         else if (o.opcode==gOpcode::notify)
118                                 need_notify = 1;
119                         else
120                         {
121                                 o.dc->exec(&o);
122                                 // o.dc is a gDC* filled with grabref... so we must release it here
123                                 o.dc->Release();
124                         }
125                 }
126                 else
127                 {
128                         if (need_notify)
129                         {
130                                 need_notify = 0;
131                                 m_notify_pump.send(1);
132                         }
133 #ifndef SYNC_PAINT
134                         while(rp == wp)
135                         {
136                         
137                                         /* when the main thread is non-idle for a too long time without any display output,
138                                            we want to display a spinner. */
139
140                                 struct timeval time;
141                                 struct timespec timeout;
142                                 gettimeofday(&time, NULL);
143                                 timeout.tv_sec = time.tv_sec;
144                                 timeout.tv_nsec = time.tv_usec * 1000;
145                                 
146                                 if (m_spinner_enabled)
147                                         timeout.tv_nsec += 100*1000*1000;
148                                 else
149                                         timeout.tv_nsec += 500*1000*1000;
150
151                                         /* yes, this is required. */
152                                 if (timeout.tv_nsec > 1000*1000*1000)
153                                 {
154                                         timeout.tv_nsec -= 1000*1000*1000;
155                                         timeout.tv_sec++;
156                                 }
157
158                                 int idle = 1;
159
160                                 if (pthread_cond_timedwait(&cond, &mutex, &timeout) == ETIMEDOUT)
161                                 {
162                                         if (eApp && !eApp->isIdle())
163                                                 idle = 0;
164                                 }
165                                 
166                                 pthread_mutex_unlock(&mutex);
167
168                                 if (!idle)
169                                 {
170                                         enableSpinner();
171                                         eDebug("main thread is non-idle! display spinner!");
172                                 } else
173                                         disableSpinner();
174                         }
175 #endif
176                 }
177         }
178 #ifndef SYNC_PAINT
179         pthread_exit(0);
180 #endif
181         return 0;
182 }
183
184 void gRC::recv_notify(const int &i)
185 {
186         notify();
187 }
188
189 gRC *gRC::getInstance()
190 {
191         return instance;
192 }
193
194 void gRC::enableSpinner()
195 {
196         if (!m_spinner_dc)
197         {
198                 eDebug("no spinner DC!");
199                 return;
200         }
201
202         m_spinner_enabled = 1;
203
204         gOpcode o;
205         o.opcode = m_spinner_enabled ? gOpcode::incrementSpinner : gOpcode::enableSpinner;
206         m_spinner_dc->exec(&o);
207 }
208
209 void gRC::disableSpinner()
210 {
211         if (!m_spinner_enabled)
212                 return;
213
214         if (!m_spinner_dc)
215         {
216                 eDebug("no spinner DC!");
217                 return;
218         }
219
220         m_spinner_enabled = 0;
221         
222         gOpcode o;
223         o.opcode = gOpcode::disableSpinner;
224         m_spinner_dc->exec(&o);
225 }
226
227 static int gPainter_instances;
228
229 gPainter::gPainter(gDC *dc, eRect rect): m_dc(dc), m_rc(gRC::getInstance())
230 {
231 //      ASSERT(!gPainter_instances);
232         gPainter_instances++;
233 //      begin(rect);
234 }
235
236 gPainter::~gPainter()
237 {
238         end();
239         gPainter_instances--;
240 }
241
242 void gPainter::setBackgroundColor(const gColor &color)
243 {
244         if ( m_dc->islocked() )
245                 return;
246         gOpcode o;
247         o.opcode = gOpcode::setBackgroundColor;
248         o.dc = m_dc.grabRef();
249         o.parm.setColor = new gOpcode::para::psetColor;
250         o.parm.setColor->color = color;
251
252         m_rc->submit(o);
253 }
254
255 void gPainter::setForegroundColor(const gColor &color)
256 {
257         if ( m_dc->islocked() )
258                 return;
259         gOpcode o;
260         o.opcode = gOpcode::setForegroundColor;
261         o.dc = m_dc.grabRef();
262         o.parm.setColor = new gOpcode::para::psetColor;
263         o.parm.setColor->color = color;
264
265         m_rc->submit(o);
266 }
267
268 void gPainter::setBackgroundColor(const gRGB &color)
269 {
270         if ( m_dc->islocked() )
271                 return;
272         gOpcode o;
273         o.opcode = gOpcode::setBackgroundColorRGB;
274         o.dc = m_dc.grabRef();
275         o.parm.setColorRGB = new gOpcode::para::psetColorRGB;
276         o.parm.setColorRGB->color = color;
277
278         m_rc->submit(o);
279 }
280
281 void gPainter::setForegroundColor(const gRGB &color)
282 {
283         if ( m_dc->islocked() )
284                 return;
285         gOpcode o;
286         o.opcode = gOpcode::setForegroundColorRGB;
287         o.dc = m_dc.grabRef();
288         o.parm.setColorRGB = new gOpcode::para::psetColorRGB;
289         o.parm.setColorRGB->color = color;
290
291         m_rc->submit(o);
292 }
293
294 void gPainter::setFont(gFont *font)
295 {
296         if ( m_dc->islocked() )
297                 return;
298         gOpcode o;
299         o.opcode = gOpcode::setFont;
300         o.dc = m_dc.grabRef();
301         font->AddRef();
302         o.parm.setFont = new gOpcode::para::psetFont;
303         o.parm.setFont->font = font;
304
305         m_rc->submit(o);
306 }
307
308 void gPainter::renderText(const eRect &pos, const std::string &string, int flags)
309 {
310         if ( m_dc->islocked() )
311                 return;
312         gOpcode o;
313         o.opcode=gOpcode::renderText;
314         o.dc = m_dc.grabRef();
315         o.parm.renderText = new gOpcode::para::prenderText;
316         o.parm.renderText->area = pos;
317         o.parm.renderText->text = string.empty()?0:strdup(string.c_str());
318         o.parm.renderText->flags = flags;
319         m_rc->submit(o);
320 }
321
322 void gPainter::renderPara(eTextPara *para, ePoint offset)
323 {
324         if ( m_dc->islocked() )
325                 return;
326         gOpcode o;
327         o.opcode=gOpcode::renderPara;
328         o.dc = m_dc.grabRef();
329         o.parm.renderPara = new gOpcode::para::prenderPara;
330         o.parm.renderPara->offset = offset;
331
332         para->AddRef();
333         o.parm.renderPara->textpara = para;
334         m_rc->submit(o);
335 }
336
337 void gPainter::fill(const eRect &area)
338 {
339         if ( m_dc->islocked() )
340                 return;
341         gOpcode o;
342         o.opcode=gOpcode::fill;
343
344         o.dc = m_dc.grabRef();
345         o.parm.fill = new gOpcode::para::pfillRect;
346         o.parm.fill->area = area;
347         m_rc->submit(o);
348 }
349
350 void gPainter::fill(const gRegion &region)
351 {
352         if ( m_dc->islocked() )
353                 return;
354         gOpcode o;
355         o.opcode=gOpcode::fillRegion;
356
357         o.dc = m_dc.grabRef();
358         o.parm.fillRegion = new gOpcode::para::pfillRegion;
359         o.parm.fillRegion->region = region;
360         m_rc->submit(o);
361 }
362
363 void gPainter::clear()
364 {
365         if ( m_dc->islocked() )
366                 return;
367         gOpcode o;
368         o.opcode=gOpcode::clear;
369         o.dc = m_dc.grabRef();
370         o.parm.fill = new gOpcode::para::pfillRect;
371         o.parm.fill->area = eRect();
372         m_rc->submit(o);
373 }
374
375 void gPainter::blit(gPixmap *pixmap, ePoint pos, const eRect &clip, int flags)
376 {
377         if ( m_dc->islocked() )
378                 return;
379         gOpcode o;
380
381         ASSERT(pixmap);
382
383         o.opcode=gOpcode::blit;
384         o.dc = m_dc.grabRef();
385         pixmap->AddRef();
386         o.parm.blit  = new gOpcode::para::pblit;
387         o.parm.blit->pixmap = pixmap;
388         o.parm.blit->position = pos;
389         o.parm.blit->clip = clip;
390         o.parm.blit->flags=flags;
391         m_rc->submit(o);
392 }
393
394
395 void gPainter::setPalette(gRGB *colors, int start, int len)
396 {
397         if ( m_dc->islocked() )
398                 return;
399         gOpcode o;
400         o.opcode=gOpcode::setPalette;
401         o.dc = m_dc.grabRef();
402         gPalette *p=new gPalette;
403
404         o.parm.setPalette = new gOpcode::para::psetPalette;
405         p->data=new gRGB[len];
406
407         memcpy(p->data, colors, len*sizeof(gRGB));
408         p->start=start;
409         p->colors=len;
410         o.parm.setPalette->palette = p;
411         m_rc->submit(o);
412 }
413
414 void gPainter::setPalette(gPixmap *source)
415 {
416         ASSERT(source);
417         setPalette(source->surface->clut.data, source->surface->clut.start, source->surface->clut.colors);
418 }
419
420 void gPainter::mergePalette(gPixmap *target)
421 {
422         if ( m_dc->islocked() )
423                 return;
424         gOpcode o;
425         o.opcode = gOpcode::mergePalette;
426         o.dc = m_dc.grabRef();
427         target->AddRef();
428         o.parm.mergePalette = new gOpcode::para::pmergePalette;
429         o.parm.mergePalette->target = target;
430         m_rc->submit(o);
431 }
432
433 void gPainter::line(ePoint start, ePoint end)
434 {
435         if ( m_dc->islocked() )
436                 return;
437         gOpcode o;
438         o.opcode=gOpcode::line;
439         o.dc = m_dc.grabRef();
440         o.parm.line = new gOpcode::para::pline;
441         o.parm.line->start = start;
442         o.parm.line->end = end;
443         m_rc->submit(o);
444 }
445
446 void gPainter::setOffset(ePoint val)
447 {
448         if ( m_dc->islocked() )
449                 return;
450         gOpcode o;
451         o.opcode=gOpcode::setOffset;
452         o.dc = m_dc.grabRef();
453         o.parm.setOffset = new gOpcode::para::psetOffset;
454         o.parm.setOffset->rel = 0;
455         o.parm.setOffset->value = val;
456         m_rc->submit(o);
457 }
458
459 void gPainter::moveOffset(ePoint rel)
460 {
461         if ( m_dc->islocked() )
462                 return;
463         gOpcode o;
464         o.opcode=gOpcode::setOffset;
465         o.dc = m_dc.grabRef();
466         o.parm.setOffset = new gOpcode::para::psetOffset;
467         o.parm.setOffset->rel = 1;
468         o.parm.setOffset->value = rel;
469         m_rc->submit(o);
470 }
471
472 void gPainter::resetOffset()
473 {
474         if ( m_dc->islocked() )
475                 return;
476         gOpcode o;
477         o.opcode=gOpcode::setOffset;
478         o.dc = m_dc.grabRef();
479         o.parm.setOffset = new gOpcode::para::psetOffset;
480         o.parm.setOffset->rel = 0;
481         o.parm.setOffset->value = ePoint(0, 0);
482         m_rc->submit(o);
483 }
484
485 void gPainter::resetClip(const gRegion &region)
486 {
487         if ( m_dc->islocked() )
488                 return;
489         gOpcode o;
490         o.opcode = gOpcode::setClip;
491         o.dc = m_dc.grabRef();
492         o.parm.clip = new gOpcode::para::psetClip;
493         o.parm.clip->region = region;
494         m_rc->submit(o);
495 }
496
497 void gPainter::clip(const gRegion &region)
498 {
499         if ( m_dc->islocked() )
500                 return;
501         gOpcode o;
502         o.opcode = gOpcode::addClip;
503         o.dc = m_dc.grabRef();
504         o.parm.clip = new gOpcode::para::psetClip;
505         o.parm.clip->region = region;
506         m_rc->submit(o);
507 }
508
509 void gPainter::clippop()
510 {
511         if ( m_dc->islocked() )
512                 return;
513         gOpcode o;
514         o.opcode = gOpcode::popClip;
515         o.dc = m_dc.grabRef();
516         m_rc->submit(o);
517 }
518
519 void gPainter::flush()
520 {
521         if ( m_dc->islocked() )
522                 return;
523         gOpcode o;
524         o.opcode = gOpcode::flush;
525         o.dc = m_dc.grabRef();
526         m_rc->submit(o);
527 }
528
529 void gPainter::waitVSync()
530 {
531         if ( m_dc->islocked() )
532                 return;
533         gOpcode o;
534         o.opcode = gOpcode::waitVSync;
535         o.dc = m_dc.grabRef();
536         m_rc->submit(o);
537 }
538
539 void gPainter::flip()
540 {
541         if ( m_dc->islocked() )
542                 return;
543         gOpcode o;
544         o.opcode = gOpcode::flip;
545         o.dc = m_dc.grabRef();
546         m_rc->submit(o);
547 }
548
549 void gPainter::notify()
550 {
551         if ( m_dc->islocked() )
552                 return;
553         gOpcode o;
554         o.opcode = gOpcode::notify;
555         o.dc = m_dc.grabRef();
556         m_rc->submit(o);
557 }
558
559 void gPainter::end()
560 {
561         if ( m_dc->islocked() )
562                 return;
563         gOpcode o;
564         o.opcode = gOpcode::flush;
565         o.dc = m_dc.grabRef();
566         m_rc->submit(o);
567 }
568
569 gDC::gDC()
570 {
571 }
572
573 gDC::gDC(gPixmap *pixmap): m_pixmap(pixmap)
574 {
575 }
576
577 gDC::~gDC()
578 {
579 }
580
581 void gDC::exec(gOpcode *o)
582 {
583         switch (o->opcode)
584         {
585         case gOpcode::setBackgroundColor:
586                 m_background_color = o->parm.setColor->color;
587                 m_background_color_rgb = getRGB(m_background_color);
588                 delete o->parm.setColor;
589                 break;
590         case gOpcode::setForegroundColor:
591                 m_foreground_color = o->parm.setColor->color;
592                 m_background_color_rgb = getRGB(m_foreground_color);
593                 delete o->parm.setColor;
594                 break;
595         case gOpcode::setBackgroundColorRGB:
596                 if (m_pixmap->needClut())
597                         m_background_color = m_pixmap->surface->clut.findColor(o->parm.setColorRGB->color);
598                 m_background_color_rgb = o->parm.setColorRGB->color;
599                 delete o->parm.setColorRGB;
600                 break;
601         case gOpcode::setForegroundColorRGB:
602                 if (m_pixmap->needClut())
603                         m_foreground_color = m_pixmap->surface->clut.findColor(o->parm.setColorRGB->color);
604                 m_foreground_color_rgb = o->parm.setColorRGB->color;
605                 delete o->parm.setColorRGB;
606                 break;
607         case gOpcode::setFont:
608                 m_current_font = o->parm.setFont->font;
609                 o->parm.setFont->font->Release();
610                 delete o->parm.setFont;
611                 break;
612         case gOpcode::renderText:
613         {
614                 ePtr<eTextPara> para = new eTextPara(o->parm.renderText->area);
615                 int flags = o->parm.renderText->flags;
616                 assert(m_current_font);
617                 para->setFont(m_current_font);
618                 para->renderString(o->parm.renderText->text, (flags & gPainter::RT_WRAP) ? RS_WRAP : 0);
619                 if (o->parm.renderText->text)
620                         free(o->parm.renderText->text);
621                 if (flags & gPainter::RT_HALIGN_RIGHT)
622                         para->realign(eTextPara::dirRight);
623                 else if (flags & gPainter::RT_HALIGN_CENTER)
624                         para->realign(eTextPara::dirCenter);
625                 else if (flags & gPainter::RT_HALIGN_BLOCK)
626                         para->realign(eTextPara::dirBlock);
627                 
628                 ePoint offset = m_current_offset;
629                 
630                 if (o->parm.renderText->flags & gPainter::RT_VALIGN_CENTER)
631                 {
632                         eRect bbox = para->getBoundBox();
633                         int vcentered_top = o->parm.renderText->area.top() + ((o->parm.renderText->area.height() - bbox.height()) / 2);
634                         int correction = vcentered_top - bbox.top();
635                         offset += ePoint(0, correction);
636                 }
637                 
638                 para->blit(*this, offset, m_background_color_rgb, m_foreground_color_rgb);
639                 delete o->parm.renderText;
640                 break;
641         }
642         case gOpcode::renderPara:
643         {
644                 o->parm.renderPara->textpara->blit(*this, o->parm.renderPara->offset + m_current_offset, m_background_color_rgb, m_foreground_color_rgb);
645                 o->parm.renderPara->textpara->Release();
646                 delete o->parm.renderPara;
647                 break;
648         }
649         case gOpcode::fill:
650         {
651                 eRect area = o->parm.fill->area;
652                 area.moveBy(m_current_offset);
653                 gRegion clip = m_current_clip & area;
654                 if (m_pixmap->needClut())
655                         m_pixmap->fill(clip, m_foreground_color);
656                 else
657                         m_pixmap->fill(clip, m_foreground_color_rgb);
658                 delete o->parm.fill;
659                 break;
660         }
661         case gOpcode::fillRegion:
662         {
663                 o->parm.fillRegion->region.moveBy(m_current_offset);
664                 gRegion clip = m_current_clip & o->parm.fillRegion->region;
665                 if (m_pixmap->needClut())
666                         m_pixmap->fill(clip, m_foreground_color);
667                 else
668                         m_pixmap->fill(clip, m_foreground_color_rgb);
669                 delete o->parm.fillRegion;
670                 break;
671         }
672         case gOpcode::clear:
673                 if (m_pixmap->needClut())
674                         m_pixmap->fill(m_current_clip, m_background_color);
675                 else
676                         m_pixmap->fill(m_current_clip, m_background_color_rgb);
677                 delete o->parm.fill;
678                 break;
679         case gOpcode::blit:
680         {
681                 gRegion clip;
682                                 // this code should be checked again but i'm too tired now
683                 
684                 o->parm.blit->position += m_current_offset;
685                 
686                 if (o->parm.blit->clip.valid())
687                 {
688                         o->parm.blit->clip.moveBy(m_current_offset);
689                         clip.intersect(gRegion(o->parm.blit->clip), m_current_clip);
690                 } else
691                         clip = m_current_clip;
692                 
693                 m_pixmap->blit(*o->parm.blit->pixmap, o->parm.blit->position, clip, o->parm.blit->flags);
694                 o->parm.blit->pixmap->Release();
695                 delete o->parm.blit;
696                 break;
697         }
698         case gOpcode::setPalette:
699                 if (o->parm.setPalette->palette->start > m_pixmap->surface->clut.colors)
700                         o->parm.setPalette->palette->start = m_pixmap->surface->clut.colors;
701                 if (o->parm.setPalette->palette->colors > (m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start))
702                         o->parm.setPalette->palette->colors = m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start;
703                 if (o->parm.setPalette->palette->colors)
704                         memcpy(m_pixmap->surface->clut.data+o->parm.setPalette->palette->start, o->parm.setPalette->palette->data, o->parm.setPalette->palette->colors*sizeof(gRGB));
705                 
706                 delete[] o->parm.setPalette->palette->data;
707                 delete o->parm.setPalette->palette;
708                 delete o->parm.setPalette;
709                 break;
710         case gOpcode::mergePalette:
711                 m_pixmap->mergePalette(*o->parm.mergePalette->target);
712                 o->parm.mergePalette->target->Release();
713                 delete o->parm.mergePalette;
714                 break; 
715         case gOpcode::line:
716         {
717                 ePoint start = o->parm.line->start + m_current_offset, end = o->parm.line->end + m_current_offset;
718                 m_pixmap->line(m_current_clip, start, end, m_foreground_color);
719                 delete o->parm.line;
720                 break;
721         }
722         case gOpcode::addClip:
723                 m_clip_stack.push(m_current_clip);
724                 o->parm.clip->region.moveBy(m_current_offset);
725                 m_current_clip &= o->parm.clip->region;
726                 delete o->parm.clip;
727                 break;
728         case gOpcode::setClip:
729                 o->parm.clip->region.moveBy(m_current_offset);
730                 m_current_clip = o->parm.clip->region & eRect(ePoint(0, 0), m_pixmap->size());
731                 delete o->parm.clip;
732                 break;
733         case gOpcode::popClip:
734                 if (!m_clip_stack.empty())
735                 {
736                         m_current_clip = m_clip_stack.top();
737                         m_clip_stack.pop();
738                 }
739                 break;
740         case gOpcode::setOffset:
741                 if (o->parm.setOffset->rel)
742                         m_current_offset += o->parm.setOffset->value;
743                 else
744                         m_current_offset  = o->parm.setOffset->value;
745                 delete o->parm.setOffset;
746                 break;
747         case gOpcode::waitVSync:
748                 break;
749         case gOpcode::flip:
750                 break;
751         case gOpcode::flush:
752                 break;
753         case gOpcode::enableSpinner:
754                 break;
755         case gOpcode::disableSpinner:
756                 break;
757         case gOpcode::incrementSpinner:
758                 break;
759         default:
760                 eFatal("illegal opcode %d. expect memory leak!", o->opcode);
761         }
762 }
763
764 gRGB gDC::getRGB(gColor col)
765 {
766         if ((!m_pixmap) || (!m_pixmap->surface->clut.data))
767                 return gRGB(col, col, col);
768         if (col<0)
769         {
770                 eFatal("bla transp");
771                 return gRGB(0, 0, 0, 0xFF);
772         }
773         return m_pixmap->surface->clut.data[col];
774 }
775
776 DEFINE_REF(gDC);
777
778 eAutoInitPtr<gRC> init_grc(eAutoInitNumbers::graphic, "gRC");