1 #include <lib/gdi/gpixmap.h>
2 #include <lib/gdi/region.h>
9 gLookup::gLookup(int size, const gPalette &pal, const gRGB &start, const gRGB &end)
12 build(size, pal, start, end);
15 void gLookup::build(int _size, const gPalette &pal, const gRGB &start, const gRGB &end)
26 lookup=new gColor[size];
28 for (int i=0; i<size; i++)
33 int rdiff=-start.r+end.r;
34 int gdiff=-start.g+end.g;
35 int bdiff=-start.b+end.b;
36 int adiff=-start.a+end.a;
37 rdiff*=i; rdiff/=(size-1);
38 gdiff*=i; gdiff/=(size-1);
39 bdiff*=i; bdiff/=(size-1);
40 adiff*=i; adiff/=(size-1);
47 lookup[i]=pal.findColor(col);
55 gSurfaceSystem::gSurfaceSystem(eSize size, int _bpp)
69 case 24: // never use 24bit mode
80 clut.data=new gRGB[clut.colors];
86 data=malloc(x*y*bypp);
89 gSurfaceSystem::~gSurfaceSystem()
95 gPixmap *gPixmap::lock()
101 void gPixmap::unlock()
103 contentlock.unlock(1);
106 void gPixmap::fill(const gRegion ®ion, const gColor &color)
109 for (i=0; i<region.rects.size(); ++i)
111 const eRect &area = region.rects[i];
112 if ((area.height()<=0) || (area.width()<=0))
114 if (surface->bpp == 8)
116 for (int y=area.top(); y<area.bottom(); y++)
117 memset(((__u8*)surface->data)+y*surface->stride+area.left(), color.color, area.width());
118 } else if (surface->bpp == 32)
119 for (int y=area.top(); y<area.bottom(); y++)
121 __u32 *dst=(__u32*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
125 if (surface->clut.data && color < surface->clut.colors)
126 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
134 eWarning("couldn't fill %d bpp", surface->bpp);
138 void gPixmap::blit(const gPixmap &src, ePoint pos, const gRegion &clip, int flag)
140 for (unsigned int i=0; i<clip.rects.size(); ++i)
142 eRect area=eRect(pos, src.size());
144 area&=eRect(ePoint(0, 0), size());
145 if ((area.width()<0) || (area.height()<0))
149 srcarea.moveBy(-pos.x(), -pos.y());
151 if ((surface->bpp == 8) && (src.surface->bpp==8))
153 __u8 *srcptr=(__u8*)src.surface->data;
154 __u8 *dstptr=(__u8*)surface->data;
156 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
157 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
158 for (int y=0; y<area.height(); y++)
160 if (flag & blitAlphaTest)
162 // no real alphatest yet
163 int width=area.width();
164 unsigned char *src=(unsigned char*)srcptr;
165 unsigned char *dst=(unsigned char*)dstptr;
166 // use duff's device here!
177 memcpy(dstptr, srcptr, area.width()*surface->bypp);
178 srcptr+=src.surface->stride;
179 dstptr+=surface->stride;
181 } else if ((surface->bpp == 32) && (src.surface->bpp==8))
183 __u8 *srcptr=(__u8*)src.surface->data;
184 __u8 *dstptr=(__u8*)surface->data; // !!
187 for (int i=0; i<256; ++i)
189 if (src.surface->clut.data && (i<src.surface->clut.colors))
190 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);
196 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
197 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
198 for (int y=0; y<area.height(); y++)
200 if (flag & blitAlphaTest)
202 // no real alphatest yet
203 int width=area.width();
204 unsigned char *src=(unsigned char*)srcptr;
205 __u32 *dst=(__u32*)dstptr;
206 // use duff's device here!
218 int width=area.width();
219 unsigned char *src=(unsigned char*)srcptr;
220 __u32 *dst=(__u32*)dstptr;
224 srcptr+=src.surface->stride;
225 dstptr+=surface->stride;
228 eFatal("cannot blit %dbpp from %dbpp", surface->bpp, src.surface->bpp);
232 void gPixmap::mergePalette(const gPixmap &target)
234 eDebug("merge palette! %p %p", surface, target.surface);
235 if ((!surface->clut.colors) || (!target.surface->clut.colors))
238 gColor *lookup=new gColor[surface->clut.colors];
240 for (int i=0; i<surface->clut.colors; i++)
241 lookup[i].color=target.surface->clut.findColor(surface->clut.data[i]);
243 delete [] surface->clut.data;
244 surface->clut.colors=target.surface->clut.colors;
245 surface->clut.data=new gRGB[surface->clut.colors];
246 memcpy(surface->clut.data, target.surface->clut.data, sizeof(gRGB)*surface->clut.colors);
248 __u8 *dstptr=(__u8*)surface->data;
250 for (int ay=0; ay<surface->y; ay++)
252 for (int ax=0; ax<surface->x; ax++)
253 dstptr[ax]=lookup[dstptr[ax]];
254 dstptr+=surface->stride;
261 static inline int sgn(int a)
271 void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color)
275 int stride = surface->stride;
277 if (clip.rects.empty())
281 if (surface->bpp == 8)
283 srf8 = (__u8*)surface->data;
284 } else if (surface->bpp == 32)
286 srf32 = (__u32*)surface->data;
288 if (surface->clut.data && color < surface->clut.colors)
289 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
295 int xa = start.x(), ya = start.y(), xb = dst.x(), yb = dst.y();
296 int dx, dy, x, y, s1, s2, e, temp, swap, i;
316 /* i don't like this clipping loop, but the only */
317 /* other choice i see is to calculate the intersections */
318 /* before iterating through the pixels. */
320 /* one could optimize this because of the ordering */
326 /* if last pixel was invisble, first check bounding box */
329 /* check if we just got into the bbox again */
330 if (clip.extends.contains(x, y))
334 } else if (!clip.rects[a].contains(x, y))
339 if (a == clip.rects.size())
346 } while (!clip.rects[a].contains(x, y));
351 srf8[y * stride + x] = color;
353 srf32[y * stride/4 + x] = col;
369 gColor gPalette::findColor(const gRGB &rgb) const
371 int difference=1<<30, best_choice=0;
372 for (int t=0; t<colors; t++)
375 int td=(signed)(rgb.r-data[t].r); td*=td; td*=(255-data[t].a);
379 td=(signed)(rgb.g-data[t].g); td*=td; td*=(255-data[t].a);
383 td=(signed)(rgb.b-data[t].b); td*=td; td*=(255-data[t].a);
387 td=(signed)(rgb.a-data[t].a); td*=td; td*=255;
405 gPixmap::gPixmap(gSurface *surface): surface(surface)
409 gPixmap::gPixmap(eSize size, int bpp)
411 surface = new gSurfaceSystem(size, bpp);