yes! ich habs kaputt gemacht! (doesn't compile anymore, doesn't work anymore,
[enigma2.git] / lib / gdi / gpixmap.cpp
1 #include <lib/gdi/gpixmap.h>
2
3 gLookup::gLookup()
4         :size(0), lookup(0)
5 {
6 }
7
8 gLookup::gLookup(int size, const gPalette &pal, const gRGB &start, const gRGB &end)
9         :size(0), lookup(0)
10 {
11         build(size, pal, start, end);
12 }
13
14 void gLookup::build(int _size, const gPalette &pal, const gRGB &start, const gRGB &end)
15 {
16         if (lookup)
17         {
18                 delete [] lookup;
19                 lookup=0;
20                 size=0;
21         }
22         size=_size;
23         if (!size)
24                 return;
25         lookup=new gColor[size];
26         
27         for (int i=0; i<size; i++)
28         {
29                 gRGB col;
30                 if (i)
31                 {
32                         int rdiff=-start.r+end.r;
33                         int gdiff=-start.g+end.g;
34                         int bdiff=-start.b+end.b;
35                         int adiff=-start.a+end.a;
36                         rdiff*=i; rdiff/=(size-1);
37                         gdiff*=i; gdiff/=(size-1);
38                         bdiff*=i; bdiff/=(size-1);
39                         adiff*=i; adiff/=(size-1);
40                         col.r=start.r+rdiff;
41                         col.g=start.g+gdiff;
42                         col.b=start.b+bdiff;
43                         col.a=start.a+adiff;
44                 } else
45                         col=start;
46                 lookup[i]=pal.findColor(col);
47         }
48 }
49
50 gSurface::~gSurface()
51 {
52 }
53
54 gSurfaceSystem::gSurfaceSystem(eSize size, int _bpp)
55 {
56         x=size.width();
57         y=size.height();
58         bpp=_bpp;
59         switch (bpp)
60         {
61         case 8:
62                 bypp=1;
63                 break;
64         case 15:
65         case 16:
66                 bypp=2;
67                 break;
68         case 24:                // never use 24bit mode
69         case 32:
70                 bypp=4;
71                 break;
72         default:
73                 bypp=(bpp+7)/8;
74         }
75         stride=x*bypp;
76         if (bpp==8)
77         {
78                 clut.colors=256;
79                 clut.data=new gRGB[clut.colors];
80         } else
81         {
82                 clut.colors=0;
83                 clut.data=0;
84         }
85         data=malloc(x*y*bypp);
86 }
87
88 gSurfaceSystem::~gSurfaceSystem()
89 {
90         free(data);
91         delete[] clut.data;
92 }
93
94 gPixmap *gPixmap::lock()
95 {
96         contentlock.lock(1);
97         return this;
98 }
99
100 void gPixmap::unlock()
101 {
102         contentlock.unlock(1);
103 }
104
105 void gPixmap::fill(const eRect &area, const gColor &color)
106 {
107         if ((area.height()<=0) || (area.width()<=0))
108                 return;
109         if (surface->bpp == 8)
110                 for (int y=area.top(); y<area.bottom(); y++)
111                         memset(((__u8*)surface->data)+y*surface->stride+area.left(), color.color, area.width());
112         else if (surface->bpp == 32)
113                 for (int y=area.top(); y<area.bottom(); y++)
114                 {
115                         __u32 *dst=(__u32*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
116                         int x=area.width();
117                         __u32 col;
118
119                         if (surface->clut.data && color < surface->clut.colors)
120                                 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
121                         else
122                                 col=0x10101*color;
123                         col^=0xFF000000;                        
124                         while (x--)
125                                 *dst++=col;
126                 }
127         else
128                 eWarning("couldn't fill %d bpp", surface->bpp);
129 }
130
131 void gPixmap::blit(const gPixmap &src, ePoint pos, const eRect &clip, int flag)
132 {
133         eRect area=eRect(pos, src.getSize());
134         area&=clip;
135         area&=eRect(ePoint(0, 0), getSize());
136         if ((area.width()<0) || (area.height()<0))
137                 return;
138
139         eRect srcarea=area;
140         srcarea.moveBy(-pos.x(), -pos.y());
141
142         if ((surface->bpp == 8) && (src.surface->bpp==8))
143         {
144                 __u8 *srcptr=(__u8*)src.surface->data;
145                 __u8 *dstptr=(__u8*)surface->data;
146         
147                 srcptr+=srcarea.left()*surface->bypp+srcarea.top()*src.surface->stride;
148                 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
149                 for (int y=0; y<area.height(); y++)
150                 {
151                         if (flag & blitAlphaTest)
152                         {
153               // no real alphatest yet
154                                 int width=area.width();
155                                 unsigned char *src=(unsigned char*)srcptr;
156                                 unsigned char *dst=(unsigned char*)dstptr;
157                                         // use duff's device here!
158                                 while (width--)
159                                 {
160                                         if (!*src)
161                                         {
162                                                 src++;
163                                                 dst++;
164                                         } else
165                                                 *dst++=*src++;
166                                 }
167                         } else
168                                 memcpy(dstptr, srcptr, area.width()*surface->bypp);
169                         srcptr+=src.surface->stride;
170                         dstptr+=surface->stride;
171                 }
172         } else if ((surface->bpp == 32) && (src.surface->bpp==8))
173         {
174                 __u8 *srcptr=(__u8*)src.surface->data;
175                 __u8 *dstptr=(__u8*)surface->data; // !!
176                 __u32 pal[256];
177                 
178                 for (int i=0; i<256; ++i)
179                 {
180                         if (src.surface->clut.data && (i<src.surface->clut.colors))
181                                 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);
182                         else
183                                 pal[i]=0x010101*i;
184                         pal[i]^=0xFF000000;
185                 }
186         
187                 srcptr+=srcarea.left()*surface->bypp+srcarea.top()*src.surface->stride;
188                 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
189                 for (int y=0; y<area.height(); y++)
190                 {
191                         if (flag & blitAlphaTest)
192                         {
193               // no real alphatest yet
194                                 int width=area.width();
195                                 unsigned char *src=(unsigned char*)srcptr;
196                                 __u32 *dst=(__u32*)dstptr;
197                                         // use duff's device here!
198                                 while (width--)
199                                 {
200                                         if (!*src)
201                                         {
202                                                 src++;
203                                                 dst++;
204                                         } else
205                                                 *dst++=pal[*src++];
206                                 }
207                         } else
208                         {
209                                 int width=area.width();
210                                 unsigned char *src=(unsigned char*)srcptr;
211                                 __u32 *dst=(__u32*)dstptr;
212                                 while (width--)
213                                         *dst++=pal[*src++];
214                         }
215                         srcptr+=src.surface->stride;
216                         dstptr+=surface->stride;
217                 }
218         } else
219                 eFatal("cannot blit %dbpp from %dbpp", surface->bpp, src.surface->bpp);
220 }
221
222 void gPixmap::mergePalette(const gPixmap &target)
223 {
224         if ((!surface->clut.colors) || (!target.surface->clut.colors))
225                 return;
226         gColor *lookup=new gColor[surface->clut.colors];
227
228         for (int i=0; i<surface->clut.colors; i++)
229                 lookup[i].color=target.surface->clut.findColor(surface->clut.data[i]);
230         
231         delete [] surface->clut.data;
232         surface->clut.colors=target.surface->clut.colors;
233         surface->clut.data=new gRGB[surface->clut.colors];
234         memcpy(surface->clut.data, target.surface->clut.data, sizeof(gRGB)*surface->clut.colors);
235
236         __u8 *dstptr=(__u8*)surface->data;
237
238         for (int ay=0; ay<surface->y; ay++)
239         {
240                 for (int ax=0; ax<surface->x; ax++)
241                         dstptr[ax]=lookup[dstptr[ax]];
242                 dstptr+=surface->stride;
243         }
244         
245         delete [] lookup;
246 }
247
248 void gPixmap::line(ePoint start, ePoint dst, gColor color)
249 {
250 int Ax=start.x(),
251 Ay=start.y(), Bx=dst.x(),
252 By=dst.y(); int dX, dY, fbXincr,
253 fbYincr, fbXYincr, dPr, dPru, P; __u8
254 *AfbAddr = &((__u8*)surface->data)[Ay*surface->stride+Ax*surface->bypp]; __u8
255 *BfbAddr = &((__u8*)surface->data)[By*surface->stride+Bx*surface->bypp]; fbXincr=
256 surface->bypp; if ( (dX=Bx-Ax) >= 0) goto AFTERNEGX; dX=-dX;
257 fbXincr=-1; AFTERNEGX: fbYincr=surface->stride; if ( (dY=By 
258 -Ay) >= 0) goto AFTERNEGY; fbYincr=-surface->stride; dY=-dY;AFTERNEGY: 
259 fbXYincr = fbXincr+fbYincr; if (dY > dX) goto YisIndependent; dPr = dY+ 
260 dY; P = -dX; dPru = P+P; dY = dX>>1; XLOOP: *AfbAddr=color; *BfbAddr=color; if ((P+=dPr) > 0)
261 goto RightAndUp;  AfbAddr+=fbXincr; BfbAddr-=fbXincr; if ((dY=dY-1) > 0) goto XLOOP; *AfbAddr=color; if ((dX & 1)
262 == 0) return;  *BfbAddr=color; return; RightAndUp: AfbAddr+=fbXYincr; BfbAddr-=fbXYincr; P+=dPru; if ((dY=dY-1) >
263 0) goto XLOOP;  *AfbAddr=color; if ((dX & 1) == 0) return; *BfbAddr=color; return; YisIndependent: dPr = dX+dX; P
264 = -dY; dPru = P+P; dX = dY>>1; YLOOP: *AfbAddr=color; *BfbAddr=color; if ((P+=dPr) > 0) goto RightAndUp2; AfbAddr
265 +=fbYincr;  BfbAddr-=fbYincr; if ((dX=dX-1) > 0) goto YLOOP; *AfbAddr=color; if ((dY & 1) == 0) return; *BfbAddr=
266 color;return; RightAndUp2: AfbAddr+=fbXYincr; BfbAddr-=fbXYincr; P+=dPru; if ((dX=dX-1) > 0) goto YLOOP; *AfbAddr
267 =color; if((dY & 1) == 0) return; *BfbAddr=color; return;
268 }
269
270 gColor gPalette::findColor(const gRGB &rgb) const
271 {
272         int difference=1<<30, best_choice=0;
273         for (int t=0; t<colors; t++)
274         {
275                 int ttd;
276                 int td=(signed)(rgb.r-data[t].r); td*=td; td*=(255-data[t].a);
277                 ttd=td;
278                 if (ttd>=difference)
279                         continue;
280                 td=(signed)(rgb.g-data[t].g); td*=td; td*=(255-data[t].a);
281                 ttd+=td;
282                 if (ttd>=difference)
283                         continue;
284                 td=(signed)(rgb.b-data[t].b); td*=td; td*=(255-data[t].a);
285                 ttd+=td;
286                 if (ttd>=difference)
287                         continue;
288                 td=(signed)(rgb.a-data[t].a); td*=td; td*=255;
289                 ttd+=td;
290                 if (ttd>=difference)
291                         continue;
292                 difference=ttd;
293                 best_choice=t;
294         }
295         return best_choice;
296 }
297
298 DEFINE_REF(gPixmap);
299
300 gPixmap::~gPixmap()
301 {
302 }
303
304 gPixmap::gPixmap(gSurface *surface): surface(surface)
305 {
306 }
307
308 gPixmap::gPixmap(eSize size, int bpp)
309 {
310         surface = new gSurfaceSystem(size, bpp);
311 }
312