fix virtual keyboard bug.
[vuplus_dvbapp] / lib / gdi / gpixmap.cpp
1 #include <cstdlib>
2 #include <cstring>
3 #include <lib/gdi/gpixmap.h>
4 #include <lib/gdi/region.h>
5 #include <lib/gdi/accel.h>
6 #include <byteswap.h>
7
8 #ifndef BYTE_ORDER
9 #error "no BYTE_ORDER defined!"
10 #endif
11
12 gLookup::gLookup()
13         :size(0), lookup(0)
14 {
15 }
16
17 gLookup::gLookup(int size, const gPalette &pal, const gRGB &start, const gRGB &end)
18         :size(0), lookup(0)
19 {
20         build(size, pal, start, end);
21 }
22
23 void gLookup::build(int _size, const gPalette &pal, const gRGB &start, const gRGB &end)
24 {
25         if (lookup)
26         {
27                 delete [] lookup;
28                 lookup=0;
29                 size=0;
30         }
31         size=_size;
32         if (!size)
33                 return;
34         lookup=new gColor[size];
35         
36         for (int i=0; i<size; i++)
37         {
38                 gRGB col;
39                 if (i)
40                 {
41                         int rdiff=-start.r+end.r;
42                         int gdiff=-start.g+end.g;
43                         int bdiff=-start.b+end.b;
44                         int adiff=-start.a+end.a;
45                         rdiff*=i; rdiff/=(size-1);
46                         gdiff*=i; gdiff/=(size-1);
47                         bdiff*=i; bdiff/=(size-1);
48                         adiff*=i; adiff/=(size-1);
49                         col.r=start.r+rdiff;
50                         col.g=start.g+gdiff;
51                         col.b=start.b+bdiff;
52                         col.a=start.a+adiff;
53                 } else
54                         col=start;
55                 lookup[i]=pal.findColor(col);
56         }
57 }
58
59 gSurface::gSurface()
60 {
61         x = 0;
62         y = 0;
63         bpp = 0;
64         bypp = 0;
65         stride = 0;
66         data = 0;
67         data_phys = 0;
68         clut.colors = 0;
69         clut.data = 0;
70         type = 0;
71 }
72
73 gSurface::gSurface(eSize size, int _bpp, int accel)
74 {
75         x = size.width();
76         y = size.height();
77         bpp = _bpp;
78
79         switch (bpp)
80         {
81         case 8:
82                 bypp = 1;
83                 break;
84         case 15:
85         case 16:
86                 bypp = 2;
87                 break;
88         case 24:                // never use 24bit mode
89         case 32:
90                 bypp = 4;
91                 break;
92         default:
93                 bypp = (bpp+7)/8;
94         }
95
96         stride = x*bypp;
97         
98         data = 0;
99         data_phys = 0;
100         
101         if (accel)
102         {
103                 stride += 63;
104                 stride &=~63;
105                 
106                 int pal_size = 0;
107                 if (bpp == 8)
108                         pal_size = 256 * 4;
109                 
110                 if (gAccel::getInstance())
111                         eDebug("accel memory: %d", gAccel::getInstance()->accelAlloc(data, data_phys, y * stride + pal_size));
112                 else
113                         eDebug("no accel available");
114         }
115         
116         clut.colors = 0;
117         clut.data = 0;
118
119         if (!data)
120                 data = new unsigned char [y * stride];
121         
122         type = 1;
123 }
124
125 gSurface::~gSurface()
126 {
127         if (type)
128         {
129                 if (data_phys)
130                         gAccel::getInstance()->accelFree(data_phys);
131                 else
132                         delete [] (unsigned char*)data;
133
134                 delete [] clut.data;
135         }
136 }
137
138 gPixmap *gPixmap::lock()
139 {
140         contentlock.lock(1);
141         return this;
142 }
143
144 void gPixmap::unlock()
145 {
146         contentlock.unlock(1);
147 }
148
149 void gPixmap::fill(const gRegion &region, const gColor &color)
150 {
151         unsigned int i;
152         for (i=0; i<region.rects.size(); ++i)
153         {
154                 const eRect &area = region.rects[i];
155                 if (area.empty())
156                         continue;
157
158                 if (surface->bpp == 8)
159                 {
160                         for (int y=area.top(); y<area.bottom(); y++)
161                                 memset(((__u8*)surface->data)+y*surface->stride+area.left(), color.color, area.width());
162                 } else if (surface->bpp == 16)
163                 {
164                         __u32 icol;
165
166                         if (surface->clut.data && color < surface->clut.colors)
167                                 icol=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
168                         else
169                                 icol=0x10101*color;
170 #if BYTE_ORDER == LITTLE_ENDIAN
171                         __u16 col = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
172 #else
173                         __u16 col = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
174 #endif
175                         for (int y=area.top(); y<area.bottom(); y++)
176                         {
177                                 __u16 *dst=(__u16*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
178                                 int x=area.width();
179                                 while (x--)
180                                         *dst++=col;
181                         }
182                 } else if (surface->bpp == 32)
183                 {
184                         __u32 col;
185
186                         if (surface->clut.data && color < surface->clut.colors)
187                                 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
188                         else
189                                 col=0x10101*color;
190                         
191                         col^=0xFF000000;
192                         
193                         if (surface->data_phys && gAccel::getInstance())
194                                 if (!gAccel::getInstance()->fill(surface,  area, col))
195                                         continue;
196
197                         for (int y=area.top(); y<area.bottom(); y++)
198                         {
199                                 __u32 *dst=(__u32*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
200                                 int x=area.width();
201                                 while (x--)
202                                         *dst++=col;
203                         }
204                 }       else
205                         eWarning("couldn't fill %d bpp", surface->bpp);
206         }
207 }
208
209 void gPixmap::fill(const gRegion &region, const gRGB &color)
210 {
211         unsigned int i;
212         for (i=0; i<region.rects.size(); ++i)
213         {
214                 const eRect &area = region.rects[i];
215                 if (area.empty())
216                         continue;
217
218                 if (surface->bpp == 32)
219                 {
220                         __u32 col;
221
222                         col = color.argb();
223                         col^=0xFF000000;
224
225                         if (surface->data_phys && gAccel::getInstance())
226                                 if (!gAccel::getInstance()->fill(surface,  area, col))
227                                         continue;
228
229                         for (int y=area.top(); y<area.bottom(); y++)
230                         {
231                                 __u32 *dst=(__u32*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
232                                 int x=area.width();
233                                 while (x--)
234                                         *dst++=col;
235                         }
236                 } else if (surface->bpp == 16)
237                 {
238                         __u32 icol = color.argb();
239 #if BYTE_ORDER == LITTLE_ENDIAN
240                         __u16 col = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
241 #else
242                         __u16 col = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
243 #endif
244                         for (int y=area.top(); y<area.bottom(); y++)
245                         {
246                                 __u16 *dst=(__u16*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
247                                 int x=area.width();
248                                 while (x--)
249                                         *dst++=col;
250                         }
251                 }       else
252                         eWarning("couldn't rgbfill %d bpp", surface->bpp);
253         }
254 }
255
256 static inline void blit_8i_to_32(__u32 *dst, __u8 *src, __u32 *pal, int width)
257 {
258         while (width--)
259                 *dst++=pal[*src++];
260 }
261
262 static inline void blit_8i_to_32_at(__u32 *dst, __u8 *src, __u32 *pal, int width)
263 {
264         while (width--)
265         {
266                 if (!(pal[*src]&0x80000000))
267                 {
268                         src++;
269                         dst++;
270                 } else
271                         *dst++=pal[*src++];
272         }
273 }
274
275 static inline void blit_8i_to_16(__u16 *dst, __u8 *src, __u32 *pal, int width)
276 {
277         while (width--)
278                 *dst++=pal[*src++] & 0xFFFF;
279 }
280
281 static inline void blit_8i_to_16_at(__u16 *dst, __u8 *src, __u32 *pal, int width)
282 {
283         while (width--)
284         {
285                 if (!(pal[*src]&0x80000000))
286                 {
287                         src++;
288                         dst++;
289                 } else
290                         *dst++=pal[*src++] & 0xFFFF;
291         }
292 }
293
294                 /* WARNING, this function is not endian safe! */
295 static void blit_8i_to_32_ab(__u32 *dst, __u8 *src, __u32 *pal, int width)
296 {
297         while (width--)
298         {
299 #define BLEND(x, y, a) (y + (((x-y) * a)>>8))
300                 __u32 srccol = pal[*src++];
301                 __u32 dstcol = *dst;
302                 unsigned char sb = srccol & 0xFF;
303                 unsigned char sg = (srccol >> 8) & 0xFF;
304                 unsigned char sr = (srccol >> 16) & 0xFF;
305                 unsigned char sa = (srccol >> 24) & 0xFF;
306
307                 unsigned char db = dstcol & 0xFF;
308                 unsigned char dg = (dstcol >> 8) & 0xFF;
309                 unsigned char dr = (dstcol >> 16) & 0xFF;
310                 unsigned char da = (dstcol >> 24) & 0xFF;
311
312                 da = BLEND(0xFF, da, sa) & 0xFF;
313                 dr = BLEND(sr, dr, sa) & 0xFF;
314                 dg = BLEND(sg, dg, sa) & 0xFF;
315                 db = BLEND(sb, db, sa) & 0xFF;
316
317 #undef BLEND
318                 *dst++ = db | (dg << 8) | (dr << 16) | (da << 24);
319         }
320 }
321
322 #define FIX 0x10000
323
324
325 void gPixmap::blit(const gPixmap &src, const eRect &_pos, const gRegion &clip, int flag)
326 {
327 //      eDebug("blit: -> %d.%d %d:%d -> %d.%d %d:%d, flags=%d",
328 //              _pos.x(), _pos.y(), _pos.width(), _pos.height(),
329 //              clip.extends.x(), clip.extends.y(), clip.extends.width(), clip.extends.height(),
330 //              flag);
331         eRect pos = _pos;
332         
333 //      eDebug("source size: %d %d", src.size().width(), src.size().height());
334         
335         if (!(flag & blitScale)) /* pos' size is valid only when scaling */
336                 pos = eRect(pos.topLeft(), src.size());
337         else if (pos.size() == src.size()) /* no scaling required */
338                 flag &= ~blitScale;
339
340         int scale_x = FIX, scale_y = FIX;
341         
342         if (flag & blitScale)
343         {
344                 ASSERT(src.size().width());
345                 ASSERT(src.size().height());
346                 scale_x = pos.size().width() * FIX / src.size().width();
347                 scale_y = pos.size().height() * FIX / src.size().height();
348         }
349         
350 //      eDebug("SCALE %x %x", scale_x, scale_y);
351
352         for (unsigned int i=0; i<clip.rects.size(); ++i)
353         {
354 //              eDebug("clip rect: %d %d %d %d", clip.rects[i].x(), clip.rects[i].y(), clip.rects[i].width(), clip.rects[i].height());
355                 eRect area = pos; /* pos is the virtual (pre-clipping) area on the dest, which can be larger/smaller than src if scaling is enabled */
356                 area&=clip.rects[i];
357                 area&=eRect(ePoint(0, 0), size());
358
359                 if (area.empty())
360                         continue;
361
362                 eRect srcarea = area;
363                 srcarea.moveBy(-pos.x(), -pos.y());
364
365 //              eDebug("srcarea before scale: %d %d %d %d",
366 //                      srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height());
367                 
368                 if (flag & blitScale)
369                         srcarea = eRect(srcarea.x() * FIX / scale_x, srcarea.y() * FIX / scale_y, srcarea.width() * FIX / scale_x, srcarea.height() * FIX / scale_y);
370
371 //              eDebug("srcarea after scale: %d %d %d %d",
372 //                      srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height());
373
374                 if ((surface->data_phys && src.surface->data_phys) && (gAccel::getInstance()))
375                         if (!gAccel::getInstance()->blit(surface, src.surface, area, srcarea, flag))
376                                 continue;
377
378                 if (flag & blitScale)
379                 {
380                         eWarning("unimplemented: scale on non-accel surfaces");
381                         continue;
382                 }
383
384 #ifdef SET_RIGHT_HALF_VFD_SKIN
385                 if ((surface->bpp == 8) && (src.surface->bpp==8))
386                 {
387                         __u8 *srcptr=(__u8*)src.surface->data;
388                         __u8 *dstptr=(__u8*)surface->data;
389                         __u8 *nomptr = new __u8[area.width()];
390                         unsigned char gray_max = 0;
391                         unsigned char gray_min = 255;
392                         unsigned char index = 0;
393                         unsigned char gray_value = 0;
394                         gRGB pixdata;
395 //                      printf("[bilt]srcarea.left:%d, src.surface->bypp : %d,srcarea.top() :%d,src.surface->stride : %d\n",srcarea.left(),src.surface->bypp,srcarea.top(),src.surface->stride);
396                         srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
397 //                      nomptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
398                         dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
399                         if(src.surface->clut.colors != 0)
400                         {
401                                 for (int y=0; y<area.height(); y++)
402                                 {
403                                         for(int x=0;x<area.width();x++)
404                                         {
405                                                 index = (unsigned char)(*(srcptr+x+y*src.surface->stride));
406                                                 pixdata = src.surface->clut.data[index];
407                                                 gray_value = ((pixdata.r+pixdata.g +pixdata.b)/3);
408         //                                      printf("%3d ",gray_value);
409                                                 if(gray_value > gray_max)
410                                                         gray_max = gray_value;
411                                                 if(gray_value < gray_min)
412                                                         gray_min = gray_value;
413                                         }
414         //                              printf("\n");
415                                 }
416                         }
417 //                      printf("\n[bilt] ### gray_min : %d, gray_max : %d\n\n",gray_min,gray_max);
418                         for (int y=0; y<area.height(); y++)
419                         {
420                                 if(src.surface->clut.colors != 0)
421                                 {
422                                         for(int x=0;x<area.width();x++)
423                                         {
424                                                 pixdata = src.surface->clut.data[*(srcptr+x)];
425                                                 gray_value = ((pixdata.r+pixdata.g +pixdata.b)/3);
426                                                 if(gray_max==gray_min)
427                                                         *(nomptr+x)=gray_value;
428 /*                                              else if(y == 0 || y == area.height()-1 || x == 0 || x == area.width()-1)
429                                                         *(nomptr+x) = 255;*/
430                                                 else
431                                                         *(nomptr+x)=( ((gray_value - gray_min)*255)/(gray_max-gray_min) );
432         //                                      printf("%3d ",*(nomptr+x));
433                                         }
434         //                              printf("\n");
435                                 }
436                                 else
437                                 {
438                                         for(int x=0;x<area.width();x++)
439                                         {
440 /*                                              if(y == 0 || y == area.height()-1 || x == 0 || x == area.width()-1)
441                                                         *(nomptr+x) = 255;
442                                                 else
443                                                         *(nomptr+x)=*(srcptr+x);*/
444                                                 *(nomptr+x)=*(srcptr+x);
445 //                                              printf("%3d ",*(nomptr+x));
446                                         }
447 //                                      printf("\n");
448                                 }
449                                 if (flag & (blitAlphaTest|blitAlphaBlend))
450                                 {
451                       // no real alphatest yet
452                                         int width=area.width();
453 //                                      unsigned char *src=(unsigned char*)srcptr;
454                                         unsigned char *src=(unsigned char*)nomptr;
455                                         unsigned char *dst=(unsigned char*)dstptr;
456                                                 // use duff's device here!
457                                         while (width--)
458                                         {
459                                                 if (!*src)
460                                                 {
461                                                         src++;
462                                                         dst++;
463                                                 } else
464                                                         *dst++=*src++;
465                                         }
466                                 } else
467 //                                      memcpy(dstptr, srcptr, area.width()*surface->bypp);
468                                         memcpy(dstptr, nomptr, area.width()*surface->bypp);
469                                 srcptr+=src.surface->stride;
470                                 dstptr+=surface->stride;
471                         }
472                         delete [] nomptr;
473 #else
474                 if ((surface->bpp == 8) && (src.surface->bpp==8))
475                 {
476                         __u8 *srcptr=(__u8*)src.surface->data;
477                         __u8 *dstptr=(__u8*)surface->data;
478
479                         srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
480                         dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
481                         for (int y=0; y<area.height(); y++)
482                         {
483                                 if (flag & (blitAlphaTest|blitAlphaBlend))
484                                 {
485                       // no real alphatest yet
486                                         int width=area.width();
487                                         unsigned char *src=(unsigned char*)srcptr;
488                                         unsigned char *dst=(unsigned char*)dstptr;
489                                                 // use duff's device here!
490                                         while (width--)
491                                         {
492                                                 if (!*src)
493                                                 {
494                                                         src++;
495                                                         dst++;
496                                                 } else
497                                                         *dst++=*src++;
498                                         }
499                                 } else
500                                         memcpy(dstptr, srcptr, area.width()*surface->bypp);
501                                 srcptr+=src.surface->stride;
502                                 dstptr+=surface->stride;
503                         }
504 #endif
505                 } else if ((surface->bpp == 32) && (src.surface->bpp==32))
506                 {
507                         __u32 *srcptr=(__u32*)src.surface->data;
508                         __u32 *dstptr=(__u32*)surface->data;
509
510                         srcptr+=srcarea.left()+srcarea.top()*src.surface->stride/4;
511                         dstptr+=area.left()+area.top()*surface->stride/4;
512                         for (int y=0; y<area.height(); y++)
513                         {
514                                 if (flag & blitAlphaTest)
515                                 {
516                                         int width=area.width();
517                                         unsigned long *src=(unsigned long*)srcptr;
518                                         unsigned long *dst=(unsigned long*)dstptr;
519
520                                         while (width--)
521                                         {
522                                                 if (!((*src)&0xFF000000))
523                                                 {
524                                                         src++;
525                                                         dst++;
526                                                 } else
527                                                         *dst++=*src++;
528                                         }
529                                 } else if (flag & blitAlphaBlend)
530                                 {
531                                         // uh oh. this is only until hardware accel is working.
532
533                                         int width=area.width();
534                                                         // ARGB color space!
535                                         unsigned char *src=(unsigned char*)srcptr;
536                                         unsigned char *dst=(unsigned char*)dstptr;
537
538 #define BLEND(x, y, a) (y + ((x-y) * a)/256)
539                                         while (width--)
540                                         {
541                                                 unsigned char sa = src[3];
542                                                 unsigned char sr = src[2];
543                                                 unsigned char sg = src[1];
544                                                 unsigned char sb = src[0];
545
546                                                 unsigned char da = dst[3];
547                                                 unsigned char dr = dst[2];
548                                                 unsigned char dg = dst[1];
549                                                 unsigned char db = dst[0];
550
551                                                 dst[3] = BLEND(0xFF, da, sa);
552                                                 dst[2] = BLEND(sr, dr, sa);
553                                                 dst[1] = BLEND(sg, dg, sa);
554                                                 dst[0] = BLEND(sb, db, sa);
555 #undef BLEND
556
557                                                 src += 4; dst += 4;
558                                         }
559                                 } else
560                                         memcpy(dstptr, srcptr, area.width()*surface->bypp);
561                                 srcptr+=src.surface->stride/4;
562                                 dstptr+=surface->stride/4;
563                         }
564                 } else if ((surface->bpp == 32) && (src.surface->bpp==8))
565                 {       
566                         __u8 *srcptr=(__u8*)src.surface->data;
567                         __u8 *dstptr=(__u8*)surface->data; // !!
568                         __u32 pal[256];
569
570                         for (int i=0; i<256; ++i)
571                         {
572                                 if (src.surface->clut.data && (i<src.surface->clut.colors))
573                                         pal[i]=(src.surface->clut.data[i].a<<24)|(src.surface->clut.data[i].r<<16)|(src.surface->clut.data[i].g<<8)|(src.surface->clut.data[i].b);
574                                 else
575                                         pal[i]=0x010101*i;
576                                 pal[i]^=0xFF000000;
577                         }
578
579                         srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
580                         dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
581                         for (int y=0; y<area.height(); y++)
582                         {
583                                 int width=area.width();
584                                 unsigned char *psrc=(unsigned char*)srcptr;
585                                 __u32 *dst=(__u32*)dstptr;
586                                 if (flag & blitAlphaTest)
587                                         blit_8i_to_32_at(dst, psrc, pal, width);
588                                 else if (flag & blitAlphaBlend)
589                                         blit_8i_to_32_ab(dst, psrc, pal, width);
590                                 else
591                                         blit_8i_to_32(dst, psrc, pal, width);
592                                 srcptr+=src.surface->stride;
593                                 dstptr+=surface->stride;
594                         }
595                 } else if ((surface->bpp == 16) && (src.surface->bpp==8))
596                 {
597                         __u8 *srcptr=(__u8*)src.surface->data;
598                         __u8 *dstptr=(__u8*)surface->data; // !!
599                         __u32 pal[256];
600
601                         for (int i=0; i<256; ++i)
602                         {
603                                 __u32 icol;
604                                 if (src.surface->clut.data && (i<src.surface->clut.colors))
605                                         icol=(src.surface->clut.data[i].a<<24)|(src.surface->clut.data[i].r<<16)|(src.surface->clut.data[i].g<<8)|(src.surface->clut.data[i].b);
606                                 else
607                                         icol=0x010101*i;
608 #if BYTE_ORDER == LITTLE_ENDIAN
609                                 pal[i] = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
610 #else
611                                 pal[i] = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
612 #endif
613                                 pal[i]^=0xFF000000;
614                         }
615
616                         srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
617                         dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
618
619                         if (flag & blitAlphaBlend)
620                                 eWarning("ignore unsupported 8bpp -> 16bpp alphablend!");
621
622                         for (int y=0; y<area.height(); y++)
623                         {
624                                 int width=area.width();
625                                 unsigned char *psrc=(unsigned char*)srcptr;
626                                 __u16 *dst=(__u16*)dstptr;
627                                 if (flag & blitAlphaTest)
628                                         blit_8i_to_16_at(dst, psrc, pal, width);
629                                 else
630                                         blit_8i_to_16(dst, psrc, pal, width);
631                                 srcptr+=src.surface->stride;
632                                 dstptr+=surface->stride;
633                         }
634                 } else if ((surface->bpp == 16) && (src.surface->bpp==32))
635                 {
636                         __u8 *srcptr=(__u8*)src.surface->data;
637                         __u8 *dstptr=(__u8*)surface->data;
638
639                         srcptr+=srcarea.left()+srcarea.top()*src.surface->stride;
640                         dstptr+=area.left()+area.top()*surface->stride;
641
642                         if (flag & blitAlphaBlend)
643                                 eWarning("ignore unsupported 32bpp -> 16bpp alphablend!");
644
645                         for (int y=0; y<area.height(); y++)
646                         {
647                                 int width=area.width();
648                                 __u32 *srcp=(__u32*)srcptr;
649                                 __u16 *dstp=(__u16*)dstptr;
650
651                                 if (flag & blitAlphaTest)
652                                 {
653                                         while (width--)
654                                         {
655                                                 if (!((*srcp)&0xFF000000))
656                                                 {
657                                                         srcp++;
658                                                         dstp++;
659                                                 } else
660                                                 {
661                                                         __u32 icol = *srcp++;
662 #if BYTE_ORDER == LITTLE_ENDIAN
663                                                         *dstp++ = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
664 #else
665                                                         *dstp++ = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
666 #endif
667                                                 }
668                                         }
669                                 } else
670                                 {
671                                         while (width--)
672                                         {
673                                                 __u32 icol = *srcp++;
674 #if BYTE_ORDER == LITTLE_ENDIAN
675                                                 *dstp++ = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
676 #else
677                                                 *dstp++ = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
678 #endif
679                                         }
680                                 }
681                                 srcptr+=src.surface->stride;
682                                 dstptr+=surface->stride;
683                         }
684                 } else
685                         eWarning("cannot blit %dbpp from %dbpp", surface->bpp, src.surface->bpp);
686         }
687 }
688
689 #undef FIX
690
691 void gPixmap::mergePalette(const gPixmap &target)
692 {
693         if ((!surface->clut.colors) || (!target.surface->clut.colors))
694                 return;
695
696         gColor *lookup=new gColor[surface->clut.colors];
697
698         for (int i=0; i<surface->clut.colors; i++)
699                 lookup[i].color=target.surface->clut.findColor(surface->clut.data[i]);
700         
701         delete [] surface->clut.data;
702         surface->clut.colors=target.surface->clut.colors;
703         surface->clut.data=new gRGB[surface->clut.colors];
704         memcpy(surface->clut.data, target.surface->clut.data, sizeof(gRGB)*surface->clut.colors);
705
706         __u8 *dstptr=(__u8*)surface->data;
707
708         for (int ay=0; ay<surface->y; ay++)
709         {
710                 for (int ax=0; ax<surface->x; ax++)
711                         dstptr[ax]=lookup[dstptr[ax]];
712                 dstptr+=surface->stride;
713         }
714         
715         delete [] lookup;
716 }
717
718 static inline int sgn(int a)
719 {
720         if (a < 0)
721                 return -1;
722         else if (!a)
723                 return 0;
724         else
725                 return 1;
726 }
727
728 void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color)
729 {
730         __u8 *srf8 = 0;
731         __u16 *srf16 = 0;
732         __u32 *srf32 = 0;
733         int stride = surface->stride;
734
735         if (clip.rects.empty())
736                 return;
737
738         __u16 col16;
739         __u32 col = 0;
740         if (surface->bpp == 8)
741                 srf8 = (__u8*)surface->data;
742         else
743         {
744                 srf32 = (__u32*)surface->data;
745                 if (surface->clut.data && color < surface->clut.colors)
746                         col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
747                 else
748                         col=0x10101*color;
749                 col^=0xFF000000;
750         }
751
752         if (surface->bpp == 16)
753 #if BYTE_ORDER == LITTLE_ENDIAN
754                 col16=bswap_16(((col & 0xFF) >> 3) << 11 | ((col & 0xFF00) >> 10) << 5 | (col & 0xFF0000) >> 19);
755 #else
756                 col16=((col & 0xFF) >> 3) << 11 | ((col & 0xFF00) >> 10) << 5 | (col & 0xFF0000) >> 19;
757 #endif
758
759         int xa = start.x(), ya = start.y(), xb = dst.x(), yb = dst.y();
760         int dx, dy, x, y, s1, s2, e, temp, swap, i;
761         dy=abs(yb-ya);
762         dx=abs(xb-xa);
763         s1=sgn(xb-xa);
764         s2=sgn(yb-ya);
765         x=xa;
766         y=ya;
767         if (dy>dx)
768         {
769                 temp=dx;
770                 dx=dy;
771                 dy=temp;
772                 swap=1;
773         } else
774                 swap=0;
775         e = 2*dy-dx;
776
777         int lasthit = 0;
778         for(i=1; i<=dx; i++)
779         {
780                                 /* i don't like this clipping loop, but the only */
781                                 /* other choice i see is to calculate the intersections */
782                                 /* before iterating through the pixels. */
783                                 
784                                 /* one could optimize this because of the ordering */
785                                 /* of the bands. */
786                                 
787                 lasthit = 0;
788                 int a = lasthit;
789                 
790                         /* if last pixel was invisble, first check bounding box */
791                 if (a == -1)
792                 {
793                                 /* check if we just got into the bbox again */
794                         if (clip.extends.contains(x, y))
795                                 lasthit = a = 0;
796                         else
797                                 goto fail;
798                 } else if (!clip.rects[a].contains(x, y))
799                 {
800                         do
801                         {
802                                 ++a;
803                                 if ((unsigned int)a == clip.rects.size())
804                                         a = 0;
805                                 if (a == lasthit)
806                                 {
807                                         goto fail;
808                                         lasthit = -1;
809                                 }
810                         } while (!clip.rects[a].contains(x, y));
811                         lasthit = a;
812                 }
813
814                 if (srf8)
815                         srf8[y * stride + x] = color;
816                 else if (srf16)
817                         srf16[y * stride/2 + x] = col16;
818                 else
819                         srf32[y * stride/4 + x] = col;
820 fail:
821                 while (e>=0)
822                 {
823                         if (swap==1)
824                                 x+=s1;
825                         else
826                                 y+=s2;
827                         e-=2*dx;
828                 }
829
830                 if (swap==1)
831                         y+=s2;
832                 else
833                         x+=s1;
834                 e+=2*dy;
835         }
836 }
837
838 gColor gPalette::findColor(const gRGB &rgb) const
839 {
840                 /* grayscale? */
841         if (!data)
842                 return (rgb.r + rgb.g + rgb.b) / 3;
843         
844         int difference=1<<30, best_choice=0;
845         for (int t=0; t<colors; t++)
846         {
847                 int ttd;
848                 int td=(signed)(rgb.r-data[t].r); td*=td; td*=(255-data[t].a);
849                 ttd=td;
850                 if (ttd>=difference)
851                         continue;
852                 td=(signed)(rgb.g-data[t].g); td*=td; td*=(255-data[t].a);
853                 ttd+=td;
854                 if (ttd>=difference)
855                         continue;
856                 td=(signed)(rgb.b-data[t].b); td*=td; td*=(255-data[t].a);
857                 ttd+=td;
858                 if (ttd>=difference)
859                         continue;
860                 td=(signed)(rgb.a-data[t].a); td*=td; td*=255;
861                 ttd+=td;
862                 if (ttd>=difference)
863                         continue;
864                 if (!ttd)
865                         return t;
866                 difference=ttd;
867                 best_choice=t;
868         }
869         return best_choice;
870 }
871
872 DEFINE_REF(gPixmap);
873
874 gPixmap::~gPixmap()
875 {
876         if (must_delete_surface)
877                 delete surface;
878 }
879
880 gPixmap::gPixmap(gSurface *surface)
881         :surface(surface), must_delete_surface(false)
882 {
883 }
884
885 gPixmap::gPixmap(eSize size, int bpp, int accel)
886         :must_delete_surface(true)
887 {
888         surface = new gSurface(size, bpp, accel);
889 }
890