Merging NList MCC 0.119 into the main branch.
[AROS.git] / workbench / classes / zune / nlist / nbitmap_mcc / NBitmap.c
blob55e562f072829a5a5bbe37f6010335f1af755622
1 /***************************************************************************
3 NBitmap.mcc - New Bitmap MUI Custom Class
4 Copyright (C) 2006 by Daniel Allsopp
5 Copyright (C) 2007-2013 by NList Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 NList classes Support Site: http://www.sf.net/projects/nlist-classes
19 $Id$
21 ***************************************************************************/
23 // ansi includes
24 #include <string.h>
26 // system includes
27 #include <proto/exec.h>
28 #include <proto/datatypes.h>
29 #include <proto/graphics.h>
30 #include <proto/muimaster.h>
31 #include <proto/intuition.h>
32 #include <mui/NBitmap_mcc.h>
34 // system
35 #include <datatypes/pictureclass.h>
37 #if defined(__amigaos4__)
38 #include <hardware/blit.h>
39 #else
40 #include <proto/cybergraphics.h>
41 #include <cybergraphx/cybergraphics.h>
42 #endif
44 #if defined(__MORPHOS__)
45 #include <exec/execbase.h>
46 #include <exec/system.h>
47 #endif
49 // libraries
50 #include <libraries/mui.h>
52 // local includes
53 #include "private.h"
54 #include "NBitmap.h"
55 #include "Chunky2Bitmap.h"
56 #include "DitherImage.h"
57 #include "version.h"
58 #include "Debug.h"
60 // constant data
61 /// default color map
62 const uint32 defaultColorMap[256] =
64 0x00000000, 0x00000055, 0x000000aa, 0x000000ff, 0x00002400, 0x00002455, 0x000024aa, 0x000024ff, 0x00004900, 0x00004955, 0x000049aa, 0x000049ff, 0x00006d00, 0x00006d55, 0x00006daa, 0x00006dff,
65 0x00009200, 0x00009255, 0x000092aa, 0x000092ff, 0x0000b600, 0x0000b655, 0x0000b6aa, 0x0000b6ff, 0x0000db00, 0x0000db55, 0x0000dbaa, 0x0000dbff, 0x0000ff00, 0x0000ff55, 0x0000ffaa, 0x0000ffff,
66 0x00240000, 0x00240055, 0x002400aa, 0x002400ff, 0x00242400, 0x00242455, 0x002424aa, 0x002424ff, 0x00244900, 0x00244955, 0x002449aa, 0x002449ff, 0x00246d00, 0x00246d55, 0x00246daa, 0x00246dff,
67 0x00249200, 0x00249255, 0x002492aa, 0x002492ff, 0x0024b600, 0x0024b655, 0x0024b6aa, 0x0024b6ff, 0x0024db00, 0x0024db55, 0x0024dbaa, 0x0024dbff, 0x0024ff00, 0x0024ff55, 0x0024ffaa, 0x0024ffff,
68 0x00490000, 0x00490055, 0x004900aa, 0x004900ff, 0x00492400, 0x00492455, 0x004924aa, 0x004924ff, 0x00494900, 0x00494955, 0x004949aa, 0x004949ff, 0x00496d00, 0x00496d55, 0x00496daa, 0x00496dff,
69 0x00499200, 0x00499255, 0x004992aa, 0x004992ff, 0x0049b600, 0x0049b655, 0x0049b6aa, 0x0049b6ff, 0x0049db00, 0x0049db55, 0x0049dbaa, 0x0049dbff, 0x0049ff00, 0x0049ff55, 0x0049ffaa, 0x0049ffff,
70 0x006d0000, 0x006d0055, 0x006d00aa, 0x006d00ff, 0x006d2400, 0x006d2455, 0x006d24aa, 0x006d24ff, 0x006d4900, 0x006d4955, 0x006d49aa, 0x006d49ff, 0x006d6d00, 0x006d6d55, 0x006d6daa, 0x006d6dff,
71 0x006d9200, 0x006d9255, 0x006d92aa, 0x006d92ff, 0x006db600, 0x006db655, 0x006db6aa, 0x006db6ff, 0x006ddb00, 0x006ddb55, 0x006ddbaa, 0x006ddbff, 0x006dff00, 0x006dff55, 0x006dffaa, 0x006dffff,
72 0x00920000, 0x00920055, 0x009200aa, 0x009200ff, 0x00922400, 0x00922455, 0x009224aa, 0x009224ff, 0x00924900, 0x00924955, 0x009249aa, 0x009249ff, 0x00926d00, 0x00926d55, 0x00926daa, 0x00926dff,
73 0x00929200, 0x00929255, 0x009292aa, 0x009292ff, 0x0092b600, 0x0092b655, 0x0092b6aa, 0x0092b6ff, 0x0092db00, 0x0092db55, 0x0092dbaa, 0x0092dbff, 0x0092ff00, 0x0092ff55, 0x0092ffaa, 0x0092ffff,
74 0x00b60000, 0x00b60055, 0x00b600aa, 0x00b600ff, 0x00b62400, 0x00b62455, 0x00b624aa, 0x00b624ff, 0x00b64900, 0x00b64955, 0x00b649aa, 0x00b649ff, 0x00b66d00, 0x00b66d55, 0x00b66daa, 0x00b66dff,
75 0x00b69200, 0x00b69255, 0x00b692aa, 0x00b692ff, 0x00b6b600, 0x00b6b655, 0x00b6b6aa, 0x00b6b6ff, 0x00b6db00, 0x00b6db55, 0x00b6dbaa, 0x00b6dbff, 0x00b6ff00, 0x00b6ff55, 0x00b6ffaa, 0x00b6ffff,
76 0x00db0000, 0x00db0055, 0x00db00aa, 0x00db00ff, 0x00db2400, 0x00db2455, 0x00db24aa, 0x00db24ff, 0x00db4900, 0x00db4955, 0x00db49aa, 0x00db49ff, 0x00db6d00, 0x00db6d55, 0x00db6daa, 0x00db6dff,
77 0x00db9200, 0x00db9255, 0x00db92aa, 0x00db92ff, 0x00dbb600, 0x00dbb655, 0x00dbb6aa, 0x00dbb6ff, 0x00dbdb00, 0x00dbdb55, 0x00dbdbaa, 0x00dbdbff, 0x00dbff00, 0x00dbff55, 0x00dbffaa, 0x00dbffff,
78 0x00ff0000, 0x00ff0055, 0x00ff00aa, 0x00ff00ff, 0x00ff2400, 0x00ff2455, 0x00ff24aa, 0x00ff24ff, 0x00ff4900, 0x00ff4955, 0x00ff49aa, 0x00ff49ff, 0x00ff6d00, 0x00ff6d55, 0x00ff6daa, 0x00ff6dff,
79 0x00ff9200, 0x00ff9255, 0x00ff92aa, 0x00ff92ff, 0x00ffb600, 0x00ffb655, 0x00ffb6aa, 0x00ffb6ff, 0x00ffdb00, 0x00ffdb55, 0x00ffdbaa, 0x00ffdbff, 0x00ffff00, 0x00ffff55, 0x00ffffaa, 0x00ffffff
82 ///
84 #if defined(__MORPHOS__) || defined(__AROS__)
85 // MorphOS and AROS always have working WPA() and WPAA() functions
86 #define WPA(src, srcx, srcy, srcmod, rp, destx, desty, width, height, fmt) \
87 WritePixelArray(src, srcx, srcy, srcmod, rp, destx, desty, width, height, fmt)
88 #define WPAA(src, srcx, srcy, srcmod, rp, destx, desty, width, height, globalalpha) \
89 WritePixelArrayAlpha(src, srcx, srcy, srcmod, rp, destx, desty, width, height, globalalpha)
90 #elif !defined(__amigaos4__)
91 // for AmigaOS3 this is only true for CGX V43+
92 #define WPA(src, srcx, srcy, srcmod, rp, destx, desty, width, height, fmt) \
93 { \
94 if(CyberGfxBase != NULL) \
95 WritePixelArray(src, srcx, srcy, srcmod, rp, destx, desty, width, height, fmt); \
96 else \
97 _WPA(src, srcx, srcy, srcmod, rp, destx, desty, width, height, fmt); \
99 #define WPAA(src, srcx, srcy, srcmod, rp, destx, desty, width, height, globalalpha) \
101 if(CyberGfxBase != NULL && CyberGfxBase->lib_Version >= 43) \
102 WritePixelArrayAlpha(src, srcx, srcy, srcmod, rp, destx, desty, width, height, globalalpha); \
103 else \
104 _WPAA(src, srcx, srcy, srcmod, rp, destx, desty, width, height, globalalpha); \
106 #endif
108 // functions
109 /// GetConfigItem()
111 ULONG GetConfigItem(Object *obj, ULONG configitem, ULONG defaultsetting)
113 IPTR value;
114 ULONG result = defaultsetting;
116 ENTER();
118 if(DoMethod(obj, MUIM_GetConfigItem, configitem, &value))
119 result = *(ULONG *)value;
121 /* XXX: On 64-bit AROS I'm getting for the line above the warning "cast to pointer from integer of different size". */
123 RETURN(result);
124 return result;
128 /// InitConfig()
130 static void InitConfig(Object *obj, struct InstData *data)
132 ENTER();
134 if(obj != NULL && data != NULL)
136 data->prefs.show_label = 0;
137 data->prefs.overlay_type = 0;
138 data->prefs.overlay_r = 10;
139 data->prefs.overlay_g = 36;
140 data->prefs.overlay_b = 106;
141 data->prefs.overlay_shadeover = 1500; // = 1.5 if divided by 1000
142 data->prefs.overlay_shadepress = 2500; // = 2.5 if divided by 1000
143 data->prefs.spacing_horiz = 2;
144 data->prefs.spacing_vert = 2;
147 LEAVE();
151 /// FreeConfig()
153 static void FreeConfig(struct InstData *data)
155 ENTER();
157 if(data != NULL)
159 // nothing yet
162 LEAVE();
166 /// NBitmap_LoadImage()
168 BOOL NBitmap_LoadImage(STRPTR filename, uint32 item, struct IClass *cl, Object *obj)
170 BOOL result = FALSE;
171 struct InstData *data;
173 ENTER();
175 SHOWSTRING(DBF_DATATYPE, filename);
177 if((data = INST_DATA(cl, obj)) != NULL && filename != NULL)
179 data->dt_obj[item] = NewDTObject(filename,
180 DTA_GroupID, GID_PICTURE,
181 OBP_Precision, PRECISION_EXACT,
182 PDTA_FreeSourceBitMap, TRUE,
183 PDTA_DestMode, PMODE_V43,
184 PDTA_UseFriendBitMap, TRUE,
185 TAG_DONE);
186 SHOWVALUE(DBF_DATATYPE, data->dt_obj[item]);
187 if(data->dt_obj[item] != NULL)
188 result = TRUE;
191 RETURN(result);
192 return result;
196 /// NBitmap_ExamineData()
198 static BOOL NBitmap_ExamineData(Object *dt_obj, uint32 item, struct IClass *cl, Object *obj)
200 BOOL result = FALSE;
201 ULONG arraysize;
203 struct pdtBlitPixelArray pbpa;
204 struct InstData *data = INST_DATA(cl, obj);
206 if(dt_obj != NULL)
208 /* bitmap header */
209 GetDTAttrs(dt_obj, PDTA_BitMapHeader, &data->dt_header[item], TAG_DONE);
210 D(DBF_DATATYPE, "examine: BMHD dimensions %ldx%ldx%ld", data->dt_header[item]->bmh_Width, data->dt_header[item]->bmh_Height, data->dt_header[item]->bmh_Depth);
211 data->depth = data->dt_header[item]->bmh_Depth;
213 if(data->depth>0 && data->depth<=8)
215 /* colour lookup bitmap */
216 data->fmt = PBPAFMT_LUT8;
218 /* bitmap header */
219 data->width = data->dt_header[0]->bmh_Width;
220 data->height = data->dt_header[0]->bmh_Height;
222 result = TRUE;
223 D(DBF_DATATYPE, "examine: using LUT8 bitmaps");
225 else if(data->depth >=24)
227 #if defined(__MORPHOS__)
228 /* XXX: Check out is this needed in OS 3 and AROS */
229 IPTR use_alpha;
231 GetDTAttrs(dt_obj, PDTA_AlphaChannel, (IPTR)&use_alpha, TAG_DONE);
233 if (use_alpha)
234 data->depth = 32;
235 #endif
237 /* true colour bitmap */
238 if(data->depth == 24)
240 data->fmt = PBPAFMT_RGB;
241 D(DBF_DATATYPE, "examine: using 24bit RGB data");
243 else if(data->depth == 32)
245 data->fmt = PBPAFMT_ARGB;
246 D(DBF_DATATYPE, "examine: using 32bit ARGB data");
249 data->width = data->dt_header[0]->bmh_Width;
250 data->height = data->dt_header[0]->bmh_Height;
251 data->arraybpp = data->depth/8;
252 data->arraybpr = data->arraybpp * data->width;
254 #if defined(__MORPHOS__)
255 if (SysBase->LibNode.lib_Version >= 51)
257 ULONG altivec_align = 0;
259 NewGetSystemAttrs(&altivec_align, sizeof(altivec_align), SYSTEMINFOTYPE_PPC_ALTIVEC, TAG_DONE);
261 if (altivec_align)
262 data->arraybpr = (data->arraybpr + 15) & ~15;
264 #endif
266 arraysize = (data->arraybpr) * data->height;
268 /* get array of pixels */
269 if((data->arraypixels[item] = AllocVecShared(arraysize, MEMF_ANY|MEMF_CLEAR)) != NULL)
271 ULONG error;
273 memset(&pbpa, 0, sizeof(struct pdtBlitPixelArray));
275 pbpa.MethodID = PDTM_READPIXELARRAY;
276 pbpa.pbpa_PixelData = data->arraypixels[item];
277 pbpa.pbpa_PixelFormat = data->fmt;
278 pbpa.pbpa_PixelArrayMod = data->arraybpr;
279 pbpa.pbpa_Left = 0;
280 pbpa.pbpa_Top = 0;
281 pbpa.pbpa_Width = data->width;
282 pbpa.pbpa_Height = data->height;
284 error = DoMethodA(dt_obj, (Msg)(VOID*)&pbpa);
285 (void)error;
286 D(DBF_DATATYPE, "examine: READPIXELARRAY returned %ld", error);
288 result = TRUE;
293 return(result);
297 /// NBitmap_UpdateImage()
299 VOID NBitmap_UpdateImage(uint32 item, STRPTR filename, struct IClass *cl, Object *obj)
301 struct InstData *data = NULL;
303 if((data = INST_DATA(cl, obj)) != NULL)
305 if(filename != NULL)
307 if(data->dt_obj[item] != NULL)
309 /* free old image data */
310 if(data->fmt == PBPAFMT_LUT8)
311 SetDTAttrs(data->dt_obj[item], NULL, NULL, PDTA_Screen, NULL, TAG_DONE);
313 DisposeDTObject(data->dt_obj[item]);
314 data->dt_obj[item] = NULL;
316 if(data->arraypixels[item] != NULL)
318 FreeVec(data->arraypixels[item]);
319 data->arraypixels[item] = NULL;
322 /* load new image */
323 if((NBitmap_LoadImage(filename, item, cl, obj)) != FALSE)
325 /* setup new image */
326 if((NBitmap_ExamineData(data->dt_obj[item], item, cl, obj)) != FALSE)
328 if(data->fmt == PBPAFMT_LUT8)
330 /* layout image */
331 SetDTAttrs(data->dt_obj[item], NULL, NULL, PDTA_Screen, _screen(obj), TAG_DONE);
332 if(DoMethod(data->dt_obj[item], DTM_PROCLAYOUT, NULL, 1))
334 GetDTAttrs(data->dt_obj[item], PDTA_CRegs, &data->dt_colours[item], TAG_DONE);
335 GetDTAttrs(data->dt_obj[item], PDTA_MaskPlane, &data->dt_mask[item], TAG_DONE);
336 GetDTAttrs(data->dt_obj[item], PDTA_DestBitMap, &data->dt_bitmap[item], TAG_DONE);
338 if(data->dt_bitmap[item] == NULL) GetDTAttrs(data->dt_obj[item], PDTA_BitMap, &data->dt_bitmap[item], TAG_DONE);
350 /// NBitmap_SetupShades()
351 // create an ARGB shade
352 BOOL NBitmap_SetupShades(struct InstData *data)
354 uint32 pixel, altivec_align;
356 ENTER();
358 altivec_align = 0;
360 #if defined(__MORPHOS__)
361 if (SysBase->LibNode.lib_Version >= 51)
363 NewGetSystemAttrs(&altivec_align, sizeof(altivec_align), SYSTEMINFOTYPE_PPC_ALTIVEC, TAG_DONE);
365 #endif
367 data->shadeWidth = data->width + data->border_horiz - 2;
368 data->shadeHeight = data->height + data->border_vert - 2;
369 data->shadeBytesPerRow = data->shadeWidth * 4;
371 if (altivec_align)
372 data->shadeBytesPerRow = (data->shadeBytesPerRow + 15) & ~15;
374 // the shades pixel color
375 pixel = ((ULONG)data->prefs.overlay_r << 16) | ((ULONG)data->prefs.overlay_g << 8) | (ULONG)data->prefs.overlay_b;
377 if((data->pressedShadePixels = AllocVecAligned(data->shadeBytesPerRow * data->shadeHeight, MEMF_ANY, altivec_align ? 16 : 8, 0)) != NULL)
379 uint32 w, h;
380 uint32 alpha;
381 uint32 *p = data->pressedShadePixels;
383 // calculate the alpha channel value
384 alpha = (255L - (((255L * 1000L) / (uint32)data->prefs.overlay_shadepress) & 0xff)) << 24;
386 // fill the array with the pixel and alpha channel value
387 // the border will be the 100% opaque pixel color
388 for(h = 0; h < data->shadeHeight; h++)
390 for(w = 0; w < data->shadeWidth; w++)
392 if(h == 0 || h == data->shadeHeight-1 || w == 0 || w == data->shadeWidth-1)
393 *p++ = 0xff000000 | pixel;
394 else
395 *p++ = alpha | pixel;
398 p += (data->shadeBytesPerRow - data->shadeWidth * 4) / 4;
402 if((data->overShadePixels = AllocVecAligned(data->shadeBytesPerRow * data->shadeHeight, MEMF_ANY, altivec_align ? 16 : 8, 0)) != NULL)
404 uint32 w, h;
405 uint32 alpha;
406 uint32 *p = data->overShadePixels;
408 // calculate the alpha channel value
409 alpha = (255L - (((255L * 1000L) / (uint32)data->prefs.overlay_shadeover) & 0xff)) << 24;
411 // fill the array with the pixel and alpha channel value
412 // the border will be the 100% opaque pixel color
413 for(h = 0; h < data->shadeHeight; h++)
415 for(w = 0; w < data->shadeWidth; w++)
417 if(h == 0 || h == data->shadeHeight-1 || w == 0 || w == data->shadeWidth-1)
418 *p++ = 0xff000000 | pixel;
419 else
420 *p++ = alpha | pixel;
423 p += (data->shadeBytesPerRow - data->shadeWidth * 4) / 4;
427 RETURN((data->pressedShadePixels != NULL && data->overShadePixels != NULL));
428 return (data->pressedShadePixels != NULL && data->overShadePixels != NULL);
432 /// CleanupShades()
433 // delete the ARGB shades
434 void NBitmap_CleanupShades(struct InstData *data)
436 ENTER();
438 if(data->pressedShadePixels != NULL)
440 FreeVec(data->pressedShadePixels);
441 data->pressedShadePixels = NULL;
443 if(data->overShadePixels != NULL)
445 FreeVec(data->overShadePixels);
446 data->overShadePixels = NULL;
449 LEAVE();
453 /// NBitmap_NewImage()
455 BOOL NBitmap_NewImage(struct IClass *cl, Object *obj)
457 BOOL result = FALSE;
458 struct InstData *data;
460 ENTER();
462 if((data = INST_DATA(cl, obj)) != NULL)
464 switch(data->type)
466 case MUIV_NBitmap_Type_File:
467 case MUIV_NBitmap_Type_DTObject:
469 if(data->dt_obj[0] != NULL)
471 ULONG i;
473 // assume success for the moment
474 result = TRUE;
476 for(i=0;i<3;i++)
478 if(data->dt_obj[i] != NULL)
479 result &= NBitmap_ExamineData(data->dt_obj[i], i, cl, obj);
483 break;
485 case MUIV_NBitmap_Type_CLUT8:
486 case MUIV_NBitmap_Type_RGB24:
487 case MUIV_NBitmap_Type_ARGB32:
489 // no further requirements, instant success
490 result = TRUE;
492 break;
496 RETURN(result);
497 return result;
500 BOOL NBitmap_OldNewImage(struct IClass *cl, Object *obj)
502 BOOL result = FALSE;
503 struct InstData *data;
505 /* need at least the normal image */
506 if((data = INST_DATA(cl, obj)) !=NULL && data->dt_obj[0] != NULL)
508 ULONG i;
510 for(i = 0; i < 3; i++)
512 if(data->dt_obj[i] != NULL)
514 struct FrameInfo fri;
516 memset(&fri, 0, sizeof(struct FrameInfo));
517 DoMethod(data->dt_obj[0], DTM_FRAMEBOX, NULL, &fri, &fri, sizeof(struct FrameInfo), 0);
518 data->depth = fri.fri_Dimensions.Depth;
519 D(DBF_DATATYPE, "new: framebox dimensions %ldx%ldx%ld", fri.fri_Dimensions.Width, fri.fri_Dimensions.Height, fri.fri_Dimensions.Depth);
521 if(data->maxwidth == 0 || (data->maxwidth <= data->dt_header[i]->bmh_Width))
523 if(data->maxheight == 0 || (data->maxheight <= data->dt_header[i]->bmh_Height))
525 if(data->depth > 0 && data->depth <= 8)
527 /* colour lookup bitmap */
528 data->fmt = PBPAFMT_LUT8;
530 /* bitmap header */
531 GetDTAttrs(data->dt_obj[i], PDTA_BitMapHeader, &data->dt_header[i], TAG_DONE);
532 data->width = data->dt_header[0]->bmh_Width;
533 data->height = data->dt_header[0]->bmh_Height;
534 D(DBF_DATATYPE, "new: using LUT8 bitmaps");
536 result = TRUE;
538 else if(data->depth > 8)
540 ULONG arraysize;
542 /* correct read buffer */
543 if(data->depth == 24)
545 data->fmt = PBPAFMT_RGB;
546 D(DBF_DATATYPE, "new: using 24bit RGB data");
548 else
550 data->fmt = PBPAFMT_ARGB;
551 D(DBF_DATATYPE, "new: using 32bit ARGB data");
554 /* bitmap header */
555 GetDTAttrs(data->dt_obj[i], PDTA_BitMapHeader, &data->dt_header[i], TAG_DONE);
556 data->width = data->dt_header[0]->bmh_Width;
557 data->height = data->dt_header[0]->bmh_Height;
558 data->arraybpp = data->depth / 8;
559 data->arraybpr = data->arraybpp * data->width;
560 arraysize = (data->arraybpr) * data->height;
562 /* get array of pixels */
563 if((data->arraypixels[i] = AllocVecShared(arraysize, MEMF_ANY|MEMF_CLEAR)) != NULL)
565 ULONG error;
567 error = DoMethod(data->dt_obj[i], PDTM_READPIXELARRAY, data->arraypixels[i], data->fmt, data->arraybpr, 0, 0, data->width, data->height);
568 (void)error;
569 D(DBF_DATATYPE, "new: READPIXELARRAY returned %ld", error);
571 // finally create the shades
572 result = NBitmap_SetupShades(data);
581 RETURN(result);
582 return result;
586 /// NBitmap_DisposeImage()
588 VOID NBitmap_DisposeImage(struct IClass *cl, Object *obj)
590 struct InstData *data;
592 ENTER();
594 if((data = INST_DATA(cl, obj)) != NULL)
596 ULONG i;
598 /* free datatype object */
599 if(data->type == MUIV_NBitmap_Type_File)
601 for(i =0 ; i < 3; i++)
603 SHOWVALUE(DBF_DATATYPE, data->dt_obj[i]);
604 if(data->dt_obj[i] != NULL)
606 DisposeDTObject(data->dt_obj[i]);
607 data->dt_obj[i] = NULL;
612 if(data->label != NULL)
614 FreeVec(data->label);
615 data->label = NULL;
618 /* free pixel memory */
619 for(i = 0; i < 3; i++)
621 if(data->arraypixels[i] != NULL)
623 FreeVec(data->arraypixels[i]);
624 data->arraypixels[i] = NULL;
628 NBitmap_CleanupShades(data);
631 LEAVE();
635 /// NBitmap_SetupImage()
637 BOOL NBitmap_SetupImage(struct IClass *cl, Object *obj)
639 struct InstData *data;
640 BOOL result = FALSE;
642 ENTER();
644 if((data = INST_DATA(cl, obj)) != NULL)
646 /* stored config */
647 InitConfig(obj, data);
649 data->scrdepth = GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH);
651 /* input */
652 if(data->button)
654 data->ehnode.ehn_Priority = 0;
655 data->ehnode.ehn_Flags = MUI_EHF_GUIMODE;
656 data->ehnode.ehn_Object = obj;
657 data->ehnode.ehn_Class = cl;
658 data->ehnode.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE;
660 DoMethod(_win(obj), MUIM_Window_AddEventHandler, &data->ehnode);
663 switch(data->type)
665 case MUIV_NBitmap_Type_File:
666 case MUIV_NBitmap_Type_DTObject:
669 /* 8-bit data */
670 if(data->fmt == PBPAFMT_LUT8 && data->dt_obj[0] != NULL)
672 ULONG i;
674 /* layout image */
675 for(i = 0; i < 3; i++)
677 // set the new screen for this object
678 SetDTAttrs(data->dt_obj[i], NULL, NULL, PDTA_Screen, _screen(obj), TAG_DONE);
679 if(DoMethod(data->dt_obj[i], DTM_PROCLAYOUT, NULL, 1))
681 GetDTAttrs(data->dt_obj[i], PDTA_CRegs, &data->dt_colours[i],
682 PDTA_MaskPlane, &data->dt_mask[i],
683 PDTA_DestBitMap, &data->dt_bitmap[i],
684 TAG_DONE);
685 if(data->dt_bitmap[i] == NULL)
686 GetDTAttrs(data->dt_obj[i], PDTA_BitMap, &data->dt_bitmap[i], TAG_DONE);
687 SHOWVALUE(DBF_DATATYPE, data->dt_bitmap[i]);
691 result = TRUE;
693 else if(data->depth > 8)
694 result = NBitmap_SetupShades(data);
696 break;
698 case MUIV_NBitmap_Type_CLUT8:
699 case MUIV_NBitmap_Type_RGB24:
700 case MUIV_NBitmap_Type_ARGB32:
702 SHOWVALUE(DBF_ALWAYS, data->scrdepth);
703 // in case we are to be displayed on a colormapped screen we have to create
704 // dithered copies of the images
705 #if defined(__amigaos4__)
706 if(data->scrdepth <= 8)
707 #else
708 SHOWVALUE(DBF_ALWAYS, CyberGfxBase);
709 if(CyberGfxBase != NULL)
710 SHOWVALUE(DBF_ALWAYS, CyberGfxBase->lib_Version);
711 if(data->scrdepth <= 8 || CyberGfxBase == NULL)
712 #endif
714 ULONG i;
715 const uint32 *colorMap;
717 // use a user definable colormap or the default color map
718 if(data->clut != NULL)
720 D(DBF_ALWAYS, "using user defined color map");
721 colorMap = data->clut;
723 else
725 D(DBF_ALWAYS, "using default color map");
726 colorMap = defaultColorMap;
729 D(DBF_ALWAYS, "obtaining pens");
730 // allocate all pens
731 for(i = 0; i < 256; i++)
733 data->ditherPenMap[i] = ObtainBestPen(_screen(obj)->ViewPort.ColorMap, ((colorMap[i] >> 16) & 0x000000ffUL) << 24,
734 ((colorMap[i] >> 8) & 0x000000ffUL) << 24,
735 ((colorMap[i] >> 0) & 0x000000ffUL) << 24,
736 OBP_Precision, PRECISION_IMAGE,
737 TAG_DONE);
738 if(data->ditherPenMap[i] == -1)
739 E(DBF_ALWAYS, "failed to obtain pen %ld RGB=%06lx", i, colorMap[i]);
742 for(i = 0; i < 3; i++)
744 if(data->data[i] != NULL)
746 D(DBF_ALWAYS, "dithering image %ld", i);
747 // create a dithered copy of the raw image
748 data->ditheredImage[i] = DitherImage((CONST_APTR)data->data[i], DITHERA_Width, data->width,
749 DITHERA_Height, data->height,
750 DITHERA_Format, data->type,
751 DITHERA_ColorMap, (IPTR)colorMap,
752 DITHERA_PenMap, (IPTR)data->ditherPenMap,
753 DITHERA_MaskPlane, (IPTR)&data->ditheredMask[i],
754 TAG_DONE);
756 #if !defined(__amigaos4__)
757 // CyberGraphics cannot blit raw data through a mask, thus we have to
758 // use this ugly workaround and take the detour using a bitmap.
759 D(DBF_ALWAYS, "setting up dithered bitmap %ld", i);
760 data->ditheredBitmap[i] = Chunky2Bitmap(data->ditheredImage[i], data->width, data->height, data->scrdepth);
761 #endif // !__amigaos4__
765 // no further requirements, instant success
766 result = TRUE;
768 break;
772 RETURN(result);
773 return result;
777 /// NBitmap_CleanupImage()
779 VOID NBitmap_CleanupImage(struct IClass *cl, Object *obj)
781 struct InstData *data;
783 ENTER();
785 if((data = INST_DATA(cl, obj)) != NULL)
787 // input
788 if(data->button)
789 DoMethod(_win(obj), MUIM_Window_RemEventHandler, &data->ehnode);
791 switch(data->type)
793 case MUIV_NBitmap_Type_File:
794 case MUIV_NBitmap_Type_DTObject:
796 if(data->fmt == PBPAFMT_LUT8 && data->dt_obj[0] != NULL)
798 ULONG i;
800 /* layout image */
801 for(i = 0; i < 3; i++)
803 // reset the screen pointer
804 SetDTAttrs(data->dt_obj[i], NULL, NULL, PDTA_Screen, NULL, TAG_DONE);
808 break;
810 case MUIV_NBitmap_Type_CLUT8:
811 case MUIV_NBitmap_Type_RGB24:
812 case MUIV_NBitmap_Type_ARGB32:
814 // nothing to do
815 ULONG i;
816 struct Screen *scr = _screen(obj);
818 // free the possibly dithered image copies
819 for(i = 0; i < 3; i++)
821 #if !defined(__amigaos4__)
822 if(data->ditheredBitmap[i] != NULL)
824 D(DBF_ALWAYS, "freeing dithered bitmap %ld", i);
825 FreeBitMap(data->ditheredBitmap[i]);
826 data->ditheredBitmap[i] = NULL;
828 #endif // !__amigaos4__
829 if(data->ditheredImage[i] != NULL)
831 D(DBF_ALWAYS, "freeing dithered image %ld", i);
832 FreeDitheredImage(data->ditheredImage[i], data->ditheredMask[i]);
833 data->ditheredImage[i] = NULL;
837 // release all allocated pens
838 if(data->scrdepth <= 8)
840 D(DBF_ALWAYS, "releasing pens");
841 for(i = 0; i < 256; i++)
843 if(data->ditherPenMap[i] != -1)
844 ReleasePen(scr->ViewPort.ColorMap, data->ditherPenMap[i]);
848 break;
851 NBitmap_CleanupShades(data);
853 // stored config
854 FreeConfig(data);
857 LEAVE();
861 /// NBitmap_DrawSimpleFrame()
863 static void NBitmap_DrawSimpleFrame(Object *obj, uint32 x, uint32 y, uint32 w, uint32 h)
865 ENTER();
867 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
868 Move(_rp(obj), x, y+(h+1));
869 Draw(_rp(obj), x, y);
870 Draw(_rp(obj), x+(w+1), y);
872 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
873 Draw(_rp(obj), x+(w+1), y+(h+1));
874 Draw(_rp(obj), x, y+(h+1));
876 LEAVE();
880 /// NBitmap_DrawImage()
882 void NBitmap_DrawImage(struct IClass *cl, Object *obj)
884 struct InstData *data;
886 ENTER();
888 if((data = INST_DATA(cl, obj)) != NULL)
890 LONG item;
891 ULONG x, y, twidth;
893 /* coordinates */
894 item = 0;
895 x = _left(obj);
896 y = _top(obj);
897 twidth = (data->width + data->border_horiz) - 2; /* subtract standard 1 pixel border */
899 // clear the background first, otherwise a multiply applied alpha channel
900 // will become darker and darker every time
901 if(data->button != FALSE)
902 DoMethod(obj, MUIM_DrawBackground, _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj), _left(obj), _top(obj), 0);
904 /* label */
905 if(data->label != NULL && data->button != FALSE)
907 uint32 labelx;
909 SetFont(_rp(obj), _font(obj));
910 SetAPen(_rp(obj), 1);
912 labelx = (twidth/2) - (data->labelte.te_Width/2);
914 Move(_rp(obj), x + labelx, _bottom(obj) - 3);
915 Text(_rp(obj), data->label, strlen(data->label));
918 /* draw image */
919 switch(data->type)
921 case MUIV_NBitmap_Type_File:
922 case MUIV_NBitmap_Type_DTObject:
924 if(data->dt_obj[0] != NULL)
926 if(data->fmt == PBPAFMT_LUT8)
928 #if defined(__amigaos4__)
929 uint32 error;
930 #endif
932 /* select bitmap */
933 if(data->button && data->pressed && data->overlay && data->dt_bitmap[2])
934 item = 2;
936 SHOWVALUE(DBF_DRAW, item);
937 SHOWVALUE(DBF_DRAW, data->dt_bitmap[item]);
938 SHOWVALUE(DBF_DRAW, data->dt_mask[item]);
940 #if defined(__amigaos4__)
941 error = BltBitMapTags(BLITA_Source, data->dt_bitmap[item],
942 BLITA_Dest, _rp(obj),
943 BLITA_SrcX, 0,
944 BLITA_SrcY, 0,
945 BLITA_DestX, x + (data->border_horiz / 2),
946 BLITA_DestY, y + ((data->border_vert / 2) - (data->label_vert/2)),
947 BLITA_Width, data->width,
948 BLITA_Height, data->height,
949 BLITA_SrcType, BLITT_BITMAP,
950 BLITA_DestType, BLITT_RASTPORT,
951 BLITA_MaskPlane, data->dt_mask[item],
952 TAG_DONE);
953 SHOWVALUE(DBF_DRAW, error);
955 #else
957 if(data->dt_mask[item] != NULL)
959 BltMaskBitMapRastPort(data->dt_bitmap[item], 0, 0, _rp(obj),
960 _left(obj) + (data->border_horiz / 2),
961 _top(obj) + (data->border_vert / 2),
962 data->width,
963 data->height,
964 0xc0,
965 (APTR)data->dt_mask[item]);
967 else
969 BltBitMapRastPort(data->dt_bitmap[item], 0, 0, _rp(obj),
970 _left(obj) + (data->border_horiz / 2),
971 _top(obj) + (data->border_vert / 2),
972 data->width,
973 data->height,
974 0xc0);
976 #endif
978 else
980 /* select bitmap */
981 if(data->button && data->pressed && data->overlay && data->arraypixels[2] != NULL)
982 item = 2;
984 SHOWVALUE(DBF_DRAW, item);
985 SHOWVALUE(DBF_DRAW, data->arraypixels[item]);
987 if(data->arraypixels[item] != NULL)
989 #if defined(__amigaos4__)
990 int32 srctype;
991 uint32 error;
993 if(data->depth == 24)
994 srctype = BLITT_RGB24;
995 else
996 srctype = BLITT_ARGB32;
998 error = BltBitMapTags(BLITA_Source, data->arraypixels[item],
999 BLITA_Dest, _rp(obj),
1000 BLITA_SrcX, 0,
1001 BLITA_SrcY, 0,
1002 BLITA_DestX, x + (data->border_horiz / 2),
1003 BLITA_DestY, y + ((data->border_vert / 2) - (data->label_vert/2)),
1004 BLITA_Width, data->width,
1005 BLITA_Height, data->height,
1006 BLITA_SrcType, srctype,
1007 BLITA_DestType, BLITT_RASTPORT,
1008 BLITA_SrcBytesPerRow, data->arraybpr,
1009 BLITA_UseSrcAlpha, TRUE,
1010 TAG_DONE);
1012 SHOWVALUE(DBF_DRAW, error);
1014 #else
1016 if(data->depth == 24)
1018 WPA(data->arraypixels[item], 0, 0, data->arraybpr, _rp(obj), _left(obj) + (data->border_horiz / 2), _top(obj) + (data->border_vert / 2), data->width, data->height, RECTFMT_RGB);
1020 else
1022 WPAA(data->arraypixels[item], 0, 0, data->arraybpr, _rp(obj), _left(obj) + (data->border_horiz / 2), _top(obj) + (data->border_vert / 2), data->width, data->height, 0xffffffff);
1025 #endif
1030 break;
1032 case MUIV_NBitmap_Type_CLUT8:
1033 case MUIV_NBitmap_Type_RGB24:
1034 case MUIV_NBitmap_Type_ARGB32:
1036 int w = min((uint32)_mwidth (obj), data->width );
1037 int h = min((uint32)_mheight(obj), data->height);
1039 /* select bitmap */
1040 if(data->button && data->pressed && data->overlay && data->data[2] != NULL)
1041 item = 2;
1043 SHOWVALUE(DBF_ALWAYS, data->scrdepth);
1044 SHOWVALUE(DBF_ALWAYS, data->ditheredImage[item]);
1045 SHOWVALUE(DBF_ALWAYS, data->ditheredMask[item]);
1046 #if !defined(__amigaos4__)
1047 SHOWVALUE(DBF_ALWAYS, data->ditheredBitmap[item]);
1048 #endif
1050 if(data->data[item] != NULL)
1052 #if defined(__amigaos4__)
1053 if(data->scrdepth <= 8 && data->ditheredImage[item] != NULL)
1055 if(data->ditheredMask[item] != NULL)
1057 D(DBF_ALWAYS, "drawing remapped/dithered image with mask");
1058 BltBitMapTags(BLITA_Source, data->ditheredImage[item],
1059 BLITA_Dest, _rp(obj),
1060 BLITA_SrcX, 0,
1061 BLITA_SrcY, 0,
1062 BLITA_DestX, x + (data->border_horiz / 2),
1063 BLITA_DestY, y + ((data->border_vert / 2) - (data->label_vert/2)),
1064 BLITA_Width, w,
1065 BLITA_Height, h,
1066 BLITA_SrcType, BLITT_CHUNKY,
1067 BLITA_DestType, BLITT_RASTPORT,
1068 BLITA_SrcBytesPerRow, data->width,
1069 BLITA_MaskPlane, data->ditheredMask[item],
1070 BLITA_Minterm, (ABC|ABNC|ANBC),
1071 TAG_DONE);
1073 else
1075 D(DBF_ALWAYS, "drawing remapped/dithered image without mask");
1076 BltBitMapTags(BLITA_Source, data->ditheredImage[item],
1077 BLITA_Dest, _rp(obj),
1078 BLITA_SrcX, 0,
1079 BLITA_SrcY, 0,
1080 BLITA_DestX, x + (data->border_horiz / 2),
1081 BLITA_DestY, y + ((data->border_vert / 2) - (data->label_vert/2)),
1082 BLITA_Width, w,
1083 BLITA_Height, h,
1084 BLITA_SrcType, BLITT_CHUNKY,
1085 BLITA_DestType, BLITT_RASTPORT,
1086 BLITA_SrcBytesPerRow, data->width,
1087 BLITA_Minterm, (ABC|ABNC),
1088 TAG_DONE);
1091 #else // __amigaos4__
1092 if((data->scrdepth <= 8 || CyberGfxBase == NULL) && data->ditheredBitmap[item] != NULL)
1094 // CyberGraphics cannot blit raw data through a mask, thus we have to
1095 // take this ugly workaround and take the detour using a bitmap.
1096 if(data->ditheredMask[item] != NULL)
1098 D(DBF_ALWAYS, "drawing remapped/dithered image with mask");
1099 BltMaskBitMapRastPort(data->ditheredBitmap[item], 0, 0, _rp(obj), x + (data->border_horiz / 2), y + ((data->border_vert / 2) - (data->label_vert/2)), w, h, (ABC|ABNC|ANBC), data->ditheredMask[item]);
1101 else
1103 D(DBF_ALWAYS, "drawing remapped/dithered image without mask");
1104 BltBitMapRastPort(data->ditheredBitmap[item], 0, 0, _rp(obj), x + (data->border_horiz / 2), y + ((data->border_vert / 2) - (data->label_vert/2)), w, h, (ABC|ABNC));
1107 #endif // __amigaos4__
1108 else
1110 #if defined(__amigaos4__)
1111 switch(data->type)
1113 case MUIV_NBitmap_Type_CLUT8:
1114 BltBitMapTags(BLITA_Source, data->data[item],
1115 BLITA_Dest, _rp(obj),
1116 BLITA_SrcX, 0,
1117 BLITA_SrcY, 0,
1118 BLITA_DestX, x + (data->border_horiz / 2),
1119 BLITA_DestY, y + ((data->border_vert / 2) - (data->label_vert/2)),
1120 BLITA_Width, w,
1121 BLITA_Height, h,
1122 BLITA_SrcType, BLITT_CHUNKY,
1123 BLITA_DestType, BLITT_RASTPORT,
1124 BLITA_SrcBytesPerRow, data->width,
1125 BLITA_CLUT, data->clut,
1126 TAG_DONE);
1127 break;
1129 case MUIV_NBitmap_Type_RGB24:
1130 D(DBF_ALWAYS, "drawing RGB image");
1131 BltBitMapTags(BLITA_Source, data->data[item],
1132 BLITA_Dest, _rp(obj),
1133 BLITA_SrcX, 0,
1134 BLITA_SrcY, 0,
1135 BLITA_DestX, x + (data->border_horiz / 2),
1136 BLITA_DestY, y + ((data->border_vert / 2) - (data->label_vert/2)),
1137 BLITA_Width, w,
1138 BLITA_Height, h,
1139 BLITA_SrcType, BLITT_RGB24,
1140 BLITA_DestType, BLITT_RASTPORT,
1141 BLITA_SrcBytesPerRow, data->width*3,
1142 BLITA_Alpha, data->alpha,
1143 TAG_DONE);
1144 break;
1146 case MUIV_NBitmap_Type_ARGB32:
1147 D(DBF_ALWAYS, "drawing ARGB image");
1148 BltBitMapTags(BLITA_Source, data->data[item],
1149 BLITA_Dest, _rp(obj),
1150 BLITA_SrcX, 0,
1151 BLITA_SrcY, 0,
1152 BLITA_DestX, x + (data->border_horiz / 2),
1153 BLITA_DestY, y + ((data->border_vert / 2) - (data->label_vert/2)),
1154 BLITA_Width, w,
1155 BLITA_Height, h,
1156 BLITA_SrcType, BLITT_ARGB32,
1157 BLITA_DestType, BLITT_RASTPORT,
1158 BLITA_SrcBytesPerRow, data->width*4,
1159 BLITA_UseSrcAlpha, TRUE,
1160 BLITA_Alpha, data->alpha,
1161 TAG_DONE);
1162 break;
1164 #else // __amigaos4__
1165 switch(data->type)
1167 case MUIV_NBitmap_Type_CLUT8:
1168 WriteLUTPixelArray(data->data[item], 0, 0, data->width, _rp(obj), (APTR)data->clut, x + (data->border_horiz / 2), y + ((data->border_vert / 2) - (data->label_vert/2)), w, h, CTABFMT_XRGB8);
1169 break;
1171 case MUIV_NBitmap_Type_RGB24:
1172 D(DBF_ALWAYS, "drawing RGB image");
1173 WPA(data->data[item], 0, 0, data->width*3, _rp(obj), x + (data->border_horiz / 2), y + ((data->border_vert / 2) - (data->label_vert/2)), w, h, RECTFMT_RGB);
1174 break;
1176 case MUIV_NBitmap_Type_ARGB32:
1177 D(DBF_ALWAYS, "drawing ARGB image");
1178 WPAA(data->data[item], 0, 0, data->width*4, _rp(obj), x + (data->border_horiz / 2), y + ((data->border_vert / 2) - (data->label_vert/2)), w, h, data->alpha);
1179 break;
1181 #endif // __amigaos4__
1185 break;
1188 /* overlay */
1189 if(data->button && data->overlay)
1191 if(data->prefs.overlay_type == 1 || data->scrdepth <= 8)
1193 /* standard overlay */
1194 if(data->pressed)
1195 NBitmap_DrawSimpleFrame(obj, x + (data->border_horiz / 2), y + ((data->border_vert / 2) - (data->label_vert/2)), data->width, data->height);
1196 else
1197 NBitmap_DrawSimpleFrame(obj, x + (data->border_horiz / 2), y + ((data->border_vert / 2) - (data->label_vert/2)), data->width, data->height);
1199 else
1201 #if defined(__amigaos4__)
1202 uint32 error;
1204 if(data->pressed)
1205 error = BltBitMapTags(BLITA_Source, data->pressedShadePixels,
1206 BLITA_Dest, _rp(obj),
1207 BLITA_SrcX, 0,
1208 BLITA_SrcY, 0,
1209 BLITA_DestX, x+1,
1210 BLITA_DestY, y+1,
1211 BLITA_Width, data->shadeWidth,
1212 BLITA_Height, data->shadeHeight,
1213 BLITA_SrcType, BLITT_ARGB32,
1214 BLITA_DestType, BLITT_RASTPORT,
1215 BLITA_SrcBytesPerRow, data->shadeBytesPerRow,
1216 BLITA_UseSrcAlpha, TRUE,
1217 TAG_DONE);
1218 else
1219 error = BltBitMapTags(BLITA_Source, data->overShadePixels,
1220 BLITA_Dest, _rp(obj),
1221 BLITA_SrcX, 0,
1222 BLITA_SrcY, 0,
1223 BLITA_DestX, x+1,
1224 BLITA_DestY, y+1,
1225 BLITA_Width, data->shadeWidth,
1226 BLITA_Height, data->shadeHeight,
1227 BLITA_SrcType, BLITT_ARGB32,
1228 BLITA_DestType, BLITT_RASTPORT,
1229 BLITA_SrcBytesPerRow, data->shadeBytesPerRow,
1230 BLITA_UseSrcAlpha, TRUE,
1231 TAG_DONE);
1233 SHOWVALUE(DBF_DRAW, error);
1235 #else
1237 if(data->pressed)
1239 WPAA(data->pressedShadePixels, 0, 0, data->shadeBytesPerRow, _rp(obj), x+1, y+1, data->shadeWidth, data->shadeHeight, 0xffffffff);
1241 else
1243 WPAA(data->overShadePixels, 0, 0, data->shadeBytesPerRow, _rp(obj), x+1, y+1, data->shadeWidth, data->shadeHeight, 0xffffffff);
1246 #endif
1251 LEAVE();