revert commit 56204.
[AROS.git] / workbench / libs / muimaster / classes / image.c
blob9c7ba87ccb50c83b08bee96799baa8e84957fa2f
1 /*
2 Copyright 2002-2019, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <stdio.h>
8 #include <intuition/imageclass.h>
9 #include <datatypes/pictureclass.h>
11 #include <graphics/gfx.h>
12 #include <graphics/view.h>
13 #include <clib/alib_protos.h>
14 #include <proto/exec.h>
15 #include <proto/graphics.h>
16 #include <proto/utility.h>
17 #include <proto/intuition.h>
18 #include <proto/muimaster.h>
19 #include <proto/cybergraphics.h>
20 #include <proto/datatypes.h>
22 #include <string.h>
24 /* #define MYDEBUG 1 */
26 #include "../datatypescache.h"
27 #include "../imspec_intern.h"
29 #include "debug.h"
30 #include "mui.h"
31 #include "muimaster_intern.h"
32 #include "support.h"
33 #include "imspec.h"
35 // FIXME: quick hack to not draw the background for gradients. It should really be generalized
36 #include "imspec_intern.h"
38 extern struct Library *MUIMasterBase;
40 #define MIF_FREEVERT (1<<0)
41 #define MIF_FREEHORIZ (1<<1)
42 #define MIF_FONTMATCHWIDTH (1<<3)
43 #define MIF_FONTMATCHHEIGHT (1<<4)
45 struct MUI_ImageData
47 char *spec;
48 ULONG flags;
49 struct MUI_ImageSpec_intern *img;
50 struct NewImage *propimage;
51 struct Image *old_image;
52 Object *prop; /* private hack to use prop images */
53 LONG state; /* see IDS_* in intuition/imageclass.h */
54 ULONG specnr;
58 /**************************************************************************
59 OM_NEW
60 **************************************************************************/
61 IPTR Image__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
63 struct MUI_ImageData *data;
64 struct TagItem *tags;
65 struct TagItem *tag;
66 Object *prop;
68 /* D(bug("Image_New starts\n")); */
70 prop = (Object *)GetTagData(MUIA_Image_Prop, 0, msg->ops_AttrList);
73 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
74 if (!obj) return FALSE;
76 data = INST_DATA(cl, obj);
77 data->state = IDS_NORMAL;
79 /* parse initial taglist */
81 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
83 switch (tag->ti_Tag)
85 case MUIA_Selected:
86 if (tag->ti_Data)
87 data->state = IDS_SELECTED;
88 break;
89 case MUIA_Image_FontMatch:
90 _handle_bool_tag(data->flags, tag->ti_Data, MIF_FONTMATCHWIDTH);
91 _handle_bool_tag(data->flags, tag->ti_Data, MIF_FONTMATCHHEIGHT);
92 break;
93 case MUIA_Image_FontMatchWidth:
94 _handle_bool_tag(data->flags, tag->ti_Data, MIF_FONTMATCHWIDTH);
95 break;
96 case MUIA_Image_FontMatchHeight:
97 _handle_bool_tag(data->flags, tag->ti_Data, MIF_FONTMATCHHEIGHT);
98 break;
99 case MUIA_Image_FreeHoriz:
100 _handle_bool_tag(data->flags, tag->ti_Data, MIF_FREEHORIZ);
101 break;
102 case MUIA_Image_FreeVert:
103 _handle_bool_tag(data->flags, tag->ti_Data, MIF_FREEVERT);
104 break;
105 case MUIA_Image_Spec:
107 char *spec;
108 char spec_buf[20];
110 data->specnr = tag->ti_Data;
112 if (tag->ti_Data >= MUII_WindowBack && tag->ti_Data < MUII_BACKGROUND)
114 sprintf(spec_buf,"6:%ld",tag->ti_Data);
115 spec = spec_buf;
117 else if (tag->ti_Data >= MUII_BACKGROUND && tag->ti_Data < MUII_LASTPAT)
119 sprintf(spec_buf,"0:%ld",tag->ti_Data);
120 spec = spec_buf;
122 else
124 spec = (char*)tag->ti_Data;
126 data->spec = StrDup(spec);
128 break;
130 case MUIA_Image_OldImage:
131 data->old_image = (struct Image *)tag->ti_Data;
132 break;
133 case MUIA_Image_State:
134 data->state = (LONG)tag->ti_Data;
135 break;
139 data->prop = prop;
141 /* if (!data->spec && !data->old_image) */
142 /* { */
143 /* data->spec = StrDup("0:128"); */
144 /* } */
146 /* if (!data->spec && !data->old_image) */
147 /* { */
148 /* CoerceMethod(cl,obj,OM_DISPOSE); */
149 /* return NULL; */
150 /* } */
152 /* D(bug("Image_New(%lx) spec=%lx\n", obj, data->img)); */
153 return (IPTR)obj;
156 /**************************************************************************
157 OM_DISPOSE
158 **************************************************************************/
159 IPTR Image__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
161 struct MUI_ImageData *data = INST_DATA(cl, obj);
163 if (data->spec)
164 zune_image_spec_free(data->spec);
165 DoSuperMethodA(cl,obj,(Msg)msg);
166 return 0;
169 /**************************************************************************
170 OM_SET
171 **************************************************************************/
172 IPTR Image__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
174 struct MUI_ImageData *data = INST_DATA(cl, obj);
175 struct TagItem *tag, *tags;
177 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
179 switch (tag->ti_Tag)
181 case MUIA_Selected:
182 if (tag->ti_Data)
183 data->state = IDS_SELECTED;
184 else
185 data->state = IDS_NORMAL;
186 D(bug("Image_Set(%p): state=%ld\n", obj, data->state));
187 break;
188 case MUIA_Image_State:
189 if (data->state != (LONG)tag->ti_Data)
191 data->state = (LONG)tag->ti_Data;
192 MUI_Redraw(obj,MADF_DRAWOBJECT);
194 break;
195 case MUIA_Image_Spec:
196 data->specnr = tag->ti_Data;
197 if (data->spec)
198 zune_image_spec_free(data->spec);
199 data->spec = zune_image_spec_duplicate(tag->ti_Data);
201 if ((_flags(obj) & MADF_CANDRAW) && data->img)
202 zune_imspec_hide(data->img);
204 if (_flags(obj) & MADF_SETUP)
206 if (data->img)
207 zune_imspec_cleanup(data->img);
208 data->img = zune_imspec_setup((IPTR)data->spec, muiRenderInfo(obj));
209 // FIXME: quick hack to not draw the background for gradients. It should really be generalized
210 if (data->img)
212 if (data->img->type == IST_SCALED_GRADIENT
213 || data->img->type == IST_TILED_GRADIENT)
214 set(obj, MUIA_FillArea, FALSE);
215 else
216 set(obj, MUIA_FillArea, TRUE);
220 if (_flags(obj) & MADF_CANDRAW)
221 zune_imspec_show(data->img, obj);
223 MUI_Redraw(obj,MADF_DRAWOBJECT);
224 break;
228 return (IPTR)DoSuperMethodA(cl,obj,(Msg)msg);
231 /**************************************************************************
232 OM_GET
233 **************************************************************************/
234 IPTR Image__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
236 struct MUI_ImageData *data = INST_DATA(cl, obj);
237 switch (msg->opg_AttrID)
239 case MUIA_Image_Spec:
240 *msg->opg_Storage = (IPTR)data->spec;
241 return TRUE;
244 return (IPTR)DoSuperMethodA(cl,obj,(Msg)msg);
247 struct NewImage *GetPropImage(struct MUI_ImageData *data, Object *prop)
249 struct MUI_AreaData *adata = muiAreaData(prop);
250 struct MUI_ImageSpec_intern *spec = adata->mad_Background;
252 if (spec)
254 if (spec->type == IST_BITMAP)
256 struct dt_node *node = spec->u.bitmap.dt;
257 if (node)
259 if (node->mode == MODE_PROP)
261 if (data->specnr == MUII_ArrowDown) return node->img_down;
262 if (data->specnr == MUII_ArrowUp) return node->img_up;
263 if (data->specnr == MUII_ArrowLeft) return node->img_left;
264 if (data->specnr == MUII_ArrowRight) return node->img_right;
269 return NULL;
272 /**************************************************************************
273 MUIM_Setup
274 **************************************************************************/
275 IPTR Image__MUIM_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
277 struct MUI_ImageData *data = INST_DATA(cl, obj);
278 if (!DoSuperMethodA(cl, obj, (Msg)msg))
279 return (IPTR)NULL;
280 data->propimage = NULL;
282 if (data->prop)
284 if (muiGlobalInfo(obj)->mgi_Prefs->scrollbar_type == SCROLLBAR_TYPE_CUSTOM)
286 struct NewImage *ni = GetPropImage(data, data->prop);
287 if (ni)
289 set(obj, MUIA_Frame, MUIV_Frame_None);
290 return(1);
293 else
295 data->prop = NULL;
300 if (data->spec)
302 data->img = zune_imspec_setup((IPTR)data->spec, muiRenderInfo(obj));
303 // FIXME: quick hack to not draw the background for gradients. It should really be generalized
304 if (data->img)
306 if (data->img->type == IST_SCALED_GRADIENT
307 || data->img->type == IST_TILED_GRADIENT)
308 set(obj, MUIA_FillArea, FALSE);
309 else
310 set(obj, MUIA_FillArea, TRUE);
313 if ((data->img != NULL) && (data->img->type == IST_BRUSH))
315 set(obj, MUIA_Frame, MUIV_Frame_None);
318 return 1;
321 /**************************************************************************
322 MUIM_Cleanup
323 **************************************************************************/
324 IPTR Image__MUIM_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
326 struct MUI_ImageData *data = INST_DATA(cl, obj);
328 if (data->img)
330 zune_imspec_cleanup(data->img);
331 data->img = NULL;
333 return DoSuperMethodA(cl,obj,(Msg)msg);
337 /**************************************************************************
338 MUIM_AskMinMax
339 **************************************************************************/
340 IPTR Image__MUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
342 struct MUI_ImageData *data = INST_DATA(cl, obj);
344 DoSuperMethodA(cl, obj, (Msg)msg);
347 if (data->prop != NULL)
349 struct NewImage *ni = GetPropImage(data, data->prop);
350 if (ni)
352 msg->MinMaxInfo->MinWidth = ni->w >> 2;
353 msg->MinMaxInfo->MaxWidth = ni->w >> 2;
354 msg->MinMaxInfo->DefWidth = ni->w >> 2;
356 msg->MinMaxInfo->MinHeight = ni->h;
357 msg->MinMaxInfo->MaxHeight = ni->h;
358 msg->MinMaxInfo->DefHeight = ni->h;
359 data->propimage = ni;
360 return(1);
364 if (data->img)
366 struct MUI_MinMax minmax;
368 zune_imspec_askminmax(data->img, &minmax);
370 if (data->flags & MIF_FREEHORIZ)
372 msg->MinMaxInfo->MinWidth += minmax.MinWidth;
373 msg->MinMaxInfo->MaxWidth += minmax.MaxWidth;
374 msg->MinMaxInfo->DefWidth += minmax.DefWidth;
376 else
378 msg->MinMaxInfo->MinWidth += minmax.DefWidth;
379 msg->MinMaxInfo->MaxWidth += minmax.DefWidth;
380 msg->MinMaxInfo->DefWidth += minmax.DefWidth;
383 if (data->flags & MIF_FONTMATCHWIDTH)
385 msg->MinMaxInfo->DefWidth *= _font(obj)->tf_XSize / 8;
389 if (data->flags & MIF_FREEVERT)
391 msg->MinMaxInfo->MinHeight += minmax.MinHeight;
392 msg->MinMaxInfo->MaxHeight += minmax.MaxHeight;
393 msg->MinMaxInfo->DefHeight += minmax.DefHeight;
395 else
397 msg->MinMaxInfo->MinHeight += minmax.DefHeight;
398 msg->MinMaxInfo->MaxHeight += minmax.DefHeight;
399 msg->MinMaxInfo->DefHeight += minmax.DefHeight;
402 if (data->flags & MIF_FONTMATCHHEIGHT)
404 msg->MinMaxInfo->DefHeight *= _font(obj)->tf_YSize / 8;
407 else if (data->old_image)
409 msg->MinMaxInfo->MinWidth += data->old_image->Width;
410 msg->MinMaxInfo->DefWidth = msg->MinMaxInfo->MinWidth;
411 msg->MinMaxInfo->MaxWidth = msg->MinMaxInfo->MinWidth;
413 msg->MinMaxInfo->MinHeight += data->old_image->Height;
414 msg->MinMaxInfo->DefHeight = msg->MinMaxInfo->MinHeight;
415 msg->MinMaxInfo->MaxHeight = msg->MinMaxInfo->MinHeight;
417 else /* no imagespec specified */
419 /* D(bug("*** Image_AskMinMax : no img, no old_img\n")); */
420 /* msg->MinMaxInfo->MinWidth += 8; */
421 /* msg->MinMaxInfo->DefWidth = msg->MinMaxInfo->MinWidth; */
422 /* msg->MinMaxInfo->MaxWidth = msg->MinMaxInfo->MinWidth; */
424 /* msg->MinMaxInfo->MinHeight += 8; */
425 /* msg->MinMaxInfo->DefHeight = msg->MinMaxInfo->MinHeight; */
426 /* msg->MinMaxInfo->MaxHeight = msg->MinMaxInfo->MinHeight; */
428 return 1;
431 /**************************************************************************
432 MUIM_Show
433 **************************************************************************/
434 IPTR Image__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
436 struct MUI_ImageData *data = INST_DATA(cl, obj);
438 DoSuperMethodA(cl,obj,(Msg)msg);
439 if (data->img)
440 zune_imspec_show(data->img, obj);
441 return 1;
444 /**************************************************************************
445 MUIM_Hide
446 **************************************************************************/
447 IPTR Image__MUIM_Hide(struct IClass *cl, Object *obj,struct MUIP_Hide *msg)
449 struct MUI_ImageData *data = INST_DATA(cl, obj);
451 if (data->img)
452 zune_imspec_hide(data->img);
453 return DoSuperMethodA(cl,obj,(Msg)msg);
456 /**************************************************************************
457 MUIM_Draw
458 **************************************************************************/
460 void DrawAlphaStateImageToRP(struct RastPort *rp, struct NewImage *ni, ULONG state, UWORD xp, UWORD yp) {
462 /* Function: draw an Image to a specific RastPort using AlphaValues
463 * Input: RastPortd rp:
464 * RastPort to draw to
465 * NewImage ni:
466 * Image to draw
467 * UWORD xp, yp:
468 * location where to draw the Image
469 * Bugs: Not known, throught the lack of AlphaHandling in cgfx/p96 there
470 * must all be done by hand so it's recommended to use this for small Images.
471 * NOTES: a temporary Buffer must be allocated to store the Background
474 UWORD ix, iy;
475 UBYTE *d;
476 ULONG depth;
480 if (ni)
482 depth = (ULONG) GetBitMapAttr(rp->BitMap, BMA_DEPTH);
484 d = (UBYTE *) ni->data;
485 ix=ni->w;
486 iy=ni->h;
487 switch(state) {
488 case IDS_NORMAL:
489 break;
490 case IDS_SELECTED:
491 d += (ix >> 2) * 4;
492 break;
493 case IDS_INACTIVENORMAL:
494 d += (ix >> 2) * 8;
495 break;
498 if (depth >= 15)
500 WritePixelArrayAlpha(d, 0 , 0, ix*4, rp, xp, yp, ix >> 2, iy, 0xffffffff);
502 else if (ni->bitmap != NULL)
504 if (ni->mask)
506 BltMaskBitMapRastPort(ni->bitmap, 0, 0, rp, xp, yp, ix >> 2, iy, 0xe0, (PLANEPTR) ni->mask);
508 else BltBitMapRastPort(ni->bitmap, 0, 0, rp, xp, yp, ix >> 2, iy, 0xc0);
514 IPTR Image__MUIM_Draw(struct IClass *cl, Object *obj,struct MUIP_Draw *msg)
516 struct MUI_ImageData *data = INST_DATA(cl, obj);
518 D(bug("Image_Draw(%p): msg=0x%08lx state=%ld sss=%ld\n",
519 obj, ((struct MUIP_Draw *)msg)->flags, data->state,
520 !!(_flags(obj) & MADF_SHOWSELSTATE)));
522 if (data->propimage == NULL)
524 DoSuperMethodA(cl,obj,(Msg)msg);
526 if (!(msg->flags & (MADF_DRAWOBJECT|MADF_DRAWUPDATE)))
527 return 0;
530 if (data->propimage)
532 //Object *p = NULL;
533 //get(obj, MUIA_Parent, &p);
534 //if (p) DoMethod(p, MUIM_DrawParentBackground, _left(obj), _top(obj), _width(obj), _height(obj), _left(obj), _top(obj), 0);
535 //else
536 DoMethod(obj, MUIM_DrawParentBackground, _left(obj), _top(obj), _width(obj), _height(obj), _left(obj), _top(obj), 0);
538 DrawAlphaStateImageToRP(_rp(obj), data->propimage, data->state, _left(obj), _top(obj));
540 else if (data->img)
542 zune_imspec_draw(data->img, muiRenderInfo(obj),
543 _mleft(obj),_mtop(obj),_mwidth(obj),_mheight(obj),
544 0, 0, data->state);
546 else if (data->old_image)
548 DrawImage(_rp(obj), data->old_image, _mleft(obj),_mtop(obj));
550 return 1;
554 BOOPSI_DISPATCHER(IPTR, Image_Dispatcher, cl, obj, msg)
556 switch (msg->MethodID)
558 case OM_NEW: return Image__OM_NEW(cl, obj, (struct opSet *)msg);
559 case OM_DISPOSE: return Image__OM_DISPOSE(cl, obj, msg);
560 case OM_SET: return Image__OM_SET(cl, obj, (APTR)msg);
561 case OM_GET: return Image__OM_GET(cl, obj, (APTR)msg);
562 case MUIM_AskMinMax: return Image__MUIM_AskMinMax(cl,obj,(APTR)msg);
563 case MUIM_Setup: return Image__MUIM_Setup(cl,obj,(APTR)msg);
564 case MUIM_Cleanup: return Image__MUIM_Cleanup(cl,obj,(APTR)msg);
565 case MUIM_Show: return Image__MUIM_Show(cl,obj,(APTR)msg);
566 case MUIM_Hide: return Image__MUIM_Hide(cl,obj,(APTR)msg);
567 case MUIM_Draw: return Image__MUIM_Draw(cl,obj,(APTR)msg);
570 return DoSuperMethodA(cl, obj, msg);
572 BOOPSI_DISPATCHER_END
575 * Class descriptor.
577 const struct __MUIBuiltinClass _MUI_Image_desc = {
578 MUIC_Image,
579 MUIC_Area,
580 sizeof(struct MUI_ImageData),
581 (void*)Image_Dispatcher