aome further corrections to copyright notices.
[AROS.git] / workbench / libs / muimaster / datatypescache.c
blobfb5dae7b9fbb3ad27d6d436deea58b4a9e685c6a
1 /*
2 Copyright © 2002-2013, The AROS Development Team. All rights reserved.
4 $Id$
5 */
7 #include <ctype.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <stdio.h>
12 #define DT_V44_SUPPORT
14 #include <datatypes/pictureclass.h>
16 #include <clib/alib_protos.h>
17 #include <proto/exec.h>
18 #include <proto/dos.h>
19 #include <proto/datatypes.h>
20 #include <proto/graphics.h>
21 #include <proto/intuition.h>
22 #include <proto/utility.h>
23 #include <proto/layers.h>
24 #include <proto/cybergraphics.h>
26 //#define MYDEBUG 1
27 #include "debug.h"
28 #include "support.h"
29 #include "muimaster_intern.h"
30 #include "datatypescache.h"
32 extern struct Library *MUIMasterBase;
34 static struct List dt_list;
35 static int dt_initialized;
38 struct LayerHookMsg
40 STACKED struct Layer *layer;
41 STACKED struct Rectangle bounds;
42 STACKED LONG offsetx;
43 STACKED LONG offsety;
46 struct BltMaskHook
48 struct Hook hook;
49 struct BitMap maskBitMap;
50 struct BitMap *srcBitMap;
51 LONG srcx, srcy;
52 LONG destx, desty;
55 #define RECTSIZEX(r) ((r)->MaxX-(r)->MinX+1)
56 #define RECTSIZEY(r) ((r)->MaxY-(r)->MinY+1)
58 #define MOD(x,y) ((x)<0 ? (y)-((-(x))%(y)) : (x)%(y))
60 struct BackFillMsg
62 struct Layer *Layer;
63 struct Rectangle Bounds;
64 LONG OffsetX;
65 LONG OffsetY;
68 struct BackFillOptions
70 WORD MaxCopyWidth; // maximum width for the copy
71 WORD MaxCopyHeight; // maximum height for the copy
72 // BOOL CenterX; // center the tiles horizontally?
73 // BOOL CenterY; // center the tiles vertically?
74 WORD OffsetX; // offset to add
75 WORD OffsetY; // offset to add
76 BOOL OffsetTitleY; // add the screen titlebar height to the vertical offset?
79 struct BackFillInfo
81 struct Hook Hook;
82 WORD Width;
83 WORD Height;
84 struct BitMap *BitMap;
85 /* struct Screen *Screen; */ /* Needed for centering */
86 WORD CopyWidth;
87 WORD CopyHeight;
88 struct BackFillOptions Options;
89 WORD OffsetX;
90 WORD OffsetY;
93 #ifndef __AROS__
95 /* A BltBitMaskPort() replacement which blits masks for interleaved bitmaps
96 correctly */
97 #ifndef _DCC
98 VOID MyBltMaskBitMap(CONST struct BitMap *srcBitMap, LONG xSrc, LONG ySrc,
99 struct BitMap *destBitMap, LONG xDest, LONG yDest, LONG xSize,
100 LONG ySize, struct BitMap *maskBitMap)
102 BltBitMap(srcBitMap, xSrc, ySrc, destBitMap, xDest, yDest, xSize, ySize,
103 0x99, ~0, NULL);
104 BltBitMap(maskBitMap, xSrc, ySrc, destBitMap, xDest, yDest, xSize,
105 ySize, 0xe2, ~0, NULL);
106 BltBitMap(srcBitMap, xSrc, ySrc, destBitMap, xDest, yDest, xSize, ySize,
107 0x99, ~0, NULL);
109 #endif
111 ASM void HookFunc_BltMask(REG(a0, struct Hook *hook), REG(a1,
112 struct LayerHookMsg *msg), REG(a2, struct RastPort *rp))
114 struct BltMaskHook *h = (struct BltMaskHook *)hook;
116 LONG width = msg->bounds.MaxX - msg->bounds.MinX + 1;
117 LONG height = msg->bounds.MaxY - msg->bounds.MinY + 1;
118 LONG offsetx = h->srcx + msg->offsetx - h->destx;
119 LONG offsety = h->srcy + msg->offsety - h->desty;
121 #ifdef __SASC
122 putreg(REG_A4, (long)hook->h_Data);
123 #endif
125 MyBltMaskBitMap(h->srcBitMap, offsetx, offsety, rp->BitMap,
126 msg->bounds.MinX, msg->bounds.MinY, width, height, &h->maskBitMap);
129 VOID MyBltMaskBitMapRastPort(struct BitMap *srcBitMap, LONG xSrc, LONG ySrc,
130 struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize,
131 ULONG minterm, APTR bltMask)
133 if (GetBitMapAttr(srcBitMap, BMA_FLAGS) & BMF_INTERLEAVED)
135 LONG src_depth = GetBitMapAttr(srcBitMap, BMA_DEPTH);
136 struct Rectangle rect;
137 struct BltMaskHook hook;
139 /* Define the destination rectangle in the rastport */
140 rect.MinX = xDest;
141 rect.MinY = yDest;
142 rect.MaxX = xDest + xSize - 1;
143 rect.MaxY = yDest + ySize - 1;
145 /* Initialize the hook */
146 hook.hook.h_Entry = (HOOKFUNC) HookFunc_BltMask;
147 #ifdef __SASC
148 hook.hook.h_Data = (void *)getreg(REG_A4);
149 #endif
150 hook.srcBitMap = srcBitMap;
151 hook.srcx = xSrc;
152 hook.srcy = ySrc;
153 hook.destx = xDest;
154 hook.desty = yDest;
156 /* Initialize a bitmap where all plane pointers points to the mask */
157 InitBitMap(&hook.maskBitMap, src_depth, GetBitMapAttr(srcBitMap,
158 BMA_WIDTH), GetBitMapAttr(srcBitMap, BMA_HEIGHT));
159 while (src_depth)
160 hook.maskBitMap.Planes[--src_depth] = bltMask;
162 /* Blit onto the Rastport */
163 DoHookClipRects(&hook.hook, destRP, &rect);
165 else
167 BltMaskBitMapRastPort(srcBitMap, xSrc, ySrc, destRP, xDest, yDest,
168 xSize, ySize, minterm, bltMask);
172 #endif
175 static Object *LoadPicture(CONST_STRPTR filename, struct Screen *scr)
177 Object *o;
179 struct Process *myproc = (struct Process *)FindTask(NULL);
180 APTR oldwindowptr = myproc->pr_WindowPtr;
181 myproc->pr_WindowPtr = (APTR) - 1;
183 o = NewDTObject((APTR) filename,
184 DTA_GroupID, GID_PICTURE,
185 OBP_Precision, PRECISION_EXACT,
186 PDTA_Screen, (IPTR) scr,
187 PDTA_DestMode, PMODE_V43, PDTA_UseFriendBitMap, TRUE, TAG_DONE);
189 myproc->pr_WindowPtr = oldwindowptr;
190 D(bug("... picture=%lx\n", o));
192 if (o)
194 struct BitMapHeader *bmhd;
196 GetDTAttrs(o, PDTA_BitMapHeader, (IPTR) & bmhd, TAG_DONE);
197 if (bmhd->bmh_Masking == mskHasAlpha)
199 if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) >= 15)
201 SetAttrs(o, PDTA_FreeSourceBitMap, FALSE,
202 PDTA_Remap, FALSE, TAG_DONE);
206 struct FrameInfo fri = { 0 };
208 D(bug("DTM_FRAMEBOX\n", o));
209 DoMethod(o, DTM_FRAMEBOX, NULL, (IPTR) & fri, (IPTR) & fri,
210 sizeof(struct FrameInfo), 0);
212 if (fri.fri_Dimensions.Depth > 0)
214 D(bug("DTM_PROCLAYOUT\n", o));
215 if (DoMethod(o, DTM_PROCLAYOUT, NULL, 1))
217 return o;
220 DisposeDTObject(o);
222 return NULL;
226 void dt_init(void)
230 void dt_cleanup(void)
235 char *allocPath(const char *str)
237 const char *s0, *s1;
238 char *s;
239 int l;
241 s = NULL;
242 s0 = str;
244 s1 = PathPart(str);
245 if (s1)
247 for (l = 0; s0 != s1; s0++, l++);
248 s = AllocVec(l + 1, MEMF_CLEAR);
249 if (s)
250 strncpy(s, str, l);
252 return s;
255 void freeString(char *str)
257 if (str)
258 FreeVec(str);
261 char *SkipChars(char *v)
263 char *c;
265 c = strstr(v, "=");
266 return ++c;
269 int GetInt(char *v)
271 char *c;
272 c = SkipChars(v);
273 return atol(c);
276 BOOL GetBool(char *v, char *id)
278 if (strstr(v, id))
279 return TRUE;
280 else
281 return FALSE;
284 void GetIntegers(char *v, int *v1, int *v2)
286 char *c;
287 char va1[32], va2[32];
288 int cnt;
289 c = SkipChars(v);
290 if (c)
292 cnt = sscanf(c, "%s %s", va1, va2);
293 if (cnt == 1)
295 *v1 = -1;
296 *v2 = atol(va1);
298 else if (cnt == 2)
300 *v1 = atol(va1);
301 *v2 = atol(va2);
306 /* Function: Create a new Image with the specified dimensions
307 * Input: UWORD w, h:
308 * width and height ofthe wished Image
309 * Output: NewImage:
310 * Pointer to the Created image or NULL
311 * Bugs: Not known yet
312 * NOTES: Function will only return non-NULL if all allocations could be done
313 * so you have not to check something inside the NewImage structure
315 struct NewImage *NewImageContainer(UWORD w, UWORD h)
318 struct NewImage *ni;
320 ni = AllocVec(sizeof(struct NewImage), MEMF_ANY | MEMF_CLEAR);
321 if (ni)
323 ni->w = w;
324 ni->h = h;
325 ni->data = AllocVec(w * h * 4, MEMF_ANY | MEMF_CLEAR);
326 if (ni->data == NULL)
328 FreeVec(ni);
329 ni = NULL;
332 return ni;
335 /* Function: Remove all Memory used by an Image
336 * Input: NewImage ni:
337 * Pointer to an Image to be deallocated
338 * Bugs: Not known
340 void DisposeImageContainer(struct NewImage *ni)
343 if (ni)
345 if (ni->data)
347 FreeVec(ni->data);
349 if (ni->o != NULL)
350 DisposeDTObject(ni->o);
351 FreeVec(ni);
355 /* Function: Load an Image from a file
356 * Input: char name:
357 * Filename of the Image to load
358 * Output: NewImage:
359 * Pointer to the Created image or NULL
360 * Bugs: Not known yet
361 * NOTES: Function will only return non-NULL if all allocations could be done
362 * so you have not to check something inside the NewImage struct.
363 * This function uses DataTypes for loading images, so be sure to have
364 * the specific DataTypes installed
366 struct NewImage *GetImageFromFile(char *name, struct Screen *scr)
369 struct BitMapHeader *bmhd = NULL;
370 struct NewImage *ni;
372 struct pdtBlitPixelArray pa;
373 Object *pic;
374 UWORD w, h;
375 ULONG a, depth;
376 UBYTE mask;
377 ni = NULL;
379 pic = NewDTObject(name, DTA_SourceType, DTST_FILE,
380 DTA_GroupID, GID_PICTURE,
381 PDTA_Remap, FALSE, PDTA_DestMode, PMODE_V43, TAG_DONE);
382 if (pic)
384 get(pic, PDTA_BitMapHeader, &bmhd);
385 if (bmhd)
387 w = bmhd->bmh_Width;
388 h = bmhd->bmh_Height;
389 mask = bmhd->bmh_Masking;
390 ni = NewImageContainer(w, h);
391 if (ni)
393 pa.MethodID = PDTM_READPIXELARRAY;
394 pa.pbpa_PixelData = (APTR) ni->data;
395 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
396 pa.pbpa_PixelArrayMod = w * 4;
397 pa.pbpa_Left = 0;
398 pa.pbpa_Top = 0;
399 pa.pbpa_Width = w;
400 pa.pbpa_Height = h;
401 DoMethodA(pic, (Msg) & pa);
402 if (mask != mskHasAlpha)
404 #if !AROS_BIG_ENDIAN
405 for (a = 0; a < (w * h); a++)
406 ni->data[a] |= 0x000000ff;
407 #else
408 for (a = 0; a < (w * h); a++)
409 ni->data[a] |= 0xff000000;
410 #endif
412 if (scr != NULL)
414 depth = (ULONG) GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH);
416 if (depth < 15)
417 ni->o = LoadPicture(name, scr);
418 if (ni->o != NULL)
420 GetDTAttrs(ni->o, PDTA_DestBitMap,
421 (IPTR) & ni->bitmap, TAG_DONE);
422 if (ni->bitmap == NULL)
423 GetDTAttrs(ni->o, PDTA_BitMap,
424 (IPTR) & ni->bitmap, TAG_DONE);
426 if (ni->bitmap)
427 GetDTAttrs(ni->o, PDTA_MaskPlane,
428 (IPTR) & ni->mask, TAG_DONE);
433 DisposeDTObject(pic);
435 return ni;
440 BOOL ReadPropConfig(struct dt_node * data, struct Screen * scr)
443 char buffer[256];
444 char *line, *v;
445 BPTR file;
447 file = Open(data->filename, MODE_OLDFILE);
448 if (file)
452 line = FGets(file, buffer, 256);
453 if (line)
455 if ((v = strstr(line, "ContainerTop ")) == line)
457 GetIntegers(v, &data->ContainerTop_o,
458 &data->ContainerTop_s);
460 else if ((v = strstr(line, "ContainerVertTile ")) == line)
462 GetIntegers(v, &data->ContainerVertTile_o,
463 &data->ContainerVertTile_s);
465 else if ((v = strstr(line, "KnobTop ")) == line)
467 GetIntegers(v, &data->KnobTop_o, &data->KnobTop_s);
469 else if ((v = strstr(line, "KnobTileTop ")) == line)
471 GetIntegers(v, &data->KnobTileTop_o,
472 &data->KnobTileTop_s);
474 else if ((v = strstr(line, "KnobVertGripper ")) == line)
476 GetIntegers(v, &data->KnobVertGripper_o,
477 &data->KnobVertGripper_s);
479 else if ((v = strstr(line, "KnobTileBottom ")) == line)
481 GetIntegers(v, &data->KnobTileBottom_o,
482 &data->KnobTileBottom_s);
484 else if ((v = strstr(line, "KnobBottom ")) == line)
486 GetIntegers(v, &data->KnobBottom_o,
487 &data->KnobBottom_s);
489 else if ((v = strstr(line, "ContainerBottom ")) == line)
491 GetIntegers(v, &data->ContainerBottom_o,
492 &data->ContainerBottom_s);
494 else if ((v = strstr(line, "ContainerLeft ")) == line)
496 GetIntegers(v, &data->ContainerLeft_o,
497 &data->ContainerLeft_s);
499 else if ((v = strstr(line, "ContainerHorTile ")) == line)
501 GetIntegers(v, &data->ContainerHorTile_o,
502 &data->ContainerHorTile_s);
504 else if ((v = strstr(line, "KnobLeft ")) == line)
506 GetIntegers(v, &data->KnobLeft_o, &data->KnobLeft_s);
508 else if ((v = strstr(line, "KnobTileLeft ")) == line)
510 GetIntegers(v, &data->KnobTileLeft_o,
511 &data->KnobTileLeft_s);
513 else if ((v = strstr(line, "KnobHorGripper ")) == line)
515 GetIntegers(v, &data->KnobHorGripper_o,
516 &data->KnobHorGripper_s);
518 else if ((v = strstr(line, "KnobTileRight ")) == line)
520 GetIntegers(v, &data->KnobTileRight_o,
521 &data->KnobTileRight_s);
523 else if ((v = strstr(line, "KnobRight ")) == line)
525 GetIntegers(v, &data->KnobRight_o, &data->KnobRight_s);
527 else if ((v = strstr(line, "ContainerRight ")) == line)
529 GetIntegers(v, &data->ContainerRight_o,
530 &data->ContainerRight_s);
534 while (line);
535 Close(file);
537 STRPTR path = allocPath(data->filename);
538 if (path)
540 BPTR lock = Lock(path, ACCESS_READ);
541 if (lock)
543 BPTR oldcd = CurrentDir(lock);
544 data->img_verticalcontainer =
545 GetImageFromFile("Container/Vertical", scr);
546 data->img_verticalknob = GetImageFromFile("Knob/Vertical", scr);
547 data->img_horizontalcontainer =
548 GetImageFromFile("Container/Horizontal", scr);
549 data->img_horizontalknob =
550 GetImageFromFile("Knob/Horizontal", scr);
551 data->img_up = GetImageFromFile("ArrowUp/default", scr);
552 data->img_down = GetImageFromFile("ArrowDown/default", scr);
553 data->img_left = GetImageFromFile("ArrowLeft/default", scr);
554 data->img_right = GetImageFromFile("ArrowRight/default", scr);
556 CurrentDir(oldcd);
557 UnLock(lock);
560 freeString(path);
563 if (data->img_horizontalcontainer && data->img_horizontalknob
564 && data->img_verticalcontainer && data->img_verticalknob
565 && data->img_up && data->img_down && data->img_left
566 && data->img_right)
567 return TRUE;
568 return FALSE;
571 void FreePropConfig(struct dt_node *data)
573 DisposeImageContainer(data->img_verticalcontainer);
574 DisposeImageContainer(data->img_verticalknob);
575 DisposeImageContainer(data->img_horizontalcontainer);
576 DisposeImageContainer(data->img_horizontalknob);
577 DisposeImageContainer(data->img_up);
578 DisposeImageContainer(data->img_down);
579 DisposeImageContainer(data->img_left);
580 DisposeImageContainer(data->img_right);
584 BOOL ReadFrameConfig(CONST_STRPTR filename, struct dt_frame_image *fi,
585 struct Screen *scr)
588 char buffer[256];
589 char *line, *v;
590 BPTR file;
592 fi->noalpha = FALSE;
594 file = Open(filename, MODE_OLDFILE);
595 if (file)
599 line = FGets(file, buffer, 256);
600 if (line)
602 if ((v = strstr(line, "TileLeft ")) == line)
604 fi->tile_left = GetInt(v);
606 else if ((v = strstr(line, "TileTop ")) == line)
608 fi->tile_top = GetInt(v);
610 else if ((v = strstr(line, "TileRight ")) == line)
612 fi->tile_right = GetInt(v);
614 else if ((v = strstr(line, "TileBottom ")) == line)
616 fi->tile_bottom = GetInt(v);
618 else if ((v = strstr(line, "InnerLeft ")) == line)
620 fi->inner_left = GetInt(v);
622 else if ((v = strstr(line, "InnerTop ")) == line)
624 fi->inner_top = GetInt(v);
626 else if ((v = strstr(line, "InnerRight ")) == line)
628 fi->inner_right = GetInt(v);
630 else if ((v = strstr(line, "InnerBottom ")) == line)
632 fi->inner_bottom = GetInt(v);
634 else if ((v = strstr(line, "NoAlpha ")) == line)
636 fi->noalpha = GetBool(v, "Yes");
640 while (line);
641 Close(file);
644 STRPTR path = allocPath(filename);
645 if (path)
647 BPTR lock = Lock(path, ACCESS_READ);
648 if (lock)
650 BPTR oldcd = CurrentDir(lock);
651 fi->img_up = GetImageFromFile("up/default", scr);
652 fi->img_down = GetImageFromFile("down/default", scr);
654 CurrentDir(oldcd);
655 UnLock(lock);
658 freeString(path);
660 if (fi->img_up && fi->img_down)
661 return TRUE;
662 return FALSE;
665 void FreeFrameConfig(struct dt_frame_image *fi)
667 if (fi != NULL)
669 DisposeImageContainer(fi->img_up);
670 DisposeImageContainer(fi->img_down);
674 void dispose_custom_frame(struct dt_frame_image *fi)
676 if (fi != NULL)
678 FreeFrameConfig(fi);
679 FreeVec(fi);
683 struct dt_frame_image *load_custom_frame(CONST_STRPTR filename,
684 struct Screen *scr)
686 struct dt_frame_image *fi =
687 AllocVec(sizeof(struct dt_frame_image), MEMF_ANY);
689 if (fi)
691 /* special configuration image for prop gadgets */
692 if (Stricmp(FilePart(filename), "frame.config") == 0)
694 if (ReadFrameConfig(filename, fi, scr))
696 return fi;
698 else
700 FreeFrameConfig(fi);
701 FreeVec(fi);
702 return NULL;
705 FreeVec(fi);
707 return NULL;
710 struct dt_node *dt_load_picture(CONST_STRPTR filename, struct Screen *scr)
712 struct dt_node *node;
713 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
714 if (!dt_initialized)
716 NewList(&dt_list);
717 dt_initialized = 1;
720 node = List_First(&dt_list);
721 while (node)
723 if (!Stricmp(filename, node->filename) && scr == node->scr)
725 node->count++;
726 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
727 return node;
729 node = Node_Next(node);
732 if ((node =
733 (struct dt_node *)AllocVec(sizeof(struct dt_node), MEMF_CLEAR)))
736 if ((node->filename = StrDup(filename)))
738 /* create the datatypes object */
739 D(bug("loading %s\n", filename));
741 /* special configuration image for prop gadgets */
742 if ((Stricmp(FilePart(filename), "prop.config") == 0)
743 || (Stricmp(FilePart(filename), "config") == 0))
745 if (ReadPropConfig(node, scr))
748 node->mode = MODE_PROP;
749 node->scr = scr;
750 node->count = 1;
751 AddTail((struct List *)&dt_list, (struct Node *)node);
752 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
753 return node;
755 else
757 FreePropConfig(node);
760 else
762 if ((node->o = LoadPicture(filename, scr)))
764 struct BitMapHeader *bmhd;
765 GetDTAttrs(node->o, PDTA_BitMapHeader, (IPTR) & bmhd,
766 TAG_DONE);
767 D(bug("picture %lx\n", node->o));
769 if (bmhd)
771 node->width = bmhd->bmh_Width;
772 node->height = bmhd->bmh_Height;
773 node->mask = bmhd->bmh_Masking;
774 D(bug("picture %lx = %ldx%ld\n", node->o,
775 node->width, node->height));
777 node->scr = scr;
778 node->count = 1;
779 AddTail((struct List *)&dt_list, (struct Node *)node);
780 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
781 return node;
784 FreeVec(node->filename);
786 FreeVec(node);
788 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
789 return NULL;
792 void dt_dispose_picture(struct dt_node *node)
794 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
795 if (node && node->count)
797 node->count--;
798 if (!node->count)
800 Remove((struct Node *)node);
801 if (node->bfi != NULL)
803 if (node->bfi->BitMap != NULL)
804 FreeBitMap(node->bfi->BitMap);
805 FreeVec(node->bfi);
807 if (node->mode == MODE_PROP)
808 FreePropConfig(node);
809 else
810 DisposeDTObject(node->o);
811 FreeVec(node->filename);
812 FreeVec(node);
815 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
818 int dt_width(struct dt_node *node)
820 if (node)
821 return node->width;
822 else
823 return 0;
826 int dt_height(struct dt_node *node)
828 if (node)
829 return node->height;
830 else
831 return 0;
834 void dt_put_on_rastport(struct dt_node *node, struct RastPort *rp, int x,
835 int y)
837 struct BitMap *bitmap = NULL;
838 struct pdtBlitPixelArray pa;
839 ULONG *img;
840 Object *o;
841 BOOL doAlpha = TRUE;
843 o = node->o;
844 if (NULL == o)
845 return;
847 #ifdef __mc68000
848 /* WritePixelArrayAlpha is insanely expensive on slow
849 * m68k machines in planar graphics modes
851 doAlpha = GetBitMapAttr(rp->BitMap, BMA_DEPTH) > 8;
852 #endif
854 if (doAlpha && node->mask == mskHasAlpha)
856 img =
857 (ULONG *) AllocVec(dt_width(node) * dt_height(node) * 4,
858 MEMF_ANY);
859 if (img)
861 pa.MethodID = PDTM_READPIXELARRAY;
862 pa.pbpa_PixelData = (UBYTE *) img;
863 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
864 pa.pbpa_PixelArrayMod = dt_width(node) * 4;
865 pa.pbpa_Left = 0;
866 pa.pbpa_Top = 0;
867 pa.pbpa_Width = dt_width(node);
868 pa.pbpa_Height = dt_height(node);
869 DoMethodA(o, (Msg) & pa);
870 WritePixelArrayAlpha(img, 0, 0, dt_width(node) * 4, rp, x, y,
871 dt_width(node), dt_height(node), 0xffffffff);
872 FreeVec((APTR) img);
875 else
877 GetDTAttrs(o, PDTA_DestBitMap, (IPTR) & bitmap, TAG_DONE);
878 if (NULL == bitmap)
879 GetDTAttrs(o, PDTA_BitMap, (IPTR) & bitmap, TAG_DONE);
881 if (bitmap)
883 APTR mask = NULL;
885 GetDTAttrs(o, PDTA_MaskPlane, (IPTR) & mask, TAG_DONE);
886 if (mask)
888 #ifndef __AROS__
889 MyBltMaskBitMapRastPort(bitmap, 0, 0, rp, x, y,
890 dt_width(node), dt_height(node), 0xe0, (PLANEPTR) mask);
891 #else
892 BltMaskBitMapRastPort(bitmap, 0, 0, rp, x, y,
893 dt_width(node), dt_height(node), 0xe0, (PLANEPTR) mask);
894 #endif
896 else
897 BltBitMapRastPort(bitmap, 0, 0, rp, x, y,
898 dt_width(node), dt_height(node), 0xc0);
903 void dt_put_mim_on_rastport(struct dt_node *node, struct RastPort *rp,
904 int x, int y, int state)
906 struct BitMap *bitmap = NULL;
907 struct pdtBlitPixelArray pa;
908 ULONG *img;
910 Object *o;
912 o = node->o;
913 if (NULL == o)
914 return;
915 int width = dt_width(node) >> 1;
916 if (node->mask == mskHasAlpha)
918 img =
919 (ULONG *) AllocVec(dt_width(node) * dt_height(node) * 4,
920 MEMF_ANY);
921 if (img)
924 int height = dt_height(node);
925 pa.MethodID = PDTM_READPIXELARRAY;
926 pa.pbpa_PixelData = (UBYTE *) img;
927 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
928 pa.pbpa_PixelArrayMod = width * 4;
929 pa.pbpa_Left = state * width;
930 pa.pbpa_Top = 0;
931 pa.pbpa_Width = width;
932 pa.pbpa_Height = height;
933 DoMethodA(o, (Msg) & pa);
934 WritePixelArrayAlpha(img, 0, 0, width * 4, rp, x, y, width,
935 height, 0xffffffff);
936 FreeVec((APTR) img);
939 else
941 GetDTAttrs(o, PDTA_DestBitMap, (IPTR) & bitmap, TAG_DONE);
942 if (NULL == bitmap)
943 GetDTAttrs(o, PDTA_BitMap, (IPTR) & bitmap, TAG_DONE);
946 if (bitmap)
948 APTR mask = NULL;
950 GetDTAttrs(o, PDTA_MaskPlane, (IPTR) & mask, TAG_DONE);
951 if (mask)
953 #ifndef __AROS__
954 MyBltMaskBitMapRastPort(bitmap, width * state, 0, rp, x, y,
955 width, dt_height(node), 0xe0, (PLANEPTR) mask);
956 #else
957 BltMaskBitMapRastPort(bitmap, width * state, 0, rp, x, y,
958 width, dt_height(node), 0xe0, (PLANEPTR) mask);
959 #endif
961 else
962 BltBitMapRastPort(bitmap, width * state, 0, rp, x, y,
963 width, dt_height(node), 0xc0);
970 static void CopyTiledBitMap(struct BitMap *Src, WORD SrcOffsetX,
971 WORD SrcOffsetY, WORD SrcSizeX, WORD SrcSizeY, struct BitMap *Dst,
972 struct Rectangle *DstBounds)
974 WORD FirstSizeX; // the width of the rectangle to blit as the first column
975 WORD FirstSizeY; // the height of the rectangle to blit as the first row
976 WORD SecondMinX; // the left edge of the second column
977 WORD SecondMinY; // the top edge of the second column
978 WORD SecondSizeX; // the width of the second column
979 WORD SecondSizeY; // the height of the second column
980 WORD Pos; // used as starting position in the "exponential" blit
981 WORD Size; // used as bitmap size in the "exponential" blit
983 // the width of the first tile, this is either the rest of the tile right
984 // to SrcOffsetX or the width of the dest rect, if the rect is narrow
985 FirstSizeX = MIN(SrcSizeX - SrcOffsetX, RECTSIZEX(DstBounds));
987 // the start for the second tile (if used)
988 SecondMinX = DstBounds->MinX + FirstSizeX;
990 // the width of the second tile (we want the whole tile to be SrcSizeX
991 // pixels wide, if we use SrcSizeX-SrcOffsetX pixels for the left part
992 // we'll use SrcOffsetX for the right part)
993 SecondSizeX = MIN(SrcOffsetX, DstBounds->MaxX - SecondMinX + 1);
995 // the same values are calculated for y direction
996 FirstSizeY = MIN(SrcSizeY - SrcOffsetY, RECTSIZEY(DstBounds));
997 SecondMinY = DstBounds->MinY + FirstSizeY;
998 SecondSizeY = MIN(SrcOffsetY, DstBounds->MaxY - SecondMinY + 1);
1000 // blit the first piece of the tile
1001 BltBitMap(Src, SrcOffsetX, SrcOffsetY, Dst, DstBounds->MinX,
1002 DstBounds->MinY, FirstSizeX, FirstSizeY, 0xC0, -1, NULL);
1004 // if SrcOffset was 0 or the dest rect was to narrow, we won't need a
1005 // second column
1006 if (SecondSizeX > 0)
1007 BltBitMap(Src, 0, SrcOffsetY, Dst, SecondMinX, DstBounds->MinY,
1008 SecondSizeX, FirstSizeY, 0xC0, -1, NULL);
1010 // is a second row necessary?
1011 if (SecondSizeY > 0)
1013 BltBitMap(Src, SrcOffsetX, 0, Dst, DstBounds->MinX, SecondMinY,
1014 FirstSizeX, SecondSizeY, 0xC0, -1, NULL);
1015 if (SecondSizeX > 0)
1016 BltBitMap(Src, 0, 0, Dst, SecondMinX, SecondMinY, SecondSizeX,
1017 SecondSizeY, 0xC0, -1, NULL);
1020 // this loop generates the first row of the tiles
1021 for (Pos = DstBounds->MinX + SrcSizeX, Size =
1022 MIN(SrcSizeX, DstBounds->MaxX - Pos + 1); Pos <= DstBounds->MaxX;)
1024 BltBitMap(Dst, DstBounds->MinX, DstBounds->MinY, Dst, Pos,
1025 DstBounds->MinY, Size, MIN(SrcSizeY, RECTSIZEY(DstBounds)),
1026 0xC0, -1, NULL);
1027 Pos += Size;
1028 Size = MIN(Size << 1, DstBounds->MaxX - Pos + 1);
1031 // this loop blit the first row down several times to fill the whole
1032 // dest rect
1033 for (Pos = DstBounds->MinY + SrcSizeY, Size =
1034 MIN(SrcSizeY, DstBounds->MaxY - Pos + 1); Pos <= DstBounds->MaxY;)
1036 BltBitMap(Dst, DstBounds->MinX, DstBounds->MinY, Dst,
1037 DstBounds->MinX, Pos, RECTSIZEX(DstBounds), Size, 0xC0, -1,
1038 NULL);
1039 Pos += Size;
1040 Size = MIN(Size << 1, DstBounds->MaxY - Pos + 1);
1044 AROS_UFH3S(void, WindowPatternBackFillFunc,
1045 AROS_UFHA(struct Hook *, Hook, A0),
1046 AROS_UFHA(struct RastPort *, RP, A2),
1047 AROS_UFHA(struct BackFillMsg *, BFM, A1))
1049 AROS_USERFUNC_INIT
1051 WORD OffsetX; // the offset within the tile in x direction
1052 WORD OffsetY; // the offset within the tile in y direction
1054 // get the data for our backfillhook
1055 struct BackFillInfo *BFI = (struct BackFillInfo *)Hook;
1057 #ifdef __SASC
1058 putreg(12, (long)Hook->h_Data);
1059 #endif
1061 // The first tile normally isn't totally visible => calculate the offset
1062 // (offset 0 would mean that the left edge of the damage rectangle
1063 // coincides with the left edge of a tile)
1064 OffsetX = BFM->Bounds.MinX - BFI->Options.OffsetX;
1065 // if (BFI->Options.CenterX) // horizontal centering?
1066 // OffsetX -= (BFI->Screen->Width-BFI->Width)/2;
1068 // The same values are calculated for y direction
1069 OffsetY = BFM->Bounds.MinY - BFI->Options.OffsetY;
1072 if (BFI->Options.OffsetTitleY) // shift the tiles down?
1073 OffsetY -= BFI->Screen->BarHeight+1;
1076 // if (BFI->Options.CenterY) // horizontal centering?
1077 // OffsetY -= (BFI->Screen->Height - BFI->Height)/2;
1079 CopyTiledBitMap(BFI->BitMap, MOD(OffsetX + BFI->OffsetX, BFI->Width),
1080 MOD(OffsetY + BFI->OffsetY, BFI->Height), BFI->CopyWidth,
1081 BFI->CopyHeight, RP->BitMap, &BFM->Bounds);
1083 AROS_USERFUNC_EXIT
1086 static void CalculateCopySizes(struct BackFillInfo *BFI)
1088 BFI->CopyWidth =
1089 (BFI->Width >
1090 BFI->Options.MaxCopyWidth) ? BFI->Width : BFI->Options.
1091 MaxCopyWidth - BFI->Options.MaxCopyWidth % BFI->Width;
1092 BFI->CopyHeight =
1093 (BFI->Height >
1094 BFI->Options.MaxCopyHeight) ? BFI->Height : BFI->Options.
1095 MaxCopyHeight - BFI->Options.MaxCopyHeight % BFI->Height;
1099 **********************************************************/
1100 void dt_put_on_rastport_tiled(struct dt_node *node, struct RastPort *rp,
1101 int x1, int y1, int x2, int y2, int xoffset, int yoffset)
1103 struct Screen *scr = node->scr;
1104 struct BitMap *bitmap;
1105 Object *o;
1107 o = node->o;
1108 if (!o)
1109 return;
1111 GetDTAttrs(o, PDTA_DestBitMap, (IPTR) & bitmap, TAG_DONE);
1112 if (NULL == bitmap)
1113 GetDTAttrs(o, PDTA_BitMap, (IPTR) & bitmap, TAG_DONE);
1114 if (NULL == bitmap)
1115 return;
1117 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
1119 if (!node->bfi)
1121 struct BackFillInfo *bfi =
1122 (struct BackFillInfo *)AllocVec(sizeof(struct BackFillInfo),
1123 MEMF_CLEAR);
1124 if (bfi)
1126 LONG depth = GetBitMapAttr(bitmap, BMA_DEPTH);
1127 bfi->Hook.h_Entry = (HOOKFUNC) WindowPatternBackFillFunc;
1128 #ifdef __SASC
1129 bfi->Hook.h_Data = (APTR) getreg(12); /* register A4 */
1130 #endif
1132 bfi->Options.MaxCopyWidth = 256;
1133 bfi->Options.MaxCopyHeight = 256;
1134 // bfi->Options.CenterX = FALSE; /* center the tiles horizontally? */
1135 // bfi->Options.CenterY = FALSE; /* center the tiles vertically? */
1136 bfi->Options.OffsetX = 0; /* offset to add */
1137 bfi->Options.OffsetY = 0; /* offset to add */
1139 /* add the screen titlebar height to the vertical offset? */
1140 bfi->Options.OffsetTitleY = TRUE;
1141 bfi->Width = dt_width(node);
1142 bfi->Height = dt_height(node);
1144 CalculateCopySizes(bfi);
1146 if ((bfi->BitMap =
1147 AllocBitMap(bfi->CopyWidth, bfi->CopyHeight, depth,
1148 BMF_INTERLEAVED | BMF_MINPLANES,
1149 scr->RastPort.BitMap)))
1151 struct Rectangle CopyBounds;
1152 CopyBounds.MinX = 0;
1153 CopyBounds.MinY = 0;
1154 CopyBounds.MaxX = bfi->CopyWidth - 1;
1155 CopyBounds.MaxY = bfi->CopyHeight - 1;
1157 CopyTiledBitMap(bitmap, 0, 0, bfi->Width, bfi->Height,
1158 bfi->BitMap, &CopyBounds);
1161 node->bfi = bfi;
1164 if (node->bfi)
1166 struct BackFillInfo *bfi = node->bfi;
1167 struct Rectangle rect;
1169 rect.MinX = x1;
1170 rect.MinY = y1;
1171 rect.MaxX = x2;
1172 rect.MaxY = y2;
1174 if (rp->Layer)
1176 LockLayer(0, rp->Layer);
1177 xoffset -= rp->Layer->bounds.MinX;
1178 yoffset -= rp->Layer->bounds.MinY;
1181 bfi->OffsetX = xoffset;
1182 bfi->OffsetY = yoffset;
1184 DoHookClipRects((struct Hook *)bfi, rp, &rect);
1186 if (rp->Layer)
1188 UnlockLayer(rp->Layer);
1191 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);