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
21 ***************************************************************************/
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>
35 #include <datatypes/pictureclass.h>
37 #if defined(__amigaos4__)
38 #include <hardware/blit.h>
40 #include <proto/cybergraphics.h>
41 #include <cybergraphx/cybergraphics.h>
44 #if defined(__MORPHOS__)
45 #include <exec/execbase.h>
46 #include <exec/system.h>
50 #include <libraries/mui.h>
55 #include "Chunky2Bitmap.h"
56 #include "DitherImage.h"
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
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) \
94 if(CyberGfxBase != NULL) \
95 WritePixelArray(src, srcx, srcy, srcmod, rp, destx, desty, width, height, fmt); \
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); \
104 _WPAA(src, srcx, srcy, srcmod, rp, destx, desty, width, height, globalalpha); \
111 ULONG
GetConfigItem(Object
*obj
, ULONG configitem
, ULONG defaultsetting
)
114 ULONG result
= defaultsetting
;
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". */
130 static void InitConfig(Object
*obj
, struct InstData
*data
)
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;
153 static void FreeConfig(struct InstData
*data
)
166 /// NBitmap_LoadImage()
168 BOOL
NBitmap_LoadImage(STRPTR filename
, uint32 item
, struct IClass
*cl
, Object
*obj
)
171 struct InstData
*data
;
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
,
186 SHOWVALUE(DBF_DATATYPE
, data
->dt_obj
[item
]);
187 if(data
->dt_obj
[item
] != NULL
)
196 /// NBitmap_ExamineData()
198 static BOOL
NBitmap_ExamineData(Object
*dt_obj
, uint32 item
, struct IClass
*cl
, Object
*obj
)
203 struct pdtBlitPixelArray pbpa
;
204 struct InstData
*data
= INST_DATA(cl
, obj
);
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
;
219 data
->width
= data
->dt_header
[0]->bmh_Width
;
220 data
->height
= data
->dt_header
[0]->bmh_Height
;
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 */
231 GetDTAttrs(dt_obj
, PDTA_AlphaChannel
, (IPTR
)&use_alpha
, TAG_DONE
);
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
);
262 data
->arraybpr
= (data
->arraybpr
+ 15) & ~15;
266 arraysize
= (data
->arraybpr
) * data
->height
;
268 /* get array of pixels */
269 if((data
->arraypixels
[item
] = AllocVecShared(arraysize
, MEMF_ANY
|MEMF_CLEAR
)) != NULL
)
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
;
281 pbpa
.pbpa_Width
= data
->width
;
282 pbpa
.pbpa_Height
= data
->height
;
284 error
= DoMethodA(dt_obj
, (Msg
)(VOID
*)&pbpa
);
286 D(DBF_DATATYPE
, "examine: READPIXELARRAY returned %ld", error
);
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
)
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
;
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
)
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
;
360 #if defined(__MORPHOS__)
361 if (SysBase
->LibNode
.lib_Version
>= 51)
363 NewGetSystemAttrs(&altivec_align
, sizeof(altivec_align
), SYSTEMINFOTYPE_PPC_ALTIVEC
, TAG_DONE
);
367 data
->shadeWidth
= data
->width
+ data
->border_horiz
- 2;
368 data
->shadeHeight
= data
->height
+ data
->border_vert
- 2;
369 data
->shadeBytesPerRow
= data
->shadeWidth
* 4;
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
)
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
;
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
)
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
;
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
);
433 // delete the ARGB shades
434 void NBitmap_CleanupShades(struct InstData
*data
)
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
;
453 /// NBitmap_NewImage()
455 BOOL
NBitmap_NewImage(struct IClass
*cl
, Object
*obj
)
458 struct InstData
*data
;
462 if((data
= INST_DATA(cl
, obj
)) != NULL
)
466 case MUIV_NBitmap_Type_File
:
467 case MUIV_NBitmap_Type_DTObject
:
469 if(data
->dt_obj
[0] != NULL
)
473 // assume success for the moment
478 if(data
->dt_obj
[i
] != NULL
)
479 result
&= NBitmap_ExamineData(data
->dt_obj
[i
], i
, cl
, obj
);
485 case MUIV_NBitmap_Type_CLUT8
:
486 case MUIV_NBitmap_Type_RGB24
:
487 case MUIV_NBitmap_Type_ARGB32
:
489 // no further requirements, instant success
500 BOOL
NBitmap_OldNewImage(struct IClass
*cl
, Object
*obj
)
503 struct InstData
*data
;
505 /* need at least the normal image */
506 if((data
= INST_DATA(cl
, obj
)) !=NULL
&& data
->dt_obj
[0] != NULL
)
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
;
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");
538 else if(data
->depth
> 8)
542 /* correct read buffer */
543 if(data
->depth
== 24)
545 data
->fmt
= PBPAFMT_RGB
;
546 D(DBF_DATATYPE
, "new: using 24bit RGB data");
550 data
->fmt
= PBPAFMT_ARGB
;
551 D(DBF_DATATYPE
, "new: using 32bit ARGB data");
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
)
567 error
= DoMethod(data
->dt_obj
[i
], PDTM_READPIXELARRAY
, data
->arraypixels
[i
], data
->fmt
, data
->arraybpr
, 0, 0, data
->width
, data
->height
);
569 D(DBF_DATATYPE
, "new: READPIXELARRAY returned %ld", error
);
571 // finally create the shades
572 result
= NBitmap_SetupShades(data
);
586 /// NBitmap_DisposeImage()
588 VOID
NBitmap_DisposeImage(struct IClass
*cl
, Object
*obj
)
590 struct InstData
*data
;
594 if((data
= INST_DATA(cl
, obj
)) != NULL
)
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
);
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
);
635 /// NBitmap_SetupImage()
637 BOOL
NBitmap_SetupImage(struct IClass
*cl
, Object
*obj
)
639 struct InstData
*data
;
644 if((data
= INST_DATA(cl
, obj
)) != NULL
)
647 InitConfig(obj
, data
);
649 data
->scrdepth
= GetBitMapAttr(_screen(obj
)->RastPort
.BitMap
, BMA_DEPTH
);
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
);
665 case MUIV_NBitmap_Type_File
:
666 case MUIV_NBitmap_Type_DTObject
:
670 if(data
->fmt
== PBPAFMT_LUT8
&& data
->dt_obj
[0] != NULL
)
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
],
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
]);
693 else if(data
->depth
> 8)
694 result
= NBitmap_SetupShades(data
);
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)
708 SHOWVALUE(DBF_ALWAYS
, CyberGfxBase
);
709 if(CyberGfxBase
!= NULL
)
710 SHOWVALUE(DBF_ALWAYS
, CyberGfxBase
->lib_Version
);
711 if(data
->scrdepth
<= 8 || CyberGfxBase
== NULL
)
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
;
725 D(DBF_ALWAYS
, "using default color map");
726 colorMap
= defaultColorMap
;
729 D(DBF_ALWAYS
, "obtaining 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
,
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
],
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
777 /// NBitmap_CleanupImage()
779 VOID
NBitmap_CleanupImage(struct IClass
*cl
, Object
*obj
)
781 struct InstData
*data
;
785 if((data
= INST_DATA(cl
, obj
)) != NULL
)
789 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, &data
->ehnode
);
793 case MUIV_NBitmap_Type_File
:
794 case MUIV_NBitmap_Type_DTObject
:
796 if(data
->fmt
== PBPAFMT_LUT8
&& data
->dt_obj
[0] != NULL
)
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
);
810 case MUIV_NBitmap_Type_CLUT8
:
811 case MUIV_NBitmap_Type_RGB24
:
812 case MUIV_NBitmap_Type_ARGB32
:
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
]);
851 NBitmap_CleanupShades(data
);
861 /// NBitmap_DrawSimpleFrame()
863 static void NBitmap_DrawSimpleFrame(Object
*obj
, uint32 x
, uint32 y
, uint32 w
, uint32 h
)
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));
880 /// NBitmap_DrawImage()
882 void NBitmap_DrawImage(struct IClass
*cl
, Object
*obj
)
884 struct InstData
*data
;
888 if((data
= INST_DATA(cl
, obj
)) != NULL
)
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);
905 if(data
->label
!= NULL
&& data
->button
!= FALSE
)
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
));
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__)
933 if(data
->button
&& data
->pressed
&& data
->overlay
&& data
->dt_bitmap
[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
),
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
],
953 SHOWVALUE(DBF_DRAW
, error
);
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),
965 (APTR
)data
->dt_mask
[item
]);
969 BltBitMapRastPort(data
->dt_bitmap
[item
], 0, 0, _rp(obj
),
970 _left(obj
) + (data
->border_horiz
/ 2),
971 _top(obj
) + (data
->border_vert
/ 2),
981 if(data
->button
&& data
->pressed
&& data
->overlay
&& data
->arraypixels
[2] != NULL
)
984 SHOWVALUE(DBF_DRAW
, item
);
985 SHOWVALUE(DBF_DRAW
, data
->arraypixels
[item
]);
987 if(data
->arraypixels
[item
] != NULL
)
989 #if defined(__amigaos4__)
993 if(data
->depth
== 24)
994 srctype
= BLITT_RGB24
;
996 srctype
= BLITT_ARGB32
;
998 error
= BltBitMapTags(BLITA_Source
, data
->arraypixels
[item
],
999 BLITA_Dest
, _rp(obj
),
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
,
1012 SHOWVALUE(DBF_DRAW
, error
);
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
);
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);
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
);
1040 if(data
->button
&& data
->pressed
&& data
->overlay
&& data
->data
[2] != NULL
)
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
]);
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
),
1062 BLITA_DestX
, x
+ (data
->border_horiz
/ 2),
1063 BLITA_DestY
, y
+ ((data
->border_vert
/ 2) - (data
->label_vert
/2)),
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
),
1075 D(DBF_ALWAYS
, "drawing remapped/dithered image without mask");
1076 BltBitMapTags(BLITA_Source
, data
->ditheredImage
[item
],
1077 BLITA_Dest
, _rp(obj
),
1080 BLITA_DestX
, x
+ (data
->border_horiz
/ 2),
1081 BLITA_DestY
, y
+ ((data
->border_vert
/ 2) - (data
->label_vert
/2)),
1084 BLITA_SrcType
, BLITT_CHUNKY
,
1085 BLITA_DestType
, BLITT_RASTPORT
,
1086 BLITA_SrcBytesPerRow
, data
->width
,
1087 BLITA_Minterm
, (ABC
|ABNC
),
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
]);
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__
1110 #if defined(__amigaos4__)
1113 case MUIV_NBitmap_Type_CLUT8
:
1114 BltBitMapTags(BLITA_Source
, data
->data
[item
],
1115 BLITA_Dest
, _rp(obj
),
1118 BLITA_DestX
, x
+ (data
->border_horiz
/ 2),
1119 BLITA_DestY
, y
+ ((data
->border_vert
/ 2) - (data
->label_vert
/2)),
1122 BLITA_SrcType
, BLITT_CHUNKY
,
1123 BLITA_DestType
, BLITT_RASTPORT
,
1124 BLITA_SrcBytesPerRow
, data
->width
,
1125 BLITA_CLUT
, data
->clut
,
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
),
1135 BLITA_DestX
, x
+ (data
->border_horiz
/ 2),
1136 BLITA_DestY
, y
+ ((data
->border_vert
/ 2) - (data
->label_vert
/2)),
1139 BLITA_SrcType
, BLITT_RGB24
,
1140 BLITA_DestType
, BLITT_RASTPORT
,
1141 BLITA_SrcBytesPerRow
, data
->width
*3,
1142 BLITA_Alpha
, data
->alpha
,
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
),
1152 BLITA_DestX
, x
+ (data
->border_horiz
/ 2),
1153 BLITA_DestY
, y
+ ((data
->border_vert
/ 2) - (data
->label_vert
/2)),
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
,
1164 #else // __amigaos4__
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
);
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
);
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
);
1181 #endif // __amigaos4__
1189 if(data
->button
&& data
->overlay
)
1191 if(data
->prefs
.overlay_type
== 1 || data
->scrdepth
<= 8)
1193 /* standard overlay */
1195 NBitmap_DrawSimpleFrame(obj
, x
+ (data
->border_horiz
/ 2), y
+ ((data
->border_vert
/ 2) - (data
->label_vert
/2)), data
->width
, data
->height
);
1197 NBitmap_DrawSimpleFrame(obj
, x
+ (data
->border_horiz
/ 2), y
+ ((data
->border_vert
/ 2) - (data
->label_vert
/2)), data
->width
, data
->height
);
1201 #if defined(__amigaos4__)
1205 error
= BltBitMapTags(BLITA_Source
, data
->pressedShadePixels
,
1206 BLITA_Dest
, _rp(obj
),
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
,
1219 error
= BltBitMapTags(BLITA_Source
, data
->overShadePixels
,
1220 BLITA_Dest
, _rp(obj
),
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
,
1233 SHOWVALUE(DBF_DRAW
, error
);
1239 WPAA(data
->pressedShadePixels
, 0, 0, data
->shadeBytesPerRow
, _rp(obj
), x
+1, y
+1, data
->shadeWidth
, data
->shadeHeight
, 0xffffffff);
1243 WPAA(data
->overShadePixels
, 0, 0, data
->shadeBytesPerRow
, _rp(obj
), x
+1, y
+1, data
->shadeWidth
, data
->shadeHeight
, 0xffffffff);