Initial import of Scalos. To decrease size I have
[AROS-Contrib.git] / scalos / datatypes / IconObject / argb.c
blobe4b7d1ab0eeb2f38774365d3291714c7b73b80c9
1 // argb.c
2 // $Date$
3 // $Revision$
6 #include <exec/types.h>
7 #include <graphics/gfxbase.h>
8 #include <intuition/classes.h>
9 #include <intuition/classusr.h>
10 #include <intuition/gadgetclass.h>
11 #include <cybergraphx/cybergraphics.h>
12 #include <datatypes/iconobject.h>
13 #include <libraries/mcpgfx.h>
15 #define __USE_SYSBASE
16 #include <proto/graphics.h>
17 #include <proto/utility.h>
18 #include <proto/exec.h>
20 #include <clib/alib_protos.h>
21 #include <proto/exec.h>
22 #include <proto/graphics.h>
23 #include <proto/intuition.h>
24 #include <proto/utility.h>
25 #include <proto/cybergraphics.h>
26 #include <proto/scalosgfx.h>
28 #include <string.h>
29 #include <ctype.h>
31 #include <defs.h>
32 #include <Year.h>
33 #include <ScalosMcpGfx.h>
35 #include <datatypes/iconobject.h>
36 #include "iconobj.h"
38 //----------------------------------------------------------------------------
40 #define min(a,b) ((a) < (b) ? (a) : (b))
42 //----------------------------------------------------------------------------
44 extern struct Library *CyberGfxBase;
46 //-----------------------------------------------------------------------------
48 static void WriteARGBArray(const struct ARGB *src, struct RastPort *dst,
49 ULONG dstx, ULONG dsty, ULONG width, ULONG height);
50 static void DrawFrame(Object *o, struct InstanceData *inst, struct RastPort *rp,
51 LONG x, LONG y, UWORD FrameType);
52 static BOOL GenMaskFromARGB(const struct IconObjectARGB *img, const struct IconObjectARGB *CloneImage,
53 struct IconObjectMask *Mask, const struct IconObjectMask *CloneMask);
55 //-----------------------------------------------------------------------------
57 void ARGB_Draw(Class *cl, Object *o, struct iopDraw *opd, LONG x, LONG y)
59 struct InstanceData *inst = INST_DATA(cl, o);
60 struct ExtGadget *gg = (struct ExtGadget *) o;
61 struct ARGBHeader *ImgHeader;
62 struct IconObjectARGB *img;
64 if ((gg->Flags & GFLG_SELECTED) && inst->iobj_SelectedARGB.iargb_ARGBimage.argb_ImageData)
66 img = &inst->iobj_SelectedARGB;
68 else
70 img = &inst->iobj_NormalARGB;
73 if (img->iargb_ScaledARGBImage.argb_ImageData)
74 ImgHeader = &img->iargb_ScaledARGBImage;
75 else
76 ImgHeader = &img->iargb_ARGBimage;
78 d1(KPrintF("%s/%s/%ld: x=%ld y=%ld w=%ld h=%ld\n", __FILE__, __FUNC__, __LINE__, x, y, ImgHeader->argb_Width, ImgHeader->argb_Height));
79 d1(KPrintF("%s/%s/%ld: o=%08lx ImgData=%08lx\n", __FILE__, __FUNC__, __LINE__, o, ImgHeader->argb_ImageData));
80 d1(kprintf("%s/%s/%ld: ImgData[]=%08lx %08lx %08lx %08lx\n", __FILE__, __FUNC__, __LINE__, \
81 ImgHeader->argb_ImageData[0], ImgHeader->argb_ImageData[1], ImgHeader->argb_ImageData[2], ImgHeader->argb_ImageData[3]));
83 if (!(IODRAWF_NoImage & opd->iopd_DrawFlags))
85 if (!(IODRAWF_NoEraseBg & opd->iopd_DrawFlags))
86 EraseRect(opd->iopd_RastPort, x, y, x + gg->Width, y + gg->Height);
88 if (NULL == CyberGfxBase)
90 Move(opd->iopd_RastPort, x + inst->iobj_imgleft, y + inst->iobj_imgtop);
92 Draw(opd->iopd_RastPort, x + inst->iobj_imgleft + gg->Width, y + inst->iobj_imgtop);
93 Draw(opd->iopd_RastPort, x + inst->iobj_imgleft + gg->Width, y + inst->iobj_imgtop + gg->Height);
94 Draw(opd->iopd_RastPort, x + inst->iobj_imgleft, y + inst->iobj_imgtop + gg->Height);
95 Draw(opd->iopd_RastPort, x + inst->iobj_imgleft, y + inst->iobj_imgtop);
97 else
99 if (gg->Flags & GFLG_SELECTED)
101 struct ARGB K = { 0, 96, 96, 144 };
103 if (IODRAWF_NoAlpha & opd->iopd_DrawFlags)
105 if (img == &inst->iobj_SelectedARGB)
107 // draw selected image
108 WriteARGBArray(ImgHeader->argb_ImageData, opd->iopd_RastPort,
109 x + inst->iobj_imgleft, y + inst->iobj_imgtop,
110 ImgHeader->argb_Width, ImgHeader->argb_Height);
112 else
114 // draw highlighted variant of normal image
115 struct IBox SrcSize;
117 SrcSize.Left = SrcSize.Top = 0;
118 SrcSize.Width = ImgHeader->argb_Width;
119 SrcSize.Height = ImgHeader->argb_Height;
121 ScalosGfxBlitARGBAlphaTags(opd->iopd_RastPort,
122 ImgHeader,
123 x + inst->iobj_imgleft, y + inst->iobj_imgtop,
124 &SrcSize,
125 SCALOSGFX_BlitARGBHilight, (ULONG) &K,
126 SCALOSGFX_BlitARGBTransparency, 200,
127 SCALOSGFX_BlitARGBNoAlpha, TRUE,
128 TAG_END);
131 else
133 if (img == &inst->iobj_SelectedARGB)
135 // draw selected image
136 ScalosGfxBlitARGBAlpha(opd->iopd_RastPort,
137 ImgHeader,
138 x + inst->iobj_imgleft, y + inst->iobj_imgtop,
139 0, 0,
140 ImgHeader->argb_Width, ImgHeader->argb_Height);
142 else
144 // draw highlighted variant of normal image
145 struct IBox SrcSize;
147 SrcSize.Left = SrcSize.Top = 0;
148 SrcSize.Width = ImgHeader->argb_Width;
149 SrcSize.Height = ImgHeader->argb_Height;
151 ScalosGfxBlitARGBAlphaTags(opd->iopd_RastPort,
152 ImgHeader,
153 x + inst->iobj_imgleft, y + inst->iobj_imgtop,
154 &SrcSize,
155 SCALOSGFX_BlitARGBHilight, (ULONG) &K,
156 SCALOSGFX_BlitARGBTransparency, 200,
157 TAG_END);
160 if (!inst->iobj_Borderless && inst->iobj_imgleft > 0 && inst->iobj_imgtop > 0)
161 DrawFrame(o, inst, opd->iopd_RastPort, x, y, inst->iobj_frametypesel);
163 else
165 if (IODRAWF_NoAlpha & opd->iopd_DrawFlags)
167 WriteARGBArray(ImgHeader->argb_ImageData, opd->iopd_RastPort,
168 x + inst->iobj_imgleft, y + inst->iobj_imgtop,
169 ImgHeader->argb_Width, ImgHeader->argb_Height);
171 else
173 ScalosGfxBlitARGBAlpha(opd->iopd_RastPort,
174 ImgHeader,
175 x + inst->iobj_imgleft, y + inst->iobj_imgtop,
176 0, 0,
177 ImgHeader->argb_Width, ImgHeader->argb_Height);
179 if (!inst->iobj_Borderless && inst->iobj_imgleft > 0 && inst->iobj_imgtop > 0)
180 DrawFrame(o, inst, opd->iopd_RastPort, x, y, inst->iobj_frametype);
186 //-----------------------------------------------------------------------------
188 static void WriteARGBArray(const struct ARGB *src, struct RastPort *dst,
189 ULONG dstx, ULONG dsty, ULONG width, ULONG height)
191 WritePixelArray((APTR) src, 0, 0,
192 width * sizeof(struct ARGB),
193 dst, dstx, dsty,
194 width, height, RECTFMT_ARGB);
197 //-----------------------------------------------------------------------------
199 static void DrawFrame(Object *o, struct InstanceData *inst, struct RastPort *rp,
200 LONG x, LONG y, UWORD FrameType)
202 struct RastPort rpCopy;
203 struct ExtGadget *gg = (struct ExtGadget *) o;
205 rpCopy = *rp;
207 d1(kprintf("%s/%s/%ld: xMin=%ld yMin=%ld xMax=%ld yMax=%ld\n", \
208 __FILE__, __FUNC__, __LINE__, x, y, x + gg->Width - 1, y + gg->Height - 1));
210 McpGfxDrawFrame(&rpCopy, x, y, x + gg->Width - 1, y + gg->Height - 1,
211 IA_HalfShinePen, inst->iobj_HalfShinePen,
212 IA_HalfShadowPen, inst->iobj_HalfShadowPen,
213 IA_FrameType, FrameType & 0x7fff,
214 IA_Recessed, (FrameType & 0x8000) ? 1 : 0,
215 TAG_END);
218 //-----------------------------------------------------------------------------
220 BOOL GenMasksFromARGB(Class *cl, Object *o)
222 struct InstanceData *inst = INST_DATA(cl, o);
224 d1(KPrintF("%s/%s/%ld: START o=%08lx inst=%08lx\n", __FILE__, __FUNC__, __LINE__, o, inst));
226 if (!GenMaskFromARGB(&inst->iobj_NormalARGB, NULL,
227 &inst->iobj_NormalMask, NULL))
228 return FALSE;
230 d1(KPrintF("%s/%s/%ld: o=%08lx inst=%08lx\n", __FILE__, __FUNC__, __LINE__, o, inst));
232 return GenMaskFromARGB(&inst->iobj_SelectedARGB, &inst->iobj_NormalARGB,
233 &inst->iobj_SelectedMask, &inst->iobj_NormalMask);
236 //-----------------------------------------------------------------------------
238 static BOOL GenMaskFromARGB(const struct IconObjectARGB *img, const struct IconObjectARGB *CloneImage,
239 struct IconObjectMask *Mask, const struct IconObjectMask *CloneMask)
241 const struct ARGBHeader *ImgHeader;
242 const struct ARGB *PicPtr;
243 ULONG BytesPerRow;
244 const struct IconObjectARGB *imgUsed;
245 size_t Size;
247 d1(KPrintF( "%s/%s/%ld: img=%08lx CloneImage=%08lx\n", __FILE__, __FUNC__, __LINE__, img, CloneImage));
248 d1(KPrintF( "%s/%s/%ld: Mask=%08lx CloneMask=%08lx\n", __FILE__, __FUNC__, __LINE__, Mask, CloneMask));
250 imgUsed = img->iargb_ARGBimage.argb_ImageData ? img : CloneImage;
252 if (NULL == imgUsed)
253 return FALSE;
255 d1(KPrintF( "%s/%s/%ld: iargb_ScaledARGBImage=%08lx w=%ld h=%ld ImageData=%08lx\n", __FILE__, __FUNC__, __LINE__, \
256 &imgUsed->iargb_ScaledARGBImage, \
257 imgUsed->iargb_ScaledARGBImage.argb_Width, \
258 imgUsed->iargb_ScaledARGBImage.argb_Height, \
259 imgUsed->iargb_ScaledARGBImage.argb_ImageData));
260 d1(KPrintF( "%s/%s/%ld: iargb_ARGBimage=%08lx w=%ld h=%ld ImageData=%08lx\n", __FILE__, __FUNC__, __LINE__, \
261 &imgUsed->iargb_ARGBimage, \
262 imgUsed->iargb_ARGBimage.argb_Width, \
263 imgUsed->iargb_ARGBimage.argb_Height, \
264 imgUsed->iargb_ARGBimage.argb_ImageData));
266 if (imgUsed->iargb_ScaledARGBImage.argb_Width > 512
267 || imgUsed->iargb_ScaledARGBImage.argb_Height > 512)
268 return FALSE;
270 d1(KPrintF( "%s/%s/%ld: imgUsed=%08lx\n", __FILE__, __FUNC__, __LINE__, imgUsed));
272 if (imgUsed->iargb_ScaledARGBImage.argb_ImageData)
273 ImgHeader = &imgUsed->iargb_ScaledARGBImage;
274 else
275 ImgHeader = &imgUsed->iargb_ARGBimage;
277 d1(KPrintF( "%s/%s/%ld: Width=%lu Height=%ld\n", __FILE__, __FUNC__, __LINE__, ImgHeader->argb_Width, ImgHeader->argb_Height));
279 Mask->iom_Width = ImgHeader->argb_Width;
280 Mask->iom_Height = ImgHeader->argb_Height;
282 BytesPerRow = BYTESPERROW(ImgHeader->argb_Width);
283 Size = BytesPerRow * ImgHeader->argb_Height;
284 Size = ALIGN_LONG(Size);
286 d1(KPrintF( "%s/%s/%ld: BytesPerRow=%ld\n", __FILE__, __FUNC__, __LINE__, BytesPerRow));
288 MyFreeVecPooled(ChipMemPool, (APTR *) &Mask->iom_Mask);
290 Mask->iom_Mask = MyAllocVecPooled(ChipMemPool, Size);
291 if (NULL == Mask->iom_Mask)
292 return FALSE;
294 memset(Mask->iom_Mask, 0, Size);
296 PicPtr = ImgHeader->argb_ImageData;
298 d1(KPrintF( "%s/%s/%ld: PicPtr=%08lx\n", __FILE__, __FUNC__, __LINE__, PicPtr));
300 if (PicPtr)
302 UBYTE *MaskPtr = Mask->iom_Mask;
303 LONG y;
304 ULONG Threshold = 0;
306 d1(KPrintF( "%s/%s/%ld: \n", __FILE__, __FUNC__, __LINE__));
308 for (y = 0; y < ImgHeader->argb_Height; y++)
310 LONG x;
311 UWORD BitMask = 0x0080;
312 UBYTE *MaskPtr2 = MaskPtr;
314 for (x = 0; x < ImgHeader->argb_Width; x++)
316 UBYTE alpha;
318 alpha = PicPtr->Alpha;
319 PicPtr++;
321 if (alpha > Threshold)
322 *MaskPtr2 |= BitMask;
324 BitMask >>= 1;
325 if (0 == BitMask)
327 BitMask = 0x0080;
328 MaskPtr2++;
329 d1(if (MaskPtr2 > Mask->iom_Mask + Size)\
331 kprintf("%s/%s/%ld: iobj_normmask overflow\n", __FILE__, __FUNC__, __LINE__); \
332 break; \
333 } );
337 MaskPtr += BytesPerRow;
340 else if (CloneImage && CloneMask)
342 d1(KPrintF( "%s/%s/%ld: \n", __FILE__, __FUNC__, __LINE__));
344 Mask->iom_Width = CloneMask->iom_Width;
345 Mask->iom_Height = CloneMask->iom_Height;
347 CopyMem(Mask->iom_Mask, CloneMask->iom_Mask, Size);
350 return TRUE;
353 //-----------------------------------------------------------------------------
355 BOOL GenAlphaFromARGB(Class *cl, Object *o, struct IconObjectARGB *img, struct ARGBHeader *ImgHeader)
357 struct InstanceData *inst = INST_DATA(cl, o);
358 struct ExtGadget *gg = (struct ExtGadget *) o;
359 UBYTE *AlphaPtr;
360 const struct ARGB *PicPtr;
361 UWORD Left, BoundsLeft;
362 ULONG IconWidth, IconHeight;
363 WORD LeftOffset;
364 ULONG y;
365 size_t Size;
368 d1(KPrintF("%s/%s/%ld: START o=%08lx w=%lu h=%lu bw=%lu bh=%lu\n", \
369 __FILE__, __FUNC__, __LINE__, o, gg->Width, gg->Height, gg->BoundsWidth, gg->BoundsHeight));
371 Left = (UWORD) gg->LeftEdge;
372 BoundsLeft = (UWORD) gg->BoundsLeftEdge;
374 d1(KPrintF("%s/%s/%ld: Left=%lu BoundsLeft=%lu\n", __FILE__, __FUNC__, __LINE__, Left, BoundsLeft));
376 IconWidth = gg->BoundsWidth;
377 IconHeight = gg->BoundsHeight;
379 d1(KPrintF("%s/%s/%ld: argb_Width=%lu BoundsWidth=%lu\n", __FILE__, __FUNC__, __LINE__, ImgHeader->argb_Width, gg->BoundsWidth));
380 d1(KPrintF("%s/%s/%ld: argb_Height=%lu BoundsHeight=%lu\n", __FILE__, __FUNC__, __LINE__, ImgHeader->argb_Height, gg->BoundsHeight));
382 LeftOffset = inst->iobj_imgleft + (Left - BoundsLeft);
383 d1(KPrintF("%s/%s/%ld: iobj_imgleft=%lu iobj_imgtop=%lu LeftOffset=%ld\n", \
384 __FILE__, __FUNC__, __LINE__, inst->iobj_imgleft, inst->iobj_imgtop, LeftOffset));
386 if ((LeftOffset + ImgHeader->argb_Width) > IconWidth)
388 IconWidth = LeftOffset + ImgHeader->argb_Width;
389 d1(KPrintF("%s/%s/%ld: Image does not fit - BoundsWidth too small or iobj_imgleft too large!!\n", __FILE__, __FUNC__, __LINE__));
392 Size = IconWidth * IconHeight;
394 MyFreeVecPooled(PubMemPool, (APTR *) &img->iargb_AlphaChannel);
396 img->iargb_AlphaChannel = MyAllocVecPooled(PubMemPool, Size);
397 d1(KPrintF("%s/%s/%ld: iobj_AlphaChannel=%08lx Size=%lu\n", __FILE__, __FUNC__, __LINE__, img->iargb_AlphaChannel, Size));
398 if (NULL == img->iargb_AlphaChannel)
399 return FALSE;
401 // make sure all parts outside the image area are visible (border + text)
402 memset(img->iargb_AlphaChannel, 0xff, Size);
404 PicPtr = ImgHeader->argb_ImageData;
405 AlphaPtr = img->iargb_AlphaChannel + inst->iobj_imgtop * IconWidth;
407 d1(KPrintF("%s/%s/%ld: argb_Width=%lu argb_Height=%lu\n", __FILE__, __FUNC__, __LINE__, \
408 ImgHeader->argb_Width, ImgHeader->argb_Height));
410 for (y = 0; y < ImgHeader->argb_Height; y++)
412 ULONG x;
413 UBYTE *XAlphaPtr;
415 for (x = 0, XAlphaPtr = AlphaPtr + LeftOffset; x < ImgHeader->argb_Width; x++)
417 d1(if (XAlphaPtr > img->iargb_AlphaChannel + Size)\
419 kprintf("%s/%s/%ld: (x=%ld,y=%ld) XAlphaPtr overflow\n", __FILE__, __FUNC__, __LINE__, x, y);\
420 break; \
421 } );
422 *XAlphaPtr++ = PicPtr->Alpha;
423 PicPtr++;
426 AlphaPtr += IconWidth;
429 d1(KPrintF("%s/%s/%ld: END o=%08lx\n", __FILE__, __FUNC__, __LINE__, o));
431 return TRUE;
434 //-----------------------------------------------------------------------------