Some fix for scrolling with lasso.
[tangerine.git] / workbench / libs / muimaster / classes / bitmap.c
blob67b4406cc35106e27599728ff3ef33d2bc9078f4
1 /*
2 Copyright © 2002-2006, 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) return;
47 if (!data->bm || (data->width < 1) || (data->height < 1)) return;
49 /* Don't remap if bitmap is hicolor/truecolor */
50 if (GetBitMapAttr(data->bm, BMA_DEPTH) > 8) return;
52 if (!data->mappingtable && !data->remaptable)
54 data->remaptable = AllocVec(256 * sizeof(WORD), MEMF_PUBLIC | MEMF_CLEAR);
55 if (!data->remaptable) return;
58 scrrp = &_screen(obj)->RastPort;
60 if (data->usefriend)
62 friendbm = scrrp->BitMap;
63 bmflags |= BMF_MINPLANES;
66 linebuffer = AllocVec(data->width + 16, MEMF_PUBLIC);
67 if (!linebuffer) return;
69 bmdepth = GetBitMapAttr(scrrp->BitMap, BMA_DEPTH);
70 if (bmdepth > 8) bmdepth = 8;
72 bmcols = 1L << bmdepth;
74 data->remapped_bm = AllocBitMap(data->width, data->height, bmdepth, bmflags, friendbm);
76 if (!data->remapped_bm)
78 FreeVec(linebuffer);
79 return;
82 bmwidth = GetBitMapAttr(data->remapped_bm, BMA_WIDTH);
83 bmheight = GetBitMapAttr(data->remapped_bm, BMA_HEIGHT);
85 if (data->transparent != -1)
87 data->mask = AllocRaster(bmwidth,bmheight);
88 memset(data->mask, 0xff, RASSIZE(bmwidth, bmheight));
91 if (CyberGfxBase &&
92 !data->mappingtable &&
93 (GetBitMapAttr(data->remapped_bm, BMA_DEPTH) >= 15))
95 cgfxcoltab = AllocVec(bmcols * sizeof(ULONG), MEMF_ANY);
97 if (cgfxcoltab)
99 for(y = 0; y < bmcols; y++)
101 ULONG red = data->sourcecolors[y * 3] & 0xFF000000;
102 ULONG green = data->sourcecolors[y * 3 + 1] & 0xFF000000;
103 ULONG blue = data->sourcecolors[y * 3 + 2] & 0xFF000000;
105 cgfxcoltab[y] = (red >> 8) | (green >> 16) | (blue >> 24);
111 InitRastPort(&temprp);
112 temprp.BitMap = AllocBitMap(data->width, 1, 1, 0, NULL);
114 InitRastPort(&bmrp);
116 for(y = 0; y < data->height; y++)
118 /* Read a line from source bitmap */
120 bmrp.BitMap = data->bm;
121 if (temprp.BitMap)
123 ReadPixelLine8(&bmrp, 0, y, data->width, linebuffer, &temprp);
125 else
127 for(x = 0; x < data->width; x++)
129 linebuffer[x] = ReadPixel(&bmrp, x, y);
133 /* Build the mask, totaly slow but works */
134 if (data->mask)
136 UBYTE *mask = data->mask + y * bmwidth / 8;
137 UBYTE xmask = 0x80;
139 for(x = 0; x < data->width; x++)
141 if (linebuffer[x] == data->transparent)
143 *mask &= ~xmask;
146 xmask >>= 1;
147 if (!xmask)
149 xmask = 0x80;
150 mask++;
155 /* Remap the line */
156 if (data->mappingtable)
158 for(x = 0; x < data->width; x++)
160 linebuffer[x] = data->mappingtable[linebuffer[x]];
163 else if (!cgfxcoltab)
165 for(x = 0; x < data->width; x++)
167 UBYTE pixel = linebuffer[x];
168 UBYTE remappixel = data->remaptable[pixel];
170 if (!remappixel)
172 struct TagItem tags[3];
173 tags[0].ti_Tag = OBP_Precision;
174 tags[0].ti_Data = data->precision;
175 tags[1].ti_Tag = OBP_FailIfBad;
176 tags[1].ti_Data = FALSE;
177 tags[2].ti_Tag = 0;
179 data->remaptable[pixel] = remappixel = ObtainBestPenA(_screen(obj)->ViewPort.ColorMap,
180 data->sourcecolors[pixel * 3],
181 data->sourcecolors[pixel * 3 + 1],
182 data->sourcecolors[pixel * 3 + 2],
183 tags) | 0x100;
186 linebuffer[x] = (remappixel & 0xFF);
189 } /* else if (!cgfxcoltab) */
191 /* Write line into destination bitmap */
193 bmrp.BitMap = data->remapped_bm;
195 if (cgfxcoltab)
197 WriteLUTPixelArray(linebuffer,
200 data->width,
201 &bmrp,
202 cgfxcoltab,
205 data->width,
207 CTABFMT_XRGB8);
209 else
211 bmrp.BitMap = data->remapped_bm;
212 if (temprp.BitMap)
214 WritePixelLine8(&bmrp, 0, y, data->width, linebuffer, &temprp);
216 else
218 for(x = 0; x < data->width; x++)
220 SetAPen(&bmrp, linebuffer[x]);
221 WritePixel(&bmrp, x, y);
227 } /* for(y = 0; y < data->height; y++) */
229 DeinitRastPort(&temprp);
230 DeinitRastPort(&bmrp);
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) return FALSE;
253 data = INST_DATA(cl, obj);
255 data->precision = PRECISION_GUI;
256 data->transparent = -1;
258 /* parse initial taglist */
260 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem**)&tags)); )
262 switch (tag->ti_Tag)
264 case MUIA_Bitmap_Bitmap:
265 data->bm = (struct BitMap *)tag->ti_Data;
266 break;
268 case MUIA_Bitmap_Height:
269 data->height = (LONG)tag->ti_Data;
270 break;
272 case MUIA_Bitmap_MappingTable:
273 data->mappingtable = (UBYTE *)tag->ti_Data;
274 break;
276 case MUIA_Bitmap_Precision:
277 data->precision = (LONG)tag->ti_Data;
278 break;
280 case MUIA_Bitmap_SourceColors:
281 data->sourcecolors = (ULONG *)tag->ti_Data;
282 break;
284 case MUIA_Bitmap_Transparent:
285 data->transparent = (LONG)tag->ti_Data;
286 break;
288 case MUIA_Bitmap_UseFriend:
289 data->usefriend = (tag->ti_Data != 0);
290 break;
292 case MUIA_Bitmap_Width:
293 data->width = (LONG)tag->ti_Data;
294 break;
299 return (IPTR)obj;
302 /**************************************************************************
303 OM_DISPOSE
304 **************************************************************************/
305 IPTR Bitmap__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
307 struct MUI_BitmapData *data = INST_DATA(cl, obj);
309 if (data->remapped_bm)
311 WaitBlit();
312 FreeBitMap(data->remapped_bm);
314 if (data->remaptable) FreeVec(data->remaptable);
316 return DoSuperMethodA(cl, obj, msg);
319 /**************************************************************************
320 OM_SET
321 **************************************************************************/
322 IPTR Bitmap__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
324 struct MUI_BitmapData *data = INST_DATA(cl, obj);
325 struct TagItem *tags = msg->ops_AttrList;
326 struct TagItem *tag;
328 while ((tag = NextTagItem((const struct TagItem**)&tags)) != NULL)
330 switch (tag->ti_Tag)
332 case MUIA_Bitmap_Bitmap:
333 if (!data->remapped_bm)
335 data->bm = (struct BitMap *)tag->ti_Data;
337 break;
339 case MUIA_Bitmap_Height:
340 data->height = (LONG)tag->ti_Data;
341 break;
343 case MUIA_Bitmap_MappingTable:
344 data->mappingtable = (UBYTE *)tag->ti_Data;
345 break;
347 case MUIA_Bitmap_Precision:
348 data->precision = (LONG)tag->ti_Data;
349 break;
351 case MUIA_Bitmap_SourceColors:
352 data->sourcecolors = (ULONG *)tag->ti_Data;
353 break;
355 case MUIA_Bitmap_Transparent:
356 data->transparent = (LONG)tag->ti_Data;
357 break;
359 case MUIA_Bitmap_Width:
360 data->width = (LONG)tag->ti_Data;
361 break;
366 return DoSuperMethodA(cl, obj, (Msg)msg);
369 /**************************************************************************
370 OM_GET
371 **************************************************************************/
372 IPTR Bitmap__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
374 #define STORE *(msg->opg_Storage)
376 struct MUI_BitmapData *data = INST_DATA(cl, obj);
378 switch(msg->opg_AttrID)
380 case MUIA_Bitmap_Bitmap:
381 STORE = (IPTR)data->bm;
382 return TRUE;
384 case MUIA_Bitmap_Height:
385 STORE = (IPTR)data->height;
386 return TRUE;
388 case MUIA_Bitmap_MappingTable:
389 STORE = (IPTR)data->mappingtable;
390 return TRUE;
392 case MUIA_Bitmap_Precision:
393 STORE = (IPTR)data->precision;
394 return TRUE;
396 case MUIA_Bitmap_RemappedBitmap:
397 STORE = (IPTR)data->remapped_bm;
398 return TRUE;
400 case MUIA_Bitmap_SourceColors:
401 STORE = (IPTR)data->sourcecolors;
402 return TRUE;
404 case MUIA_Bitmap_Transparent:
405 STORE = (IPTR)data->transparent;
406 return TRUE;
408 case MUIA_Bitmap_Width:
409 STORE = (IPTR)data->width;
410 return TRUE;
413 return DoSuperMethodA(cl, obj, (Msg)msg);
414 #undef STORE
417 /**************************************************************************
418 MUIM_Setup
419 **************************************************************************/
420 IPTR Bitmap__MUIM_Setup(struct IClass *cl, Object *obj, Msg msg)
422 //struct MUI_BitmapData *data = INST_DATA(cl, obj);
424 if (!DoSuperMethodA(cl, obj, (Msg)msg))
425 return FALSE;
427 remap_bitmap(cl, obj);
429 return TRUE;
432 /**************************************************************************
433 MUIM_Cleanup
434 **************************************************************************/
435 IPTR Bitmap__MUIM_Cleanup(struct IClass *cl, Object *obj, Msg msg)
437 struct MUI_BitmapData *data = INST_DATA(cl, obj);
439 if (data->mask)
441 LONG bmwidth = GetBitMapAttr(data->remapped_bm, BMA_WIDTH);
442 LONG bmheight = GetBitMapAttr(data->remapped_bm, BMA_HEIGHT);
443 FreeRaster(data->mask,bmwidth,bmheight);
445 data->mask = NULL;
448 if (data->remapped_bm)
450 WaitBlit();
451 FreeBitMap(data->remapped_bm);
452 data->remapped_bm = NULL;
454 if (data->remaptable)
456 WORD i;
458 for(i = 0; i < 256; i++)
460 if (data->remaptable[i])
462 ReleasePen(_screen(obj)->ViewPort.ColorMap, data->remaptable[i] & 0xFF);
463 data->remaptable[i] = 0;
469 return DoSuperMethodA(cl, obj, (Msg)msg);
472 /**************************************************************************
473 MUIM_AskMinMax
474 **************************************************************************/
475 IPTR Bitmap__MUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
477 DoSuperMethodA(cl, obj, (Msg)msg);
479 msg->MinMaxInfo->MinWidth += 1;
480 msg->MinMaxInfo->MinHeight += 1;
482 msg->MinMaxInfo->DefWidth += 1;
483 msg->MinMaxInfo->DefHeight += 1;
485 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
486 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
488 return TRUE;
491 /**************************************************************************
492 MUIM_Draw
493 **************************************************************************/
494 IPTR Bitmap__MUIM_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
496 struct MUI_BitmapData *data = INST_DATA(cl, obj);
497 struct BitMap *bm;
499 DoSuperMethodA(cl,obj,(Msg)msg);
501 bm = data->remapped_bm ? data->remapped_bm : data->bm;
502 if (bm)
504 LONG width, height;
506 width = data->width;
507 height = data->height;
509 if (width > _mwidth(obj)) width = _mwidth(obj);
510 if (height > _mheight(obj)) height = _mheight(obj);
512 if ((width > 0) && (height > 0))
514 if (data->mask)
516 BltMaskBitMapRastPort(bm, 0, 0, _rp(obj), _mleft(obj), _mtop(obj), width, height, 0xE0, data->mask);
518 else
520 BltBitMapRastPort(bm, 0, 0, _rp(obj), _mleft(obj), _mtop(obj), width, height, 0xC0);
525 return TRUE;
529 BOOPSI_DISPATCHER(IPTR, Bitmap_Dispatcher, cl, obj, msg)
531 switch (msg->MethodID)
533 case OM_NEW: return Bitmap__OM_NEW(cl, obj, (struct opSet *)msg);
534 case OM_DISPOSE: return Bitmap__OM_DISPOSE(cl, obj, msg);
535 case OM_SET: return Bitmap__OM_SET(cl, obj, (struct opSet *)msg);
536 case OM_GET: return Bitmap__OM_GET(cl, obj, (struct opGet *)msg);
537 case MUIM_Setup: return Bitmap__MUIM_Setup(cl, obj, msg);
538 case MUIM_Cleanup: return Bitmap__MUIM_Cleanup(cl, obj, msg);
539 case MUIM_AskMinMax: return Bitmap__MUIM_AskMinMax(cl, obj, (struct MUIP_AskMinMax *)msg);
540 case MUIM_Draw: return Bitmap__MUIM_Draw(cl, obj, (struct MUIP_Draw *)msg);
543 return DoSuperMethodA(cl, obj, msg);
545 BOOPSI_DISPATCHER_END
548 * Class descriptor.
550 const struct __MUIBuiltinClass _MUI_Bitmap_desc = {
551 MUIC_Bitmap,
552 MUIC_Area,
553 sizeof(struct MUI_BitmapData),
554 (void*)Bitmap_Dispatcher