Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / libs / muimaster / datatypescache.c
blob1deae9dac2272ccf8665dc16afb87e8df0c9b8fe
1 /*
2 Copyright 2002-2007, 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 /* A BltBitMaskPort() replacement which blits masks for interleaved bitmaps correctly */
40 struct LayerHookMsg
42 STACKED struct Layer *layer;
43 STACKED struct Rectangle bounds;
44 STACKED LONG offsetx;
45 STACKED LONG offsety;
48 struct BltMaskHook
50 struct Hook hook;
51 struct BitMap maskBitMap;
52 struct BitMap *srcBitMap;
53 LONG srcx,srcy;
54 LONG destx,desty;
57 #ifndef __AROS__
59 #ifndef _DCC
60 VOID MyBltMaskBitMap( CONST struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct BitMap *destBitMap, LONG xDest, LONG yDest, LONG xSize, LONG ySize, struct BitMap *maskBitMap )
62 BltBitMap(srcBitMap,xSrc,ySrc,destBitMap, xDest, yDest, xSize, ySize, 0x99,~0,NULL);
63 BltBitMap(maskBitMap,xSrc,ySrc,destBitMap, xDest, yDest, xSize, ySize, 0xe2,~0,NULL);
64 BltBitMap(srcBitMap,xSrc,ySrc,destBitMap, xDest, yDest, xSize, ySize, 0x99,~0,NULL);
66 #endif
68 ASM void HookFunc_BltMask(REG(a0, struct Hook *hook), REG(a1,struct LayerHookMsg *msg), REG(a2,struct RastPort *rp ))
70 struct BltMaskHook *h = (struct BltMaskHook*)hook;
72 LONG width = msg->bounds.MaxX - msg->bounds.MinX+1;
73 LONG height = msg->bounds.MaxY - msg->bounds.MinY+1;
74 LONG offsetx = h->srcx + msg->offsetx - h->destx;
75 LONG offsety = h->srcy + msg->offsety - h->desty;
77 #ifdef __SASC
78 putreg(REG_A4,(long)hook->h_Data);
79 #endif
81 MyBltMaskBitMap( h->srcBitMap, offsetx, offsety, rp->BitMap, msg->bounds.MinX, msg->bounds.MinY, width, height, &h->maskBitMap);
84 VOID MyBltMaskBitMapRastPort( struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize, ULONG minterm, APTR bltMask )
86 if (GetBitMapAttr(srcBitMap,BMA_FLAGS)&BMF_INTERLEAVED)
88 LONG src_depth = GetBitMapAttr(srcBitMap,BMA_DEPTH);
89 struct Rectangle rect;
90 struct BltMaskHook hook;
92 /* Define the destination rectangle in the rastport */
93 rect.MinX = xDest;
94 rect.MinY = yDest;
95 rect.MaxX = xDest + xSize - 1;
96 rect.MaxY = yDest + ySize - 1;
98 /* Initialize the hook */
99 hook.hook.h_Entry = (HOOKFUNC)HookFunc_BltMask;
100 #ifdef __SASC
101 hook.hook.h_Data = (void*)getreg(REG_A4);
102 #endif
103 hook.srcBitMap = srcBitMap;
104 hook.srcx = xSrc;
105 hook.srcy = ySrc;
106 hook.destx = xDest;
107 hook.desty = yDest;
109 /* Initialize a bitmap where all plane pointers points to the mask */
110 InitBitMap(&hook.maskBitMap,src_depth,GetBitMapAttr(srcBitMap,BMA_WIDTH),GetBitMapAttr(srcBitMap,BMA_HEIGHT));
111 while (src_depth)
112 hook.maskBitMap.Planes[--src_depth] = bltMask;
114 /* Blit onto the Rastport */
115 DoHookClipRects(&hook.hook,destRP,&rect);
116 } else
118 BltMaskBitMapRastPort(srcBitMap, xSrc, ySrc, destRP, xDest, yDest, xSize, ySize, minterm, bltMask);
122 #endif
125 static Object *LoadPicture(CONST_STRPTR filename, struct Screen *scr)
127 Object *o;
129 struct Process *myproc = (struct Process *)FindTask(NULL);
130 APTR oldwindowptr = myproc->pr_WindowPtr;
131 myproc->pr_WindowPtr = (APTR)-1;
133 o = NewDTObject((APTR)filename,
134 DTA_GroupID , GID_PICTURE,
135 OBP_Precision , PRECISION_EXACT,
136 PDTA_Screen , (IPTR)scr,
137 PDTA_FreeSourceBitMap, TRUE,
138 PDTA_DestMode , PMODE_V43,
139 PDTA_UseFriendBitMap , TRUE,
140 TAG_DONE);
142 myproc->pr_WindowPtr = oldwindowptr;
143 D(bug("... picture=%lx\n", o));
145 if (o)
147 struct BitMapHeader *bmhd;
149 GetDTAttrs(o,PDTA_BitMapHeader, (IPTR)&bmhd, TAG_DONE);
150 if (bmhd->bmh_Masking == mskHasAlpha)
152 if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) >= 15)
154 SetAttrs(o, PDTA_FreeSourceBitMap, FALSE,
155 PDTA_Remap, FALSE,
156 TAG_DONE);
160 struct FrameInfo fri = {0};
162 D(bug("DTM_FRAMEBOX\n", o));
163 DoMethod(o,DTM_FRAMEBOX,NULL,(IPTR)&fri,(IPTR)&fri,sizeof(struct FrameInfo),0);
165 if (fri.fri_Dimensions.Depth>0)
167 D(bug("DTM_PROCLAYOUT\n", o));
168 if (DoMethod(o,DTM_PROCLAYOUT,NULL,1))
170 return o;
173 DisposeDTObject(o);
175 return NULL;
179 void dt_init(void)
183 void dt_cleanup(void)
188 char *allocPath(char *str) {
189 char *s0, *s1, *s;
190 int l;
192 s = NULL;
193 s0 = str;
195 s1 = PathPart(str);
196 if (s1) {
197 for (l=0; s0 != s1; s0++,l++);
198 s = AllocVec(l+1, MEMF_CLEAR);
199 if (s) strncpy(s, str, l);
201 return s;
204 void freeString(char *str) {
205 if (str) FreeVec(str);
208 char *SkipChars(char *v) {
209 char *c;
211 c = strstr(v, "=");
212 return ++c;
215 int GetInt(char *v) {
216 char *c;
217 c = SkipChars(v);
218 return atol(c);
221 BOOL GetBool(char *v, char *id)
223 if (strstr(v, id)) return TRUE; else return FALSE;
226 void GetIntegers(char *v, int *v1, int *v2) {
227 char *c;
228 char va1[32], va2[32];
229 int cnt;
230 c = SkipChars(v);
231 if (c) {
232 cnt = sscanf(c, "%s %s", va1, va2);
233 if (cnt == 1) {
234 *v1 = -1;
235 *v2 = atol(va1);
236 } else if (cnt == 2) {
237 *v1 = atol(va1);
238 *v2 = atol(va2);
243 struct NewImage *NewImageContainer(UWORD w, UWORD h) {
245 /* Function: Create a new Image with the specified dimensions
246 * Input: UWORD w, h:
247 * width and height ofthe wished Image
248 * Output: NewImage:
249 * Pointer to the Created image or NULL
250 * Bugs: Not known yet
251 * NOTES: Function will only return non-NULL if all allocations could be done
252 * so you have not to check something inside the NewImage structure
255 struct NewImage *ni;
257 ni = AllocVec(sizeof(struct NewImage), MEMF_ANY|MEMF_CLEAR);
258 if (ni) {
259 ni->w = w;
260 ni->h = h;
261 ni->data = AllocVec(w*h*4, MEMF_ANY|MEMF_CLEAR);
262 if (ni->data == NULL) {
263 FreeVec(ni);
264 ni = NULL;
267 return ni;
270 void DisposeImageContainer(struct NewImage *ni) {
272 /* Function: Remove all Memory used by an Image
273 * Input: NewImage ni:
274 * Pointer to an Image to be deallocated
275 * Bugs: Not known
277 if (ni) {
278 if (ni->data) {
279 FreeVec(ni->data);
281 if (ni->o != NULL) DisposeDTObject(ni->o);
282 FreeVec(ni);
286 struct NewImage *GetImageFromFile(char *name, struct Screen *scr) {
288 /* Function: Load an Image from a file
289 * Input: char name:
290 * Filename of the Image to load
291 * Output: NewImage:
292 * Pointer to the Created image or NULL
293 * Bugs: Not known yet
294 * NOTES: Function will only return non-NULL if all allocations could be done
295 * so you have not to check something inside the NewImage struct.
296 * This function uses DataTypes for loading images, so be sure to have
297 * the specific DataTypes installed
300 struct BitMapHeader *bmhd;
301 struct NewImage *ni;
303 struct pdtBlitPixelArray pa;
304 Object *pic;
305 UWORD w, h;
306 ULONG a, depth;
307 UBYTE mask;
308 ni = NULL;
310 pic = NewDTObject(name, DTA_SourceType, DTST_FILE,
311 DTA_GroupID, GID_PICTURE,
312 PDTA_Remap, FALSE,
313 PDTA_DestMode, PMODE_V43,
314 TAG_DONE);
315 if (pic) {
316 get(pic, PDTA_BitMapHeader, &bmhd);
317 if(bmhd) {
318 w = bmhd->bmh_Width;
319 h = bmhd->bmh_Height;
320 mask = bmhd->bmh_Masking;
321 ni = NewImageContainer(w, h);
322 if (ni) {
323 pa.MethodID = PDTM_READPIXELARRAY;
324 pa.pbpa_PixelData = (APTR) ni->data;
325 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
326 pa.pbpa_PixelArrayMod = w*4;
327 pa.pbpa_Left = 0;
328 pa.pbpa_Top = 0;
329 pa.pbpa_Width = w;
330 pa.pbpa_Height = h;
331 DoMethodA(pic, (Msg) &pa);
332 if (mask != mskHasAlpha) {
333 #if !AROS_BIG_ENDIAN
334 for (a= 0; a < (w*h); a++) ni->data[a] |= 0x000000ff;
335 #else
336 for (a= 0; a < (w*h); a++) ni->data[a] |= 0xff000000;
337 #endif
339 if (scr != NULL)
341 depth = (ULONG) GetBitMapAttr(&scr->BitMap, BMA_DEPTH);
343 if (depth < 15) ni->o = LoadPicture(name, scr);
344 if (ni->o != NULL)
346 GetDTAttrs(ni->o, PDTA_DestBitMap, (IPTR)&ni->bitmap, TAG_DONE);
347 if (ni->bitmap == NULL) GetDTAttrs(ni->o, PDTA_BitMap, (IPTR)&ni->bitmap, TAG_DONE);
349 if (ni->bitmap) GetDTAttrs(ni->o, PDTA_MaskPlane, (IPTR)&ni->mask, TAG_DONE);
354 DisposeDTObject(pic);
356 return ni;
361 BOOL ReadPropConfig(struct dt_node *data, struct Screen *scr) {
363 char buffer[256];
364 char *line, *v;
365 BPTR file;
367 file = Open(data->filename, MODE_OLDFILE);
368 if (file) {
369 do {
370 line = FGets(file, buffer, 256);
371 if (line) {
372 if ((v = strstr(line, "ContainerTop ")) == line) {
373 GetIntegers(v, &data->ContainerTop_o, &data->ContainerTop_s);
374 } else if ((v = strstr(line, "ContainerVertTile ")) == line) {
375 GetIntegers(v, &data->ContainerVertTile_o, &data->ContainerVertTile_s);
376 } else if ((v = strstr(line, "KnobTop ")) == line) {
377 GetIntegers(v, &data->KnobTop_o, &data->KnobTop_s);
378 } else if ((v = strstr(line, "KnobTileTop ")) == line) {
379 GetIntegers(v, &data->KnobTileTop_o, &data->KnobTileTop_s);
380 } else if ((v = strstr(line, "KnobVertGripper ")) == line) {
381 GetIntegers(v, &data->KnobVertGripper_o, &data->KnobVertGripper_s);
382 } else if ((v = strstr(line, "KnobTileBottom ")) == line) {
383 GetIntegers(v, &data->KnobTileBottom_o, &data->KnobTileBottom_s);
384 } else if ((v = strstr(line, "KnobBottom ")) == line) {
385 GetIntegers(v, &data->KnobBottom_o, &data->KnobBottom_s);
386 } else if ((v = strstr(line, "ContainerBottom ")) == line) {
387 GetIntegers(v, &data->ContainerBottom_o, &data->ContainerBottom_s);
388 } else if ((v = strstr(line, "ContainerLeft ")) == line) {
389 GetIntegers(v, &data->ContainerLeft_o, &data->ContainerLeft_s);
390 } else if ((v = strstr(line, "ContainerHorTile ")) == line) {
391 GetIntegers(v, &data->ContainerHorTile_o, &data->ContainerHorTile_s);
392 } else if ((v = strstr(line, "KnobLeft ")) == line) {
393 GetIntegers(v, &data->KnobLeft_o, &data->KnobLeft_s);
394 } else if ((v = strstr(line, "KnobTileLeft ")) == line) {
395 GetIntegers(v, &data->KnobTileLeft_o, &data->KnobTileLeft_s);
396 } else if ((v = strstr(line, "KnobHorGripper ")) == line) {
397 GetIntegers(v, &data->KnobHorGripper_o, &data->KnobHorGripper_s);
398 } else if ((v = strstr(line, "KnobTileRight ")) == line) {
399 GetIntegers(v, &data->KnobTileRight_o, &data->KnobTileRight_s);
400 } else if ((v = strstr(line, "KnobRight ")) == line) {
401 GetIntegers(v, &data->KnobRight_o, &data->KnobRight_s);
402 } else if ((v = strstr(line, "ContainerRight ")) == line) {
403 GetIntegers(v, &data->ContainerRight_o, &data->ContainerRight_s);
406 } while(line);
407 Close(file);
409 STRPTR path = allocPath(data->filename);
410 if (path)
412 BPTR lock = Lock(path, ACCESS_READ);
413 if (lock)
415 BPTR oldcd = CurrentDir(lock);
416 data->img_verticalcontainer = GetImageFromFile("Container/Vertical", scr);
417 data->img_verticalknob = GetImageFromFile("Knob/Vertical", scr);
418 data->img_horizontalcontainer = GetImageFromFile("Container/Horizontal", scr);
419 data->img_horizontalknob = GetImageFromFile("Knob/Horizontal", scr);
420 data->img_up = GetImageFromFile("ArrowUp/default", scr);
421 data->img_down = GetImageFromFile("ArrowDown/default", scr);
422 data->img_left = GetImageFromFile("ArrowLeft/default", scr);
423 data->img_right = GetImageFromFile("ArrowRight/default", scr);
425 CurrentDir(oldcd);
426 UnLock(lock);
429 freeString(path);
432 if (data->img_horizontalcontainer && data->img_horizontalknob && data->img_verticalcontainer && data->img_verticalknob && data->img_up && data->img_down && data->img_left && data->img_right) return TRUE;
433 return FALSE;
436 void FreePropConfig(struct dt_node *data)
438 DisposeImageContainer(data->img_verticalcontainer);
439 DisposeImageContainer(data->img_verticalknob);
440 DisposeImageContainer(data->img_horizontalcontainer);
441 DisposeImageContainer(data->img_horizontalknob);
442 DisposeImageContainer(data->img_up);
443 DisposeImageContainer(data->img_down);
444 DisposeImageContainer(data->img_left);
445 DisposeImageContainer(data->img_right);
449 BOOL ReadFrameConfig(STRPTR filename, struct dt_frame_image *fi, struct Screen *scr) {
451 char buffer[256];
452 char *line, *v;
453 BPTR file;
455 fi->noalpha = FALSE;
457 file = Open(filename, MODE_OLDFILE);
458 if (file) {
459 do {
460 line = FGets(file, buffer, 256);
461 if (line) {
462 if ((v = strstr(line, "TileLeft ")) == line) {
463 fi->tile_left = GetInt(v);
464 } else if ((v = strstr(line, "TileTop ")) == line) {
465 fi->tile_top = GetInt(v);
466 } else if ((v = strstr(line, "TileRight ")) == line) {
467 fi->tile_right = GetInt(v);
468 } else if ((v = strstr(line, "TileBottom ")) == line) {
469 fi->tile_bottom = GetInt(v);
470 } else if ((v = strstr(line, "InnerLeft ")) == line) {
471 fi->inner_left = GetInt(v);
472 } else if ((v = strstr(line, "InnerTop ")) == line) {
473 fi->inner_top = GetInt(v);
474 } else if ((v = strstr(line, "InnerRight ")) == line) {
475 fi->inner_right = GetInt(v);
476 } else if ((v = strstr(line, "InnerBottom ")) == line) {
477 fi->inner_bottom = GetInt(v);
478 } else if ((v = strstr(line, "NoAlpha ")) == line) {
479 fi->noalpha = GetBool(v, "Yes");
482 } while(line);
483 Close(file);
486 STRPTR path = allocPath(filename);
487 if (path)
489 BPTR lock = Lock(path, ACCESS_READ);
490 if (lock)
492 BPTR oldcd = CurrentDir(lock);
493 fi->img_up = GetImageFromFile("up/default", scr);
494 fi->img_down = GetImageFromFile("down/default", scr);
496 CurrentDir(oldcd);
497 UnLock(lock);
500 freeString(path);
502 if (fi->img_up && fi->img_down) return TRUE;
503 return FALSE;
506 void FreeFrameConfig(struct dt_frame_image *fi)
508 if (fi != NULL)
510 DisposeImageContainer(fi->img_up);
511 DisposeImageContainer(fi->img_down);
515 void dispose_custom_frame(struct dt_frame_image * fi)
517 if (fi != NULL)
519 FreeFrameConfig(fi);
520 FreeVec(fi);
524 struct dt_frame_image * load_custom_frame(CONST_STRPTR filename, struct Screen *scr)
526 struct dt_frame_image *fi = AllocVec(sizeof(struct dt_frame_image), MEMF_ANY);
528 if (fi)
530 if (Stricmp(FilePart(filename), "frame.config") == 0) /* special configuration image for prop gadgets */
532 if (ReadFrameConfig(filename, fi, scr))
534 return fi;
536 else
538 FreeFrameConfig(fi);
539 FreeVec(fi);
540 return NULL;
543 FreeVec(fi);
545 return NULL;
548 struct dt_node *dt_load_picture(CONST_STRPTR filename, struct Screen *scr)
550 struct dt_node *node;
551 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
552 if (!dt_initialized)
554 NewList(&dt_list);
555 dt_initialized = 1;
558 node = List_First(&dt_list);
559 while (node)
561 if (!Stricmp(filename,node->filename) && scr == node->scr)
563 node->count++;
564 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
565 return node;
567 node = Node_Next(node);
570 if ((node = (struct dt_node*)AllocVec(sizeof(struct dt_node),MEMF_CLEAR)))
573 if ((node->filename = StrDup(filename)))
575 /* create the datatypes object */
576 D(bug("loading %s\n", filename));
577 if ((Stricmp(FilePart(filename), "prop.config") == 0) || (Stricmp(FilePart(filename), "config") == 0)) /* special configuration image for prop gadgets */
579 if (ReadPropConfig(node, scr))
582 node->mode = MODE_PROP;
583 node->scr = scr;
584 node->count = 1;
585 AddTail((struct List*)&dt_list,(struct Node*)node);
586 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
587 return node;
589 else
591 FreePropConfig(node);
594 else
596 if ((node->o = LoadPicture(filename,scr)))
598 struct BitMapHeader *bmhd;
599 GetDTAttrs(node->o,PDTA_BitMapHeader, (IPTR)&bmhd, TAG_DONE);
600 D(bug("picture %lx\n", node->o));
602 if (bmhd)
604 node->width = bmhd->bmh_Width;
605 node->height = bmhd->bmh_Height;
606 node->mask = bmhd->bmh_Masking;
607 D(bug("picture %lx = %ldx%ld\n", node->o, node->width, node->height));
609 node->scr = scr;
610 node->count = 1;
611 AddTail((struct List*)&dt_list,(struct Node*)node);
612 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
613 return node;
616 FreeVec(node->filename);
618 FreeVec(node);
620 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
621 return NULL;
624 void dt_dispose_picture(struct dt_node *node)
626 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
627 if (node && node->count)
629 node->count--;
630 if (!node->count)
632 Remove((struct Node*)node);
633 if (node->mode == MODE_PROP) FreePropConfig(node); else DisposeDTObject(node->o);
634 FreeVec(node->filename);
635 FreeVec(node);
638 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
641 int dt_width(struct dt_node *node)
643 if (node)
644 return node->width;
645 else
646 return 0;
649 int dt_height(struct dt_node *node)
651 if (node)
652 return node->height;
653 else
654 return 0;
658 void dt_put_on_rastport(struct dt_node *node, struct RastPort *rp, int x, int y)
660 struct BitMap *bitmap = NULL;
661 struct pdtBlitPixelArray pa;
662 ULONG depth = 0;
663 ULONG *img;
664 Object *o;
666 o = node->o;
667 if (NULL == o)
668 return;
670 depth = (ULONG) GetBitMapAttr(rp->BitMap, BMA_DEPTH);
671 if ((depth >= 15) && (node->mask == mskHasAlpha))
673 img = (ULONG *) AllocVec(dt_width(node) * dt_height(node) * 4, MEMF_ANY);
674 if (img)
676 pa.MethodID = PDTM_READPIXELARRAY;
677 pa.pbpa_PixelData = (UBYTE *) img;
678 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
679 pa.pbpa_PixelArrayMod = dt_width(node) * 4;
680 pa.pbpa_Left = 0;
681 pa.pbpa_Top = 0;
682 pa.pbpa_Width = dt_width(node);
683 pa.pbpa_Height = dt_height(node);
684 DoMethodA(o, (Msg) &pa);
685 WritePixelArrayAlpha(img, 0, 0, dt_width(node) * 4, rp, x, y, dt_width(node), dt_height(node), 0xffffffff);
686 FreeVec((APTR) img);
689 else
691 GetDTAttrs(o, PDTA_DestBitMap, (IPTR)&bitmap, TAG_DONE);
692 if (NULL == bitmap)
693 GetDTAttrs(o, PDTA_BitMap, (IPTR)&bitmap, TAG_DONE);
695 if (bitmap)
697 APTR mask = NULL;
699 GetDTAttrs(o, PDTA_MaskPlane, (IPTR)&mask, TAG_DONE);
700 if (mask)
702 #ifndef __AROS__
703 MyBltMaskBitMapRastPort(bitmap, 0, 0, rp, x, y,
704 dt_width(node), dt_height(node), 0xe0,
705 (PLANEPTR)mask);
706 #else
707 BltMaskBitMapRastPort(bitmap, 0, 0, rp, x, y,
708 dt_width(node), dt_height(node), 0xe0,
709 (PLANEPTR)mask);
710 #endif
712 else
713 BltBitMapRastPort(bitmap, 0, 0, rp, x, y,
714 dt_width(node), dt_height(node), 0xc0);
719 void dt_put_mim_on_rastport(struct dt_node *node, struct RastPort *rp, int x, int y,int state)
721 struct BitMap *bitmap = NULL;
722 struct pdtBlitPixelArray pa;
723 ULONG depth = 0;
724 ULONG *img;
726 Object *o;
728 o = node->o;
729 if (NULL == o)
730 return;
731 int width = dt_width(node) >> 1;
732 depth = (ULONG) GetBitMapAttr(rp->BitMap, BMA_DEPTH);
733 if ((depth >= 15) && (node->mask == mskHasAlpha))
735 img = (ULONG *) AllocVec(dt_width(node) * dt_height(node) * 4, MEMF_ANY);
736 if (img)
739 int height = dt_height(node);
740 pa.MethodID = PDTM_READPIXELARRAY;
741 pa.pbpa_PixelData = (UBYTE *) img;
742 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
743 pa.pbpa_PixelArrayMod = width * 4;
744 pa.pbpa_Left = state * width;
745 pa.pbpa_Top = 0;
746 pa.pbpa_Width = width;
747 pa.pbpa_Height = height;
748 DoMethodA(o, (Msg) &pa);
749 WritePixelArrayAlpha(img, 0, 0, width * 4, rp, x, y, width , height , 0xffffffff);
750 FreeVec((APTR) img);
753 else
755 GetDTAttrs(o, PDTA_DestBitMap, (IPTR)&bitmap, TAG_DONE);
756 if (NULL == bitmap)
757 GetDTAttrs(o, PDTA_BitMap, (IPTR)&bitmap, TAG_DONE);
760 if (bitmap)
762 APTR mask = NULL;
764 GetDTAttrs(o, PDTA_MaskPlane, (IPTR)&mask, TAG_DONE);
765 if (mask)
767 #ifndef __AROS__
768 MyBltMaskBitMapRastPort(bitmap, width*state, 0, rp, x, y,
769 width, dt_height(node), 0xe0,
770 (PLANEPTR)mask);
771 #else
772 BltMaskBitMapRastPort(bitmap, width*state, 0, rp, x, y,
773 width, dt_height(node), 0xe0,
774 (PLANEPTR)mask);
775 #endif
777 else
778 BltBitMapRastPort(bitmap, width*state, 0, rp, x, y,
779 width, dt_height(node), 0xc0);
787 #define RECTSIZEX(r) ((r)->MaxX-(r)->MinX+1)
788 #define RECTSIZEY(r) ((r)->MaxY-(r)->MinY+1)
790 #define MOD(x,y) ((x)<0 ? (y)-((-(x))%(y)) : (x)%(y))
792 struct BackFillMsg
794 struct Layer *Layer;
795 struct Rectangle Bounds;
796 LONG OffsetX;
797 LONG OffsetY;
800 struct BackFillOptions
802 WORD MaxCopyWidth; // maximum width for the copy
803 WORD MaxCopyHeight; // maximum height for the copy
804 // BOOL CenterX; // center the tiles horizontally?
805 // BOOL CenterY; // center the tiles vertically?
806 WORD OffsetX; // offset to add
807 WORD OffsetY; // offset to add
808 BOOL OffsetTitleY; // add the screen titlebar height to the vertical offset?
811 struct BackFillInfo
813 struct Hook Hook;
814 WORD Width;
815 WORD Height;
816 struct BitMap *BitMap;
817 /* struct Screen *Screen; */ /* Needed for centering */
818 WORD CopyWidth;
819 WORD CopyHeight;
820 struct BackFillOptions Options;
821 WORD OffsetX;
822 WORD OffsetY;
826 static void CopyTiledBitMap(struct BitMap *Src,WORD SrcOffsetX,WORD SrcOffsetY,WORD SrcSizeX,WORD SrcSizeY,struct BitMap *Dst,struct Rectangle *DstBounds)
828 WORD FirstSizeX; // the width of the rectangle to blit as the first column
829 WORD FirstSizeY; // the height of the rectangle to blit as the first row
830 WORD SecondMinX; // the left edge of the second column
831 WORD SecondMinY; // the top edge of the second column
832 WORD SecondSizeX; // the width of the second column
833 WORD SecondSizeY; // the height of the second column
834 WORD Pos; // used as starting position in the "exponential" blit
835 WORD Size; // used as bitmap size in the "exponential" blit
837 FirstSizeX = MIN(SrcSizeX-SrcOffsetX,RECTSIZEX(DstBounds)); // the width of the first tile, this is either the rest of the tile right to SrcOffsetX or the width of the dest rect, if the rect is narrow
838 SecondMinX = DstBounds->MinX+FirstSizeX; // the start for the second tile (if used)
839 SecondSizeX = MIN(SrcOffsetX,DstBounds->MaxX-SecondMinX+1); // the width of the second tile (we want the whole tile to be SrcSizeX pixels wide, if we use SrcSizeX-SrcOffsetX pixels for the left part we'll use SrcOffsetX for the right part)
841 FirstSizeY = MIN(SrcSizeY-SrcOffsetY,RECTSIZEY(DstBounds)); // the same values are calculated for y direction
842 SecondMinY = DstBounds->MinY+FirstSizeY;
843 SecondSizeY = MIN(SrcOffsetY,DstBounds->MaxY-SecondMinY+1);
845 BltBitMap(Src,SrcOffsetX,SrcOffsetY,Dst,DstBounds->MinX,DstBounds->MinY,FirstSizeX,FirstSizeY,0xC0,-1,NULL); // blit the first piece of the tile
846 if (SecondSizeX>0) // if SrcOffset was 0 or the dest rect was to narrow, we won't need a second column
847 BltBitMap(Src,0,SrcOffsetY,Dst,SecondMinX,DstBounds->MinY,SecondSizeX,FirstSizeY,0xC0,-1,NULL);
848 if (SecondSizeY>0) // is a second row necessary?
850 BltBitMap(Src,SrcOffsetX,0,Dst,DstBounds->MinX,SecondMinY,FirstSizeX,SecondSizeY,0xC0,-1,NULL);
851 if (SecondSizeX>0)
852 BltBitMap(Src,0,0,Dst,SecondMinX,SecondMinY,SecondSizeX,SecondSizeY,0xC0,-1,NULL);
855 // this loop generates the first row of the tiles
856 for (Pos = DstBounds->MinX+SrcSizeX,Size = MIN(SrcSizeX,DstBounds->MaxX-Pos+1);Pos<=DstBounds->MaxX;)
858 BltBitMap(Dst,DstBounds->MinX,DstBounds->MinY,Dst,Pos,DstBounds->MinY,Size,MIN(SrcSizeY,RECTSIZEY(DstBounds)),0xC0,-1,NULL);
859 Pos += Size;
860 Size = MIN(Size<<1,DstBounds->MaxX-Pos+1);
863 // this loop blit the first row down several times to fill the whole dest rect
864 for (Pos = DstBounds->MinY+SrcSizeY,Size = MIN(SrcSizeY,DstBounds->MaxY-Pos+1);Pos<=DstBounds->MaxY;)
866 BltBitMap(Dst,DstBounds->MinX,DstBounds->MinY,Dst,DstBounds->MinX,Pos,RECTSIZEX(DstBounds),Size,0xC0,-1,NULL);
867 Pos += Size;
868 Size = MIN(Size<<1,DstBounds->MaxY-Pos+1);
872 AROS_UFH3S(void, WindowPatternBackFillFunc,
873 AROS_UFHA(struct Hook *, Hook, A0),
874 AROS_UFHA(struct RastPort *, RP, A2),
875 AROS_UFHA(struct BackFillMsg *, BFM, A1))
877 AROS_USERFUNC_INIT
879 WORD OffsetX; // the offset within the tile in x direction
880 WORD OffsetY; // the offset within the tile in y direction
882 struct BackFillInfo *BFI = (struct BackFillInfo *)Hook; // get the data for our backfillhook
884 #ifdef __SASC
885 putreg(12,(long)Hook->h_Data);
886 #endif
888 OffsetX = BFM->Bounds.MinX-BFI->Options.OffsetX; // The first tile normally isn't totally visible => calculate the offset (offset 0 would mean that the left edge of the damage rectangle coincides with the left edge of a tile)
889 // if (BFI->Options.CenterX) // horizontal centering?
890 // OffsetX -= (BFI->Screen->Width-BFI->Width)/2;
892 OffsetY = BFM->Bounds.MinY-BFI->Options.OffsetY; // The same values are calculated for y direction
895 if (BFI->Options.OffsetTitleY) // shift the tiles down?
896 OffsetY -= BFI->Screen->BarHeight+1;
899 // if (BFI->Options.CenterY) // horizontal centering?
900 // OffsetY -= (BFI->Screen->Height - BFI->Height)/2;
902 CopyTiledBitMap(BFI->BitMap,MOD(OffsetX+BFI->OffsetX,BFI->Width),MOD(OffsetY+BFI->OffsetY,BFI->Height),BFI->CopyWidth,BFI->CopyHeight,RP->BitMap,&BFM->Bounds);
904 AROS_USERFUNC_EXIT
907 static void CalculateCopySizes(struct BackFillInfo *BFI)
909 BFI->CopyWidth = (BFI->Width>BFI->Options.MaxCopyWidth) ? BFI->Width : BFI->Options.MaxCopyWidth-BFI->Options.MaxCopyWidth%BFI->Width;
910 BFI->CopyHeight = (BFI->Height>BFI->Options.MaxCopyHeight) ? BFI->Height : BFI->Options.MaxCopyHeight-BFI->Options.MaxCopyHeight%BFI->Height;
913 **********************************************************/
915 void dt_put_on_rastport_tiled(struct dt_node *node, struct RastPort *rp, int x1, int y1, int x2, int y2, int xoffset, int yoffset)
917 struct Screen *scr = node->scr;
918 struct BitMap *bitmap;
919 Object *o;
921 o = node->o;
922 if (!o) return;
924 GetDTAttrs(o, PDTA_DestBitMap, (IPTR)&bitmap, TAG_DONE);
925 if (NULL == bitmap)
926 GetDTAttrs(o, PDTA_BitMap, (IPTR)&bitmap, TAG_DONE);
927 if (NULL == bitmap)
928 return;
930 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
932 if (!node->bfi)
934 struct BackFillInfo *bfi = (struct BackFillInfo*)AllocVec(sizeof(struct BackFillInfo),MEMF_CLEAR);
935 if (bfi)
937 LONG depth = GetBitMapAttr(bitmap,BMA_DEPTH);
938 bfi->Hook.h_Entry = (HOOKFUNC)WindowPatternBackFillFunc;
939 #ifdef __SASC
940 bfi->Hook.h_Data = (APTR)getreg(12); /* register A4 */
941 #endif
943 bfi->Options.MaxCopyWidth = 256;
944 bfi->Options.MaxCopyHeight = 256;
945 // bfi->Options.CenterX = FALSE; /* center the tiles horizontally? */
946 // bfi->Options.CenterY = FALSE; /* center the tiles vertically? */
947 bfi->Options.OffsetX = 0; /* offset to add */
948 bfi->Options.OffsetY = 0; /* offset to add */
949 bfi->Options.OffsetTitleY = TRUE; /* add the screen titlebar height to the vertical offset? */
950 bfi->Width = dt_width(node);
951 bfi->Height = dt_height(node);
953 CalculateCopySizes(bfi);
955 if((bfi->BitMap = AllocBitMap(bfi->CopyWidth,bfi->CopyHeight,depth, BMF_INTERLEAVED|BMF_MINPLANES,scr->RastPort.BitMap)))
957 struct Rectangle CopyBounds;
958 CopyBounds.MinX = 0;
959 CopyBounds.MinY = 0;
960 CopyBounds.MaxX = bfi->CopyWidth-1;
961 CopyBounds.MaxY = bfi->CopyHeight-1;
963 CopyTiledBitMap(bitmap,0,0,bfi->Width,bfi->Height,bfi->BitMap,&CopyBounds);
966 node->bfi = bfi;
969 if (node->bfi)
971 struct BackFillInfo *bfi = node->bfi;
972 struct Rectangle rect;
974 rect.MinX = x1;
975 rect.MinY = y1;
976 rect.MaxX = x2;
977 rect.MaxY = y2;
979 if (rp->Layer)
981 LockLayer(0, rp->Layer);
982 xoffset -= rp->Layer->bounds.MinX;
983 yoffset -= rp->Layer->bounds.MinY;
986 bfi->OffsetX = xoffset;
987 bfi->OffsetY = yoffset;
989 DoHookClipRects((struct Hook*)bfi,rp,&rect);
991 if (rp->Layer)
993 UnlockLayer(rp->Layer);
996 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);