Safer handling of Booleans.
[AROS.git] / workbench / libs / muimaster / datatypescache.c
blob3e50c8c11bcbcb31564536c4f5003497a048c80e
1 /*
2 Copyright 2002-2011, The AROS Development Team.
3 All rights reserved.
5 $Id$
6 */
8 #include <ctype.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stdio.h>
13 #define DT_V44_SUPPORT
15 #include <datatypes/pictureclass.h>
17 #include <clib/alib_protos.h>
18 #include <proto/exec.h>
19 #include <proto/dos.h>
20 #include <proto/datatypes.h>
21 #include <proto/graphics.h>
22 #include <proto/intuition.h>
23 #include <proto/utility.h>
24 #include <proto/layers.h>
25 #include <proto/cybergraphics.h>
27 //#define MYDEBUG 1
28 #include "debug.h"
29 #include "support.h"
30 #include "muimaster_intern.h"
31 #include "datatypescache.h"
33 extern struct Library *MUIMasterBase;
35 static struct List dt_list;
36 static int dt_initialized;
39 struct LayerHookMsg
41 STACKED struct Layer *layer;
42 STACKED struct Rectangle bounds;
43 STACKED LONG offsetx;
44 STACKED LONG offsety;
47 struct BltMaskHook
49 struct Hook hook;
50 struct BitMap maskBitMap;
51 struct BitMap *srcBitMap;
52 LONG srcx, srcy;
53 LONG destx, desty;
56 #ifndef __AROS__
58 /* A BltBitMaskPort() replacement which blits masks for interleaved bitmaps
59 correctly */
60 #ifndef _DCC
61 VOID MyBltMaskBitMap(CONST struct BitMap *srcBitMap, LONG xSrc, LONG ySrc,
62 struct BitMap *destBitMap, LONG xDest, LONG yDest, LONG xSize,
63 LONG ySize, struct BitMap *maskBitMap)
65 BltBitMap(srcBitMap, xSrc, ySrc, destBitMap, xDest, yDest, xSize, ySize,
66 0x99, ~0, NULL);
67 BltBitMap(maskBitMap, xSrc, ySrc, destBitMap, xDest, yDest, xSize,
68 ySize, 0xe2, ~0, NULL);
69 BltBitMap(srcBitMap, xSrc, ySrc, destBitMap, xDest, yDest, xSize, ySize,
70 0x99, ~0, NULL);
72 #endif
74 ASM void HookFunc_BltMask(REG(a0, struct Hook *hook), REG(a1,
75 struct LayerHookMsg *msg), REG(a2, struct RastPort *rp))
77 struct BltMaskHook *h = (struct BltMaskHook *)hook;
79 LONG width = msg->bounds.MaxX - msg->bounds.MinX + 1;
80 LONG height = msg->bounds.MaxY - msg->bounds.MinY + 1;
81 LONG offsetx = h->srcx + msg->offsetx - h->destx;
82 LONG offsety = h->srcy + msg->offsety - h->desty;
84 #ifdef __SASC
85 putreg(REG_A4, (long)hook->h_Data);
86 #endif
88 MyBltMaskBitMap(h->srcBitMap, offsetx, offsety, rp->BitMap,
89 msg->bounds.MinX, msg->bounds.MinY, width, height, &h->maskBitMap);
92 VOID MyBltMaskBitMapRastPort(struct BitMap *srcBitMap, LONG xSrc, LONG ySrc,
93 struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize,
94 ULONG minterm, APTR bltMask)
96 if (GetBitMapAttr(srcBitMap, BMA_FLAGS) & BMF_INTERLEAVED)
98 LONG src_depth = GetBitMapAttr(srcBitMap, BMA_DEPTH);
99 struct Rectangle rect;
100 struct BltMaskHook hook;
102 /* Define the destination rectangle in the rastport */
103 rect.MinX = xDest;
104 rect.MinY = yDest;
105 rect.MaxX = xDest + xSize - 1;
106 rect.MaxY = yDest + ySize - 1;
108 /* Initialize the hook */
109 hook.hook.h_Entry = (HOOKFUNC) HookFunc_BltMask;
110 #ifdef __SASC
111 hook.hook.h_Data = (void *)getreg(REG_A4);
112 #endif
113 hook.srcBitMap = srcBitMap;
114 hook.srcx = xSrc;
115 hook.srcy = ySrc;
116 hook.destx = xDest;
117 hook.desty = yDest;
119 /* Initialize a bitmap where all plane pointers points to the mask */
120 InitBitMap(&hook.maskBitMap, src_depth, GetBitMapAttr(srcBitMap,
121 BMA_WIDTH), GetBitMapAttr(srcBitMap, BMA_HEIGHT));
122 while (src_depth)
123 hook.maskBitMap.Planes[--src_depth] = bltMask;
125 /* Blit onto the Rastport */
126 DoHookClipRects(&hook.hook, destRP, &rect);
128 else
130 BltMaskBitMapRastPort(srcBitMap, xSrc, ySrc, destRP, xDest, yDest,
131 xSize, ySize, minterm, bltMask);
135 #endif
138 static Object *LoadPicture(CONST_STRPTR filename, struct Screen *scr)
140 Object *o;
142 struct Process *myproc = (struct Process *)FindTask(NULL);
143 APTR oldwindowptr = myproc->pr_WindowPtr;
144 myproc->pr_WindowPtr = (APTR) - 1;
146 o = NewDTObject((APTR) filename,
147 DTA_GroupID, GID_PICTURE,
148 OBP_Precision, PRECISION_EXACT,
149 PDTA_Screen, (IPTR) scr,
150 PDTA_DestMode, PMODE_V43, PDTA_UseFriendBitMap, TRUE, TAG_DONE);
152 myproc->pr_WindowPtr = oldwindowptr;
153 D(bug("... picture=%lx\n", o));
155 if (o)
157 struct BitMapHeader *bmhd;
159 GetDTAttrs(o, PDTA_BitMapHeader, (IPTR) & bmhd, TAG_DONE);
160 if (bmhd->bmh_Masking == mskHasAlpha)
162 if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) >= 15)
164 SetAttrs(o, PDTA_FreeSourceBitMap, FALSE,
165 PDTA_Remap, FALSE, TAG_DONE);
169 struct FrameInfo fri = { 0 };
171 D(bug("DTM_FRAMEBOX\n", o));
172 DoMethod(o, DTM_FRAMEBOX, NULL, (IPTR) & fri, (IPTR) & fri,
173 sizeof(struct FrameInfo), 0);
175 if (fri.fri_Dimensions.Depth > 0)
177 D(bug("DTM_PROCLAYOUT\n", o));
178 if (DoMethod(o, DTM_PROCLAYOUT, NULL, 1))
180 return o;
183 DisposeDTObject(o);
185 return NULL;
189 void dt_init(void)
193 void dt_cleanup(void)
198 char *allocPath(const char *str)
200 const char *s0, *s1;
201 char *s;
202 int l;
204 s = NULL;
205 s0 = str;
207 s1 = PathPart(str);
208 if (s1)
210 for (l = 0; s0 != s1; s0++, l++);
211 s = AllocVec(l + 1, MEMF_CLEAR);
212 if (s)
213 strncpy(s, str, l);
215 return s;
218 void freeString(char *str)
220 if (str)
221 FreeVec(str);
224 char *SkipChars(char *v)
226 char *c;
228 c = strstr(v, "=");
229 return ++c;
232 int GetInt(char *v)
234 char *c;
235 c = SkipChars(v);
236 return atol(c);
239 BOOL GetBool(char *v, char *id)
241 if (strstr(v, id))
242 return TRUE;
243 else
244 return FALSE;
247 void GetIntegers(char *v, int *v1, int *v2)
249 char *c;
250 char va1[32], va2[32];
251 int cnt;
252 c = SkipChars(v);
253 if (c)
255 cnt = sscanf(c, "%s %s", va1, va2);
256 if (cnt == 1)
258 *v1 = -1;
259 *v2 = atol(va1);
261 else if (cnt == 2)
263 *v1 = atol(va1);
264 *v2 = atol(va2);
269 /* Function: Create a new Image with the specified dimensions
270 * Input: UWORD w, h:
271 * width and height ofthe wished Image
272 * Output: NewImage:
273 * Pointer to the Created image or NULL
274 * Bugs: Not known yet
275 * NOTES: Function will only return non-NULL if all allocations could be done
276 * so you have not to check something inside the NewImage structure
278 struct NewImage *NewImageContainer(UWORD w, UWORD h)
281 struct NewImage *ni;
283 ni = AllocVec(sizeof(struct NewImage), MEMF_ANY | MEMF_CLEAR);
284 if (ni)
286 ni->w = w;
287 ni->h = h;
288 ni->data = AllocVec(w * h * 4, MEMF_ANY | MEMF_CLEAR);
289 if (ni->data == NULL)
291 FreeVec(ni);
292 ni = NULL;
295 return ni;
298 /* Function: Remove all Memory used by an Image
299 * Input: NewImage ni:
300 * Pointer to an Image to be deallocated
301 * Bugs: Not known
303 void DisposeImageContainer(struct NewImage *ni)
306 if (ni)
308 if (ni->data)
310 FreeVec(ni->data);
312 if (ni->o != NULL)
313 DisposeDTObject(ni->o);
314 FreeVec(ni);
318 /* Function: Load an Image from a file
319 * Input: char name:
320 * Filename of the Image to load
321 * Output: NewImage:
322 * Pointer to the Created image or NULL
323 * Bugs: Not known yet
324 * NOTES: Function will only return non-NULL if all allocations could be done
325 * so you have not to check something inside the NewImage struct.
326 * This function uses DataTypes for loading images, so be sure to have
327 * the specific DataTypes installed
329 struct NewImage *GetImageFromFile(char *name, struct Screen *scr)
332 struct BitMapHeader *bmhd = NULL;
333 struct NewImage *ni;
335 struct pdtBlitPixelArray pa;
336 Object *pic;
337 UWORD w, h;
338 ULONG a, depth;
339 UBYTE mask;
340 ni = NULL;
342 pic = NewDTObject(name, DTA_SourceType, DTST_FILE,
343 DTA_GroupID, GID_PICTURE,
344 PDTA_Remap, FALSE, PDTA_DestMode, PMODE_V43, TAG_DONE);
345 if (pic)
347 get(pic, PDTA_BitMapHeader, &bmhd);
348 if (bmhd)
350 w = bmhd->bmh_Width;
351 h = bmhd->bmh_Height;
352 mask = bmhd->bmh_Masking;
353 ni = NewImageContainer(w, h);
354 if (ni)
356 pa.MethodID = PDTM_READPIXELARRAY;
357 pa.pbpa_PixelData = (APTR) ni->data;
358 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
359 pa.pbpa_PixelArrayMod = w * 4;
360 pa.pbpa_Left = 0;
361 pa.pbpa_Top = 0;
362 pa.pbpa_Width = w;
363 pa.pbpa_Height = h;
364 DoMethodA(pic, (Msg) & pa);
365 if (mask != mskHasAlpha)
367 #if !AROS_BIG_ENDIAN
368 for (a = 0; a < (w * h); a++)
369 ni->data[a] |= 0x000000ff;
370 #else
371 for (a = 0; a < (w * h); a++)
372 ni->data[a] |= 0xff000000;
373 #endif
375 if (scr != NULL)
377 depth = (ULONG) GetBitMapAttr(&scr->BitMap, BMA_DEPTH);
379 if (depth < 15)
380 ni->o = LoadPicture(name, scr);
381 if (ni->o != NULL)
383 GetDTAttrs(ni->o, PDTA_DestBitMap,
384 (IPTR) & ni->bitmap, TAG_DONE);
385 if (ni->bitmap == NULL)
386 GetDTAttrs(ni->o, PDTA_BitMap,
387 (IPTR) & ni->bitmap, TAG_DONE);
389 if (ni->bitmap)
390 GetDTAttrs(ni->o, PDTA_MaskPlane,
391 (IPTR) & ni->mask, TAG_DONE);
396 DisposeDTObject(pic);
398 return ni;
403 BOOL ReadPropConfig(struct dt_node * data, struct Screen * scr)
406 char buffer[256];
407 char *line, *v;
408 BPTR file;
410 file = Open(data->filename, MODE_OLDFILE);
411 if (file)
415 line = FGets(file, buffer, 256);
416 if (line)
418 if ((v = strstr(line, "ContainerTop ")) == line)
420 GetIntegers(v, &data->ContainerTop_o,
421 &data->ContainerTop_s);
423 else if ((v = strstr(line, "ContainerVertTile ")) == line)
425 GetIntegers(v, &data->ContainerVertTile_o,
426 &data->ContainerVertTile_s);
428 else if ((v = strstr(line, "KnobTop ")) == line)
430 GetIntegers(v, &data->KnobTop_o, &data->KnobTop_s);
432 else if ((v = strstr(line, "KnobTileTop ")) == line)
434 GetIntegers(v, &data->KnobTileTop_o,
435 &data->KnobTileTop_s);
437 else if ((v = strstr(line, "KnobVertGripper ")) == line)
439 GetIntegers(v, &data->KnobVertGripper_o,
440 &data->KnobVertGripper_s);
442 else if ((v = strstr(line, "KnobTileBottom ")) == line)
444 GetIntegers(v, &data->KnobTileBottom_o,
445 &data->KnobTileBottom_s);
447 else if ((v = strstr(line, "KnobBottom ")) == line)
449 GetIntegers(v, &data->KnobBottom_o,
450 &data->KnobBottom_s);
452 else if ((v = strstr(line, "ContainerBottom ")) == line)
454 GetIntegers(v, &data->ContainerBottom_o,
455 &data->ContainerBottom_s);
457 else if ((v = strstr(line, "ContainerLeft ")) == line)
459 GetIntegers(v, &data->ContainerLeft_o,
460 &data->ContainerLeft_s);
462 else if ((v = strstr(line, "ContainerHorTile ")) == line)
464 GetIntegers(v, &data->ContainerHorTile_o,
465 &data->ContainerHorTile_s);
467 else if ((v = strstr(line, "KnobLeft ")) == line)
469 GetIntegers(v, &data->KnobLeft_o, &data->KnobLeft_s);
471 else if ((v = strstr(line, "KnobTileLeft ")) == line)
473 GetIntegers(v, &data->KnobTileLeft_o,
474 &data->KnobTileLeft_s);
476 else if ((v = strstr(line, "KnobHorGripper ")) == line)
478 GetIntegers(v, &data->KnobHorGripper_o,
479 &data->KnobHorGripper_s);
481 else if ((v = strstr(line, "KnobTileRight ")) == line)
483 GetIntegers(v, &data->KnobTileRight_o,
484 &data->KnobTileRight_s);
486 else if ((v = strstr(line, "KnobRight ")) == line)
488 GetIntegers(v, &data->KnobRight_o, &data->KnobRight_s);
490 else if ((v = strstr(line, "ContainerRight ")) == line)
492 GetIntegers(v, &data->ContainerRight_o,
493 &data->ContainerRight_s);
497 while (line);
498 Close(file);
500 STRPTR path = allocPath(data->filename);
501 if (path)
503 BPTR lock = Lock(path, ACCESS_READ);
504 if (lock)
506 BPTR oldcd = CurrentDir(lock);
507 data->img_verticalcontainer =
508 GetImageFromFile("Container/Vertical", scr);
509 data->img_verticalknob = GetImageFromFile("Knob/Vertical", scr);
510 data->img_horizontalcontainer =
511 GetImageFromFile("Container/Horizontal", scr);
512 data->img_horizontalknob =
513 GetImageFromFile("Knob/Horizontal", scr);
514 data->img_up = GetImageFromFile("ArrowUp/default", scr);
515 data->img_down = GetImageFromFile("ArrowDown/default", scr);
516 data->img_left = GetImageFromFile("ArrowLeft/default", scr);
517 data->img_right = GetImageFromFile("ArrowRight/default", scr);
519 CurrentDir(oldcd);
520 UnLock(lock);
523 freeString(path);
526 if (data->img_horizontalcontainer && data->img_horizontalknob
527 && data->img_verticalcontainer && data->img_verticalknob
528 && data->img_up && data->img_down && data->img_left
529 && data->img_right)
530 return TRUE;
531 return FALSE;
534 void FreePropConfig(struct dt_node *data)
536 DisposeImageContainer(data->img_verticalcontainer);
537 DisposeImageContainer(data->img_verticalknob);
538 DisposeImageContainer(data->img_horizontalcontainer);
539 DisposeImageContainer(data->img_horizontalknob);
540 DisposeImageContainer(data->img_up);
541 DisposeImageContainer(data->img_down);
542 DisposeImageContainer(data->img_left);
543 DisposeImageContainer(data->img_right);
547 BOOL ReadFrameConfig(CONST_STRPTR filename, struct dt_frame_image *fi,
548 struct Screen *scr)
551 char buffer[256];
552 char *line, *v;
553 BPTR file;
555 fi->noalpha = FALSE;
557 file = Open(filename, MODE_OLDFILE);
558 if (file)
562 line = FGets(file, buffer, 256);
563 if (line)
565 if ((v = strstr(line, "TileLeft ")) == line)
567 fi->tile_left = GetInt(v);
569 else if ((v = strstr(line, "TileTop ")) == line)
571 fi->tile_top = GetInt(v);
573 else if ((v = strstr(line, "TileRight ")) == line)
575 fi->tile_right = GetInt(v);
577 else if ((v = strstr(line, "TileBottom ")) == line)
579 fi->tile_bottom = GetInt(v);
581 else if ((v = strstr(line, "InnerLeft ")) == line)
583 fi->inner_left = GetInt(v);
585 else if ((v = strstr(line, "InnerTop ")) == line)
587 fi->inner_top = GetInt(v);
589 else if ((v = strstr(line, "InnerRight ")) == line)
591 fi->inner_right = GetInt(v);
593 else if ((v = strstr(line, "InnerBottom ")) == line)
595 fi->inner_bottom = GetInt(v);
597 else if ((v = strstr(line, "NoAlpha ")) == line)
599 fi->noalpha = GetBool(v, "Yes");
603 while (line);
604 Close(file);
607 STRPTR path = allocPath(filename);
608 if (path)
610 BPTR lock = Lock(path, ACCESS_READ);
611 if (lock)
613 BPTR oldcd = CurrentDir(lock);
614 fi->img_up = GetImageFromFile("up/default", scr);
615 fi->img_down = GetImageFromFile("down/default", scr);
617 CurrentDir(oldcd);
618 UnLock(lock);
621 freeString(path);
623 if (fi->img_up && fi->img_down)
624 return TRUE;
625 return FALSE;
628 void FreeFrameConfig(struct dt_frame_image *fi)
630 if (fi != NULL)
632 DisposeImageContainer(fi->img_up);
633 DisposeImageContainer(fi->img_down);
637 void dispose_custom_frame(struct dt_frame_image *fi)
639 if (fi != NULL)
641 FreeFrameConfig(fi);
642 FreeVec(fi);
646 struct dt_frame_image *load_custom_frame(CONST_STRPTR filename,
647 struct Screen *scr)
649 struct dt_frame_image *fi =
650 AllocVec(sizeof(struct dt_frame_image), MEMF_ANY);
652 if (fi)
654 /* special configuration image for prop gadgets */
655 if (Stricmp(FilePart(filename), "frame.config") == 0)
657 if (ReadFrameConfig(filename, fi, scr))
659 return fi;
661 else
663 FreeFrameConfig(fi);
664 FreeVec(fi);
665 return NULL;
668 FreeVec(fi);
670 return NULL;
673 struct dt_node *dt_load_picture(CONST_STRPTR filename, struct Screen *scr)
675 struct dt_node *node;
676 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
677 if (!dt_initialized)
679 NewList(&dt_list);
680 dt_initialized = 1;
683 node = List_First(&dt_list);
684 while (node)
686 if (!Stricmp(filename, node->filename) && scr == node->scr)
688 node->count++;
689 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
690 return node;
692 node = Node_Next(node);
695 if ((node =
696 (struct dt_node *)AllocVec(sizeof(struct dt_node), MEMF_CLEAR)))
699 if ((node->filename = StrDup(filename)))
701 /* create the datatypes object */
702 D(bug("loading %s\n", filename));
704 /* special configuration image for prop gadgets */
705 if ((Stricmp(FilePart(filename), "prop.config") == 0)
706 || (Stricmp(FilePart(filename), "config") == 0))
708 if (ReadPropConfig(node, scr))
711 node->mode = MODE_PROP;
712 node->scr = scr;
713 node->count = 1;
714 AddTail((struct List *)&dt_list, (struct Node *)node);
715 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
716 return node;
718 else
720 FreePropConfig(node);
723 else
725 if ((node->o = LoadPicture(filename, scr)))
727 struct BitMapHeader *bmhd;
728 GetDTAttrs(node->o, PDTA_BitMapHeader, (IPTR) & bmhd,
729 TAG_DONE);
730 D(bug("picture %lx\n", node->o));
732 if (bmhd)
734 node->width = bmhd->bmh_Width;
735 node->height = bmhd->bmh_Height;
736 node->mask = bmhd->bmh_Masking;
737 D(bug("picture %lx = %ldx%ld\n", node->o,
738 node->width, node->height));
740 node->scr = scr;
741 node->count = 1;
742 AddTail((struct List *)&dt_list, (struct Node *)node);
743 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
744 return node;
747 FreeVec(node->filename);
749 FreeVec(node);
751 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
752 return NULL;
755 void dt_dispose_picture(struct dt_node *node)
757 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
758 if (node && node->count)
760 node->count--;
761 if (!node->count)
763 Remove((struct Node *)node);
764 if (node->mode == MODE_PROP)
765 FreePropConfig(node);
766 else
767 DisposeDTObject(node->o);
768 FreeVec(node->filename);
769 FreeVec(node);
772 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
775 int dt_width(struct dt_node *node)
777 if (node)
778 return node->width;
779 else
780 return 0;
783 int dt_height(struct dt_node *node)
785 if (node)
786 return node->height;
787 else
788 return 0;
792 void dt_put_on_rastport(struct dt_node *node, struct RastPort *rp, int x,
793 int y)
795 struct BitMap *bitmap = NULL;
796 struct pdtBlitPixelArray pa;
797 ULONG *img;
798 Object *o;
799 IPTR depth;
801 o = node->o;
802 if (NULL == o)
803 return;
805 depth = GetBitMapAttr(rp->BitMap, BMA_DEPTH);
807 if (depth > 8 && node->mask == mskHasAlpha)
809 img =
810 (ULONG *) AllocVec(dt_width(node) * dt_height(node) * 4,
811 MEMF_ANY);
812 if (img)
814 pa.MethodID = PDTM_READPIXELARRAY;
815 pa.pbpa_PixelData = (UBYTE *) img;
816 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
817 pa.pbpa_PixelArrayMod = dt_width(node) * 4;
818 pa.pbpa_Left = 0;
819 pa.pbpa_Top = 0;
820 pa.pbpa_Width = dt_width(node);
821 pa.pbpa_Height = dt_height(node);
822 DoMethodA(o, (Msg) & pa);
823 WritePixelArrayAlpha(img, 0, 0, dt_width(node) * 4, rp, x, y,
824 dt_width(node), dt_height(node), 0xffffffff);
825 FreeVec((APTR) img);
828 else
830 GetDTAttrs(o, PDTA_DestBitMap, (IPTR) & bitmap, TAG_DONE);
831 if (NULL == bitmap)
832 GetDTAttrs(o, PDTA_BitMap, (IPTR) & bitmap, TAG_DONE);
834 if (bitmap)
836 APTR mask = NULL;
838 GetDTAttrs(o, PDTA_MaskPlane, (IPTR) & mask, TAG_DONE);
839 if (mask)
841 #ifndef __AROS__
842 MyBltMaskBitMapRastPort(bitmap, 0, 0, rp, x, y,
843 dt_width(node), dt_height(node), 0xe0, (PLANEPTR) mask);
844 #else
845 BltMaskBitMapRastPort(bitmap, 0, 0, rp, x, y,
846 dt_width(node), dt_height(node), 0xe0, (PLANEPTR) mask);
847 #endif
849 else
850 BltBitMapRastPort(bitmap, 0, 0, rp, x, y,
851 dt_width(node), dt_height(node), 0xc0);
856 void dt_put_mim_on_rastport(struct dt_node *node, struct RastPort *rp,
857 int x, int y, int state)
859 struct BitMap *bitmap = NULL;
860 struct pdtBlitPixelArray pa;
861 ULONG *img;
863 Object *o;
865 o = node->o;
866 if (NULL == o)
867 return;
868 int width = dt_width(node) >> 1;
869 if (node->mask == mskHasAlpha)
871 img =
872 (ULONG *) AllocVec(dt_width(node) * dt_height(node) * 4,
873 MEMF_ANY);
874 if (img)
877 int height = dt_height(node);
878 pa.MethodID = PDTM_READPIXELARRAY;
879 pa.pbpa_PixelData = (UBYTE *) img;
880 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
881 pa.pbpa_PixelArrayMod = width * 4;
882 pa.pbpa_Left = state * width;
883 pa.pbpa_Top = 0;
884 pa.pbpa_Width = width;
885 pa.pbpa_Height = height;
886 DoMethodA(o, (Msg) & pa);
887 WritePixelArrayAlpha(img, 0, 0, width * 4, rp, x, y, width,
888 height, 0xffffffff);
889 FreeVec((APTR) img);
892 else
894 GetDTAttrs(o, PDTA_DestBitMap, (IPTR) & bitmap, TAG_DONE);
895 if (NULL == bitmap)
896 GetDTAttrs(o, PDTA_BitMap, (IPTR) & bitmap, TAG_DONE);
899 if (bitmap)
901 APTR mask = NULL;
903 GetDTAttrs(o, PDTA_MaskPlane, (IPTR) & mask, TAG_DONE);
904 if (mask)
906 #ifndef __AROS__
907 MyBltMaskBitMapRastPort(bitmap, width * state, 0, rp, x, y,
908 width, dt_height(node), 0xe0, (PLANEPTR) mask);
909 #else
910 BltMaskBitMapRastPort(bitmap, width * state, 0, rp, x, y,
911 width, dt_height(node), 0xe0, (PLANEPTR) mask);
912 #endif
914 else
915 BltBitMapRastPort(bitmap, width * state, 0, rp, x, y,
916 width, dt_height(node), 0xc0);
923 #define RECTSIZEX(r) ((r)->MaxX-(r)->MinX+1)
924 #define RECTSIZEY(r) ((r)->MaxY-(r)->MinY+1)
926 #define MOD(x,y) ((x)<0 ? (y)-((-(x))%(y)) : (x)%(y))
928 struct BackFillMsg
930 struct Layer *Layer;
931 struct Rectangle Bounds;
932 LONG OffsetX;
933 LONG OffsetY;
936 struct BackFillOptions
938 WORD MaxCopyWidth; // maximum width for the copy
939 WORD MaxCopyHeight; // maximum height for the copy
940 // BOOL CenterX; // center the tiles horizontally?
941 // BOOL CenterY; // center the tiles vertically?
942 WORD OffsetX; // offset to add
943 WORD OffsetY; // offset to add
944 BOOL OffsetTitleY; // add the screen titlebar height to the vertical offset?
947 struct BackFillInfo
949 struct Hook Hook;
950 WORD Width;
951 WORD Height;
952 struct BitMap *BitMap;
953 /* struct Screen *Screen; */ /* Needed for centering */
954 WORD CopyWidth;
955 WORD CopyHeight;
956 struct BackFillOptions Options;
957 WORD OffsetX;
958 WORD OffsetY;
962 static void CopyTiledBitMap(struct BitMap *Src, WORD SrcOffsetX,
963 WORD SrcOffsetY, WORD SrcSizeX, WORD SrcSizeY, struct BitMap *Dst,
964 struct Rectangle *DstBounds)
966 WORD FirstSizeX; // the width of the rectangle to blit as the first column
967 WORD FirstSizeY; // the height of the rectangle to blit as the first row
968 WORD SecondMinX; // the left edge of the second column
969 WORD SecondMinY; // the top edge of the second column
970 WORD SecondSizeX; // the width of the second column
971 WORD SecondSizeY; // the height of the second column
972 WORD Pos; // used as starting position in the "exponential" blit
973 WORD Size; // used as bitmap size in the "exponential" blit
975 // the width of the first tile, this is either the rest of the tile right
976 // to SrcOffsetX or the width of the dest rect, if the rect is narrow
977 FirstSizeX = MIN(SrcSizeX - SrcOffsetX, RECTSIZEX(DstBounds));
979 // the start for the second tile (if used)
980 SecondMinX = DstBounds->MinX + FirstSizeX;
982 // the width of the second tile (we want the whole tile to be SrcSizeX
983 // pixels wide, if we use SrcSizeX-SrcOffsetX pixels for the left part
984 // we'll use SrcOffsetX for the right part)
985 SecondSizeX = MIN(SrcOffsetX, DstBounds->MaxX - SecondMinX + 1);
987 // the same values are calculated for y direction
988 FirstSizeY = MIN(SrcSizeY - SrcOffsetY, RECTSIZEY(DstBounds));
989 SecondMinY = DstBounds->MinY + FirstSizeY;
990 SecondSizeY = MIN(SrcOffsetY, DstBounds->MaxY - SecondMinY + 1);
992 // blit the first piece of the tile
993 BltBitMap(Src, SrcOffsetX, SrcOffsetY, Dst, DstBounds->MinX,
994 DstBounds->MinY, FirstSizeX, FirstSizeY, 0xC0, -1, NULL);
996 // if SrcOffset was 0 or the dest rect was to narrow, we won't need a
997 // second column
998 if (SecondSizeX > 0)
999 BltBitMap(Src, 0, SrcOffsetY, Dst, SecondMinX, DstBounds->MinY,
1000 SecondSizeX, FirstSizeY, 0xC0, -1, NULL);
1002 // is a second row necessary?
1003 if (SecondSizeY > 0)
1005 BltBitMap(Src, SrcOffsetX, 0, Dst, DstBounds->MinX, SecondMinY,
1006 FirstSizeX, SecondSizeY, 0xC0, -1, NULL);
1007 if (SecondSizeX > 0)
1008 BltBitMap(Src, 0, 0, Dst, SecondMinX, SecondMinY, SecondSizeX,
1009 SecondSizeY, 0xC0, -1, NULL);
1012 // this loop generates the first row of the tiles
1013 for (Pos = DstBounds->MinX + SrcSizeX, Size =
1014 MIN(SrcSizeX, DstBounds->MaxX - Pos + 1); Pos <= DstBounds->MaxX;)
1016 BltBitMap(Dst, DstBounds->MinX, DstBounds->MinY, Dst, Pos,
1017 DstBounds->MinY, Size, MIN(SrcSizeY, RECTSIZEY(DstBounds)),
1018 0xC0, -1, NULL);
1019 Pos += Size;
1020 Size = MIN(Size << 1, DstBounds->MaxX - Pos + 1);
1023 // this loop blit the first row down several times to fill the whole
1024 // dest rect
1025 for (Pos = DstBounds->MinY + SrcSizeY, Size =
1026 MIN(SrcSizeY, DstBounds->MaxY - Pos + 1); Pos <= DstBounds->MaxY;)
1028 BltBitMap(Dst, DstBounds->MinX, DstBounds->MinY, Dst,
1029 DstBounds->MinX, Pos, RECTSIZEX(DstBounds), Size, 0xC0, -1,
1030 NULL);
1031 Pos += Size;
1032 Size = MIN(Size << 1, DstBounds->MaxY - Pos + 1);
1036 AROS_UFH3S(void, WindowPatternBackFillFunc,
1037 AROS_UFHA(struct Hook *, Hook, A0),
1038 AROS_UFHA(struct RastPort *, RP, A2),
1039 AROS_UFHA(struct BackFillMsg *, BFM, A1))
1041 AROS_USERFUNC_INIT
1043 WORD OffsetX; // the offset within the tile in x direction
1044 WORD OffsetY; // the offset within the tile in y direction
1046 // get the data for our backfillhook
1047 struct BackFillInfo *BFI = (struct BackFillInfo *)Hook;
1049 #ifdef __SASC
1050 putreg(12, (long)Hook->h_Data);
1051 #endif
1053 // The first tile normally isn't totally visible => calculate the offset
1054 // (offset 0 would mean that the left edge of the damage rectangle
1055 // coincides with the left edge of a tile)
1056 OffsetX = BFM->Bounds.MinX - BFI->Options.OffsetX;
1057 // if (BFI->Options.CenterX) // horizontal centering?
1058 // OffsetX -= (BFI->Screen->Width-BFI->Width)/2;
1060 // The same values are calculated for y direction
1061 OffsetY = BFM->Bounds.MinY - BFI->Options.OffsetY;
1064 if (BFI->Options.OffsetTitleY) // shift the tiles down?
1065 OffsetY -= BFI->Screen->BarHeight+1;
1068 // if (BFI->Options.CenterY) // horizontal centering?
1069 // OffsetY -= (BFI->Screen->Height - BFI->Height)/2;
1071 CopyTiledBitMap(BFI->BitMap, MOD(OffsetX + BFI->OffsetX, BFI->Width),
1072 MOD(OffsetY + BFI->OffsetY, BFI->Height), BFI->CopyWidth,
1073 BFI->CopyHeight, RP->BitMap, &BFM->Bounds);
1075 AROS_USERFUNC_EXIT
1078 static void CalculateCopySizes(struct BackFillInfo *BFI)
1080 BFI->CopyWidth =
1081 (BFI->Width >
1082 BFI->Options.MaxCopyWidth) ? BFI->Width : BFI->Options.
1083 MaxCopyWidth - BFI->Options.MaxCopyWidth % BFI->Width;
1084 BFI->CopyHeight =
1085 (BFI->Height >
1086 BFI->Options.MaxCopyHeight) ? BFI->Height : BFI->Options.
1087 MaxCopyHeight - BFI->Options.MaxCopyHeight % BFI->Height;
1091 **********************************************************/
1092 void dt_put_on_rastport_tiled(struct dt_node *node, struct RastPort *rp,
1093 int x1, int y1, int x2, int y2, int xoffset, int yoffset)
1095 struct Screen *scr = node->scr;
1096 struct BitMap *bitmap;
1097 Object *o;
1099 o = node->o;
1100 if (!o)
1101 return;
1103 GetDTAttrs(o, PDTA_DestBitMap, (IPTR) & bitmap, TAG_DONE);
1104 if (NULL == bitmap)
1105 GetDTAttrs(o, PDTA_BitMap, (IPTR) & bitmap, TAG_DONE);
1106 if (NULL == bitmap)
1107 return;
1109 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
1111 if (!node->bfi)
1113 struct BackFillInfo *bfi =
1114 (struct BackFillInfo *)AllocVec(sizeof(struct BackFillInfo),
1115 MEMF_CLEAR);
1116 if (bfi)
1118 LONG depth = GetBitMapAttr(bitmap, BMA_DEPTH);
1119 bfi->Hook.h_Entry = (HOOKFUNC) WindowPatternBackFillFunc;
1120 #ifdef __SASC
1121 bfi->Hook.h_Data = (APTR) getreg(12); /* register A4 */
1122 #endif
1124 bfi->Options.MaxCopyWidth = 256;
1125 bfi->Options.MaxCopyHeight = 256;
1126 // bfi->Options.CenterX = FALSE; /* center the tiles horizontally? */
1127 // bfi->Options.CenterY = FALSE; /* center the tiles vertically? */
1128 bfi->Options.OffsetX = 0; /* offset to add */
1129 bfi->Options.OffsetY = 0; /* offset to add */
1131 /* add the screen titlebar height to the vertical offset? */
1132 bfi->Options.OffsetTitleY = TRUE;
1133 bfi->Width = dt_width(node);
1134 bfi->Height = dt_height(node);
1136 CalculateCopySizes(bfi);
1138 if ((bfi->BitMap =
1139 AllocBitMap(bfi->CopyWidth, bfi->CopyHeight, depth,
1140 BMF_INTERLEAVED | BMF_MINPLANES,
1141 scr->RastPort.BitMap)))
1143 struct Rectangle CopyBounds;
1144 CopyBounds.MinX = 0;
1145 CopyBounds.MinY = 0;
1146 CopyBounds.MaxX = bfi->CopyWidth - 1;
1147 CopyBounds.MaxY = bfi->CopyHeight - 1;
1149 CopyTiledBitMap(bitmap, 0, 0, bfi->Width, bfi->Height,
1150 bfi->BitMap, &CopyBounds);
1153 node->bfi = bfi;
1156 if (node->bfi)
1158 struct BackFillInfo *bfi = node->bfi;
1159 struct Rectangle rect;
1161 rect.MinX = x1;
1162 rect.MinY = y1;
1163 rect.MaxX = x2;
1164 rect.MaxY = y2;
1166 if (rp->Layer)
1168 LockLayer(0, rp->Layer);
1169 xoffset -= rp->Layer->bounds.MinX;
1170 yoffset -= rp->Layer->bounds.MinY;
1173 bfi->OffsetX = xoffset;
1174 bfi->OffsetY = yoffset;
1176 DoHookClipRects((struct Hook *)bfi, rp, &rect);
1178 if (rp->Layer)
1180 UnlockLayer(rp->Layer);
1183 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);