Tabs to spaces, more consistent formatting.
[AROS.git] / workbench / libs / muimaster / classes / bitmap.c
blob977287ca1c7d786d32919850530a8782ed1d3be0
1 /*
2 Copyright © 2002-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <graphics/gfx.h>
7 #include <graphics/view.h>
8 #include <clib/alib_protos.h>
9 #include <cybergraphx/cybergraphics.h>
10 #include <proto/exec.h>
11 #include <proto/graphics.h>
12 #include <proto/utility.h>
13 #include <proto/cybergraphics.h>
14 #include <proto/intuition.h>
15 #include <proto/muimaster.h>
17 #include "mui.h"
18 #include "muimaster_intern.h"
19 #include "support.h"
21 #include <string.h>
23 extern struct Library *MUIMasterBase;
25 struct MUI_BitmapData
27 struct BitMap *bm, *remapped_bm;
28 ULONG *sourcecolors;
29 LONG width, height, precision, transparent;
30 UBYTE *mappingtable;
31 PLANEPTR mask;
32 WORD *remaptable;
33 BYTE usefriend;
36 static void remap_bitmap(struct IClass *cl, Object *obj)
38 struct MUI_BitmapData *data = INST_DATA(cl, obj);
39 struct BitMap *friendbm = NULL;
40 struct RastPort temprp, bmrp, *scrrp;
41 UBYTE *linebuffer;
42 ULONG *cgfxcoltab = NULL;
43 LONG bmflags = 0;
44 WORD bmdepth, bmwidth, bmheight, bmcols, x, y;
46 if (!data->mappingtable && !data->sourcecolors)
47 return;
48 if (!data->bm || (data->width < 1) || (data->height < 1))
49 return;
51 /* Don't remap if bitmap is hicolor/truecolor */
52 if (GetBitMapAttr(data->bm, BMA_DEPTH) > 8)
53 return;
55 if (!data->mappingtable && !data->remaptable)
57 data->remaptable =
58 AllocVec(256 * sizeof(WORD), MEMF_PUBLIC | MEMF_CLEAR);
59 if (!data->remaptable)
60 return;
63 scrrp = &_screen(obj)->RastPort;
65 if (data->usefriend)
67 friendbm = scrrp->BitMap;
68 bmflags |= BMF_MINPLANES;
71 linebuffer = AllocVec(data->width + 16, MEMF_PUBLIC);
72 if (!linebuffer)
73 return;
75 bmdepth = GetBitMapAttr(scrrp->BitMap, BMA_DEPTH);
76 if (bmdepth > 8)
77 bmdepth = 8;
79 bmcols = 1L << bmdepth;
81 data->remapped_bm =
82 AllocBitMap(data->width, data->height, bmdepth, bmflags, friendbm);
84 if (!data->remapped_bm)
86 FreeVec(linebuffer);
87 return;
90 bmwidth = GetBitMapAttr(data->remapped_bm, BMA_WIDTH);
91 bmheight = GetBitMapAttr(data->remapped_bm, BMA_HEIGHT);
93 if (data->transparent != -1)
95 data->mask = AllocRaster(bmwidth, bmheight);
96 memset(data->mask, 0xff, RASSIZE(bmwidth, bmheight));
99 if (CyberGfxBase &&
100 !data->mappingtable &&
101 (GetBitMapAttr(data->remapped_bm, BMA_DEPTH) >= 15))
103 cgfxcoltab = AllocVec(bmcols * sizeof(ULONG), MEMF_ANY);
105 if (cgfxcoltab)
107 for (y = 0; y < bmcols; y++)
109 ULONG red = data->sourcecolors[y * 3] & 0xFF000000;
110 ULONG green = data->sourcecolors[y * 3 + 1] & 0xFF000000;
111 ULONG blue = data->sourcecolors[y * 3 + 2] & 0xFF000000;
113 cgfxcoltab[y] = (red >> 8) | (green >> 16) | (blue >> 24);
119 InitRastPort(&temprp);
120 temprp.BitMap = AllocBitMap(data->width, 1, 1, 0, NULL);
122 InitRastPort(&bmrp);
124 for (y = 0; y < data->height; y++)
126 /* Read a line from source bitmap */
128 bmrp.BitMap = data->bm;
129 if (temprp.BitMap)
131 ReadPixelLine8(&bmrp, 0, y, data->width, linebuffer, &temprp);
133 else
135 for (x = 0; x < data->width; x++)
137 linebuffer[x] = ReadPixel(&bmrp, x, y);
141 /* Build the mask, totaly slow but works */
142 if (data->mask)
144 UBYTE *mask = data->mask + y * bmwidth / 8;
145 UBYTE xmask = 0x80;
147 for (x = 0; x < data->width; x++)
149 if (linebuffer[x] == data->transparent)
151 *mask &= ~xmask;
154 xmask >>= 1;
155 if (!xmask)
157 xmask = 0x80;
158 mask++;
163 /* Remap the line */
164 if (data->mappingtable)
166 for (x = 0; x < data->width; x++)
168 linebuffer[x] = data->mappingtable[linebuffer[x]];
171 else if (!cgfxcoltab)
173 for (x = 0; x < data->width; x++)
175 UBYTE pixel = linebuffer[x];
176 UBYTE remappixel = data->remaptable[pixel];
178 if (!remappixel)
180 struct TagItem tags[3];
181 tags[0].ti_Tag = OBP_Precision;
182 tags[0].ti_Data = data->precision;
183 tags[1].ti_Tag = OBP_FailIfBad;
184 tags[1].ti_Data = FALSE;
185 tags[2].ti_Tag = 0;
187 data->remaptable[pixel] = remappixel =
188 ObtainBestPenA(_screen(obj)->ViewPort.ColorMap,
189 data->sourcecolors[pixel * 3],
190 data->sourcecolors[pixel * 3 + 1],
191 data->sourcecolors[pixel * 3 + 2], tags) | 0x100;
194 linebuffer[x] = (remappixel & 0xFF);
199 /* Write line into destination bitmap */
201 bmrp.BitMap = data->remapped_bm;
203 if (cgfxcoltab)
205 WriteLUTPixelArray(linebuffer,
208 data->width,
209 &bmrp, cgfxcoltab, 0, y, data->width, 1, CTABFMT_XRGB8);
211 else
213 bmrp.BitMap = data->remapped_bm;
214 if (temprp.BitMap)
216 WritePixelLine8(&bmrp, 0, y, data->width, linebuffer,
217 &temprp);
219 else
221 for (x = 0; x < data->width; x++)
223 SetAPen(&bmrp, linebuffer[x]);
224 WritePixel(&bmrp, x, y);
232 if (temprp.BitMap)
234 WaitBlit();
235 FreeBitMap(temprp.BitMap);
238 FreeVec(cgfxcoltab);
239 FreeVec(linebuffer);
242 /**************************************************************************
243 OM_NEW
244 **************************************************************************/
245 IPTR Bitmap__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
247 struct MUI_BitmapData *data;
248 struct TagItem *tag, *tags;
250 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
251 if (!obj)
252 return FALSE;
254 data = INST_DATA(cl, obj);
256 data->precision = PRECISION_GUI;
257 data->transparent = -1;
259 /* parse initial taglist */
261 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
263 switch (tag->ti_Tag)
265 case MUIA_Bitmap_Bitmap:
266 data->bm = (struct BitMap *)tag->ti_Data;
267 break;
269 case MUIA_Bitmap_Height:
270 data->height = (LONG) tag->ti_Data;
271 break;
273 case MUIA_Bitmap_MappingTable:
274 data->mappingtable = (UBYTE *) tag->ti_Data;
275 break;
277 case MUIA_Bitmap_Precision:
278 data->precision = (LONG) tag->ti_Data;
279 break;
281 case MUIA_Bitmap_SourceColors:
282 data->sourcecolors = (ULONG *) tag->ti_Data;
283 break;
285 case MUIA_Bitmap_Transparent:
286 data->transparent = (LONG) tag->ti_Data;
287 break;
289 case MUIA_Bitmap_UseFriend:
290 data->usefriend = (tag->ti_Data != 0);
291 break;
293 case MUIA_Bitmap_Width:
294 data->width = (LONG) tag->ti_Data;
295 break;
300 return (IPTR) obj;
303 /**************************************************************************
304 OM_DISPOSE
305 **************************************************************************/
306 IPTR Bitmap__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
308 struct MUI_BitmapData *data = INST_DATA(cl, obj);
310 if (data->remapped_bm)
312 WaitBlit();
313 FreeBitMap(data->remapped_bm);
315 if (data->remaptable)
316 FreeVec(data->remaptable);
318 return DoSuperMethodA(cl, obj, msg);
321 /**************************************************************************
322 OM_SET
323 **************************************************************************/
324 IPTR Bitmap__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
326 struct MUI_BitmapData *data = INST_DATA(cl, obj);
327 struct TagItem *tags = msg->ops_AttrList;
328 struct TagItem *tag;
330 while ((tag = NextTagItem(&tags)) != NULL)
332 switch (tag->ti_Tag)
334 case MUIA_Bitmap_Bitmap:
335 if (!data->remapped_bm)
337 data->bm = (struct BitMap *)tag->ti_Data;
339 break;
341 case MUIA_Bitmap_Height:
342 data->height = (LONG) tag->ti_Data;
343 break;
345 case MUIA_Bitmap_MappingTable:
346 data->mappingtable = (UBYTE *) tag->ti_Data;
347 break;
349 case MUIA_Bitmap_Precision:
350 data->precision = (LONG) tag->ti_Data;
351 break;
353 case MUIA_Bitmap_SourceColors:
354 data->sourcecolors = (ULONG *) tag->ti_Data;
355 break;
357 case MUIA_Bitmap_Transparent:
358 data->transparent = (LONG) tag->ti_Data;
359 break;
361 case MUIA_Bitmap_Width:
362 data->width = (LONG) tag->ti_Data;
363 break;
368 return DoSuperMethodA(cl, obj, (Msg) msg);
371 /**************************************************************************
372 OM_GET
373 **************************************************************************/
374 IPTR Bitmap__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
376 #define STORE *(msg->opg_Storage)
378 struct MUI_BitmapData *data = INST_DATA(cl, obj);
380 switch (msg->opg_AttrID)
382 case MUIA_Bitmap_Bitmap:
383 STORE = (IPTR) data->bm;
384 return TRUE;
386 case MUIA_Bitmap_Height:
387 STORE = (IPTR) data->height;
388 return TRUE;
390 case MUIA_Bitmap_MappingTable:
391 STORE = (IPTR) data->mappingtable;
392 return TRUE;
394 case MUIA_Bitmap_Precision:
395 STORE = (IPTR) data->precision;
396 return TRUE;
398 case MUIA_Bitmap_RemappedBitmap:
399 STORE = (IPTR) data->remapped_bm;
400 return TRUE;
402 case MUIA_Bitmap_SourceColors:
403 STORE = (IPTR) data->sourcecolors;
404 return TRUE;
406 case MUIA_Bitmap_Transparent:
407 STORE = (IPTR) data->transparent;
408 return TRUE;
410 case MUIA_Bitmap_Width:
411 STORE = (IPTR) data->width;
412 return TRUE;
415 return DoSuperMethodA(cl, obj, (Msg) msg);
416 #undef STORE
419 /**************************************************************************
420 MUIM_Setup
421 **************************************************************************/
422 IPTR Bitmap__MUIM_Setup(struct IClass *cl, Object *obj, Msg msg)
424 //struct MUI_BitmapData *data = INST_DATA(cl, obj);
426 if (!DoSuperMethodA(cl, obj, (Msg) msg))
427 return FALSE;
429 remap_bitmap(cl, obj);
431 return TRUE;
434 /**************************************************************************
435 MUIM_Cleanup
436 **************************************************************************/
437 IPTR Bitmap__MUIM_Cleanup(struct IClass *cl, Object *obj, Msg msg)
439 struct MUI_BitmapData *data = INST_DATA(cl, obj);
441 if (data->mask)
443 LONG bmwidth = GetBitMapAttr(data->remapped_bm, BMA_WIDTH);
444 LONG bmheight = GetBitMapAttr(data->remapped_bm, BMA_HEIGHT);
445 FreeRaster(data->mask, bmwidth, bmheight);
447 data->mask = NULL;
450 if (data->remapped_bm)
452 WaitBlit();
453 FreeBitMap(data->remapped_bm);
454 data->remapped_bm = NULL;
456 if (data->remaptable)
458 WORD i;
460 for (i = 0; i < 256; i++)
462 if (data->remaptable[i])
464 ReleasePen(_screen(obj)->ViewPort.ColorMap,
465 data->remaptable[i] & 0xFF);
466 data->remaptable[i] = 0;
472 return DoSuperMethodA(cl, obj, (Msg) msg);
475 /**************************************************************************
476 MUIM_AskMinMax
477 **************************************************************************/
478 IPTR Bitmap__MUIM_AskMinMax(struct IClass *cl, Object *obj,
479 struct MUIP_AskMinMax *msg)
481 DoSuperMethodA(cl, obj, (Msg) msg);
483 msg->MinMaxInfo->MinWidth += 1;
484 msg->MinMaxInfo->MinHeight += 1;
486 msg->MinMaxInfo->DefWidth += 1;
487 msg->MinMaxInfo->DefHeight += 1;
489 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
490 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
492 return TRUE;
495 /**************************************************************************
496 MUIM_Draw
497 **************************************************************************/
498 IPTR Bitmap__MUIM_Draw(struct IClass *cl, Object *obj,
499 struct MUIP_Draw *msg)
501 struct MUI_BitmapData *data = INST_DATA(cl, obj);
502 struct BitMap *bm;
504 DoSuperMethodA(cl, obj, (Msg) msg);
506 bm = data->remapped_bm ? data->remapped_bm : data->bm;
507 if (bm)
509 LONG width, height;
511 width = data->width;
512 height = data->height;
514 if (width > _mwidth(obj))
515 width = _mwidth(obj);
516 if (height > _mheight(obj))
517 height = _mheight(obj);
519 if ((width > 0) && (height > 0))
521 if (data->mask)
523 BltMaskBitMapRastPort(bm, 0, 0, _rp(obj), _mleft(obj),
524 _mtop(obj), width, height, 0xE0, data->mask);
526 else
528 BltBitMapRastPort(bm, 0, 0, _rp(obj), _mleft(obj),
529 _mtop(obj), width, height, 0xC0);
534 return TRUE;
538 BOOPSI_DISPATCHER(IPTR, Bitmap_Dispatcher, cl, obj, msg)
540 switch (msg->MethodID)
542 case OM_NEW:
543 return Bitmap__OM_NEW(cl, obj, (struct opSet *)msg);
544 case OM_DISPOSE:
545 return Bitmap__OM_DISPOSE(cl, obj, msg);
546 case OM_SET:
547 return Bitmap__OM_SET(cl, obj, (struct opSet *)msg);
548 case OM_GET:
549 return Bitmap__OM_GET(cl, obj, (struct opGet *)msg);
550 case MUIM_Setup:
551 return Bitmap__MUIM_Setup(cl, obj, msg);
552 case MUIM_Cleanup:
553 return Bitmap__MUIM_Cleanup(cl, obj, msg);
554 case MUIM_AskMinMax:
555 return Bitmap__MUIM_AskMinMax(cl, obj,
556 (struct MUIP_AskMinMax *)msg);
557 case MUIM_Draw:
558 return Bitmap__MUIM_Draw(cl, obj, (struct MUIP_Draw *)msg);
561 return DoSuperMethodA(cl, obj, msg);
563 BOOPSI_DISPATCHER_END
566 * Class descriptor.
568 const struct __MUIBuiltinClass _MUI_Bitmap_desc =
570 MUIC_Bitmap,
571 MUIC_Area,
572 sizeof(struct MUI_BitmapData),
573 (void *) Bitmap_Dispatcher