There was a segfault dt_width/dt_height when an ImageObject was created with a non...
[tangerine.git] / workbench / libs / muimaster / datatypescache.c
blobdb1f84ef79b66f88b3c5ba906ada6614d7ff3d5a
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 #include <libraries/cybergraphics.h>
29 #define MYDEBUG 1
30 #include "debug.h"
31 #include "support.h"
32 #include "muimaster_intern.h"
33 #include "datatypescache.h"
35 extern struct Library *MUIMasterBase;
37 static struct List dt_list;
38 static int dt_initialized;
41 /* A BltBitMaskPort() replacement which blits masks for interleaved bitmaps correctly */
42 struct LayerHookMsg
44 struct Layer *layer;
45 struct Rectangle bounds;
46 LONG offsetx;
47 LONG offsety;
50 struct BltMaskHook
52 struct Hook hook;
53 struct BitMap maskBitMap;
54 struct BitMap *srcBitMap;
55 LONG srcx,srcy;
56 LONG destx,desty;
59 #ifndef __AROS__
61 #ifndef _DCC
62 VOID MyBltMaskBitMap( CONST struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct BitMap *destBitMap, LONG xDest, LONG yDest, LONG xSize, LONG ySize, struct BitMap *maskBitMap )
64 BltBitMap(srcBitMap,xSrc,ySrc,destBitMap, xDest, yDest, xSize, ySize, 0x99,~0,NULL);
65 BltBitMap(maskBitMap,xSrc,ySrc,destBitMap, xDest, yDest, xSize, ySize, 0xe2,~0,NULL);
66 BltBitMap(srcBitMap,xSrc,ySrc,destBitMap, xDest, yDest, xSize, ySize, 0x99,~0,NULL);
68 #endif
70 ASM void HookFunc_BltMask(REG(a0, struct Hook *hook), REG(a1,struct LayerHookMsg *msg), REG(a2,struct RastPort *rp ))
72 struct BltMaskHook *h = (struct BltMaskHook*)hook;
74 LONG width = msg->bounds.MaxX - msg->bounds.MinX+1;
75 LONG height = msg->bounds.MaxY - msg->bounds.MinY+1;
76 LONG offsetx = h->srcx + msg->offsetx - h->destx;
77 LONG offsety = h->srcy + msg->offsety - h->desty;
79 #ifdef __SASC
80 putreg(REG_A4,(long)hook->h_Data);
81 #endif
83 MyBltMaskBitMap( h->srcBitMap, offsetx, offsety, rp->BitMap, msg->bounds.MinX, msg->bounds.MinY, width, height, &h->maskBitMap);
86 VOID MyBltMaskBitMapRastPort( struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize, ULONG minterm, APTR bltMask )
88 if (GetBitMapAttr(srcBitMap,BMA_FLAGS)&BMF_INTERLEAVED)
90 LONG src_depth = GetBitMapAttr(srcBitMap,BMA_DEPTH);
91 struct Rectangle rect;
92 struct BltMaskHook hook;
94 /* Define the destination rectangle in the rastport */
95 rect.MinX = xDest;
96 rect.MinY = yDest;
97 rect.MaxX = xDest + xSize - 1;
98 rect.MaxY = yDest + ySize - 1;
100 /* Initialize the hook */
101 hook.hook.h_Entry = (HOOKFUNC)HookFunc_BltMask;
102 #ifdef __SASC
103 hook.hook.h_Data = (void*)getreg(REG_A4);
104 #endif
105 hook.srcBitMap = srcBitMap;
106 hook.srcx = xSrc;
107 hook.srcy = ySrc;
108 hook.destx = xDest;
109 hook.desty = yDest;
111 /* Initialize a bitmap where all plane pointers points to the mask */
112 InitBitMap(&hook.maskBitMap,src_depth,GetBitMapAttr(srcBitMap,BMA_WIDTH),GetBitMapAttr(srcBitMap,BMA_HEIGHT));
113 while (src_depth)
114 hook.maskBitMap.Planes[--src_depth] = bltMask;
116 /* Blit onto the Rastport */
117 DoHookClipRects(&hook.hook,destRP,&rect);
118 } else
120 BltMaskBitMapRastPort(srcBitMap, xSrc, ySrc, destRP, xDest, yDest, xSize, ySize, minterm, bltMask);
124 #endif
127 static Object *LoadPicture(CONST_STRPTR filename, struct Screen *scr)
129 Object *o;
131 struct Process *myproc = (struct Process *)FindTask(NULL);
132 APTR oldwindowptr = myproc->pr_WindowPtr;
133 myproc->pr_WindowPtr = (APTR)-1;
135 o = NewDTObject((APTR)filename,
136 DTA_GroupID , GID_PICTURE,
137 OBP_Precision , PRECISION_EXACT,
138 PDTA_Screen , (IPTR)scr,
139 PDTA_FreeSourceBitMap, TRUE,
140 PDTA_DestMode , PMODE_V43,
141 PDTA_UseFriendBitMap , TRUE,
142 TAG_DONE);
144 myproc->pr_WindowPtr = oldwindowptr;
145 D(bug("... picture=%lx\n", o));
147 if (o)
149 struct BitMapHeader *bmhd;
151 GetDTAttrs(o,PDTA_BitMapHeader, (IPTR)&bmhd, TAG_DONE);
152 if (bmhd->bmh_Masking == mskHasAlpha)
154 if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) >= 15)
156 SetAttrs(o, PDTA_FreeSourceBitMap, FALSE,
157 PDTA_Remap, FALSE,
158 TAG_DONE);
162 struct FrameInfo fri = {0};
164 D(bug("DTM_FRAMEBOX\n", o));
165 DoMethod(o,DTM_FRAMEBOX,NULL,(IPTR)&fri,(IPTR)&fri,sizeof(struct FrameInfo),0);
167 if (fri.fri_Dimensions.Depth>0)
169 D(bug("DTM_PROCLAYOUT\n", o));
170 if (DoMethod(o,DTM_PROCLAYOUT,NULL,1))
172 return o;
175 DisposeDTObject(o);
177 return NULL;
181 void dt_init(void)
185 void dt_cleanup(void)
190 char *allocPath(char *str) {
191 char *s0, *s1, *s;
192 int l;
194 s = NULL;
195 s0 = str;
197 s1 = PathPart(str);
198 if (s1) {
199 for (l=0; s0 != s1; s0++,l++);
200 s = AllocVec(l+1, MEMF_CLEAR);
201 if (s) strncpy(s, str, l);
203 return s;
206 void freeString(char *str) {
207 if (str) FreeVec(str);
210 char *SkipChars(char *v) {
211 char *c;
213 c = strstr(v, "=");
214 return ++c;
217 int GetInt(char *v) {
218 char *c;
219 c = SkipChars(v);
220 return atol(c);
223 void GetIntegers(char *v, int *v1, int *v2) {
224 char *c;
225 char va1[32], va2[32];
226 int cnt;
227 c = SkipChars(v);
228 if (c) {
229 cnt = sscanf(c, "%s %s", va1, va2);
230 if (cnt == 1) {
231 *v1 = -1;
232 *v2 = atol(va1);
233 } else if (cnt == 2) {
234 *v1 = atol(va1);
235 *v2 = atol(va2);
240 struct NewImage *NewImageContainer(UWORD w, UWORD h) {
242 /* Function: Create a new Image with the specified dimensions
243 * Input: UWORD w, h:
244 * width and height ofthe wished Image
245 * Output: NewImage:
246 * Pointer to the Created image or NULL
247 * Bugs: Not known yet
248 * NOTES: Function will only return non-NULL if all allocations could be done
249 * so you have not to check something inside the NewImage structure
252 struct NewImage *ni;
254 ni = AllocVec(sizeof(struct NewImage), MEMF_ANY|MEMF_CLEAR);
255 if (ni) {
256 ni->w = w;
257 ni->h = h;
258 ni->data = AllocVec(w*h*4, MEMF_ANY|MEMF_CLEAR);
259 if (ni->data == NULL) {
260 FreeVec(ni);
261 ni = NULL;
264 return ni;
267 void DisposeImageContainer(struct NewImage *ni) {
269 /* Function: Remove all Memory used by an Image
270 * Input: NewImage ni:
271 * Pointer to an Image to be deallocated
272 * Bugs: Not known
274 if (ni) {
275 if (ni->data) {
276 FreeVec(ni->data);
278 if (ni->o != NULL) DisposeDTObject(ni->o);
279 FreeVec(ni);
283 struct NewImage *GetImageFromFile(char *name, struct Screen *scr) {
285 /* Function: Load an Image from a file
286 * Input: char name:
287 * Filename of the Image to load
288 * Output: NewImage:
289 * Pointer to the Created image or NULL
290 * Bugs: Not known yet
291 * NOTES: Function will only return non-NULL if all allocations could be done
292 * so you have not to check something inside the NewImage struct.
293 * This function uses DataTypes for loading images, so be sure to have
294 * the specific DataTypes installed
297 struct BitMapHeader *bmhd;
298 struct NewImage *ni;
300 struct pdtBlitPixelArray pa;
301 Object *pic;
302 UWORD w, h;
303 ULONG a, depth;
304 UBYTE mask;
305 ni = NULL;
307 pic = NewDTObject(name, DTA_SourceType, DTST_FILE,
308 DTA_GroupID, GID_PICTURE,
309 PDTA_Remap, FALSE,
310 PDTA_DestMode, PMODE_V43,
311 TAG_DONE);
312 if (pic) {
313 get(pic, PDTA_BitMapHeader, &bmhd);
314 if(bmhd) {
315 w = bmhd->bmh_Width;
316 h = bmhd->bmh_Height;
317 mask = bmhd->bmh_Masking;
318 ni = NewImageContainer(w, h);
319 if (ni) {
320 pa.MethodID = PDTM_READPIXELARRAY;
321 pa.pbpa_PixelData = (APTR) ni->data;
322 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
323 pa.pbpa_PixelArrayMod = w*4;
324 pa.pbpa_Left = 0;
325 pa.pbpa_Top = 0;
326 pa.pbpa_Width = w;
327 pa.pbpa_Height = h;
328 DoMethodA(pic, (Msg) &pa);
329 if (mask != mskHasAlpha) {
330 #if !AROS_BIG_ENDIAN
331 for (a= 0; a < (w*h); a++) ni->data[a] |= 0x000000ff;
332 #else
333 for (a= 0; a < (w*h); a++) ni->data[a] |= 0xff000000;
334 #endif
336 if (scr != NULL)
338 depth = (ULONG) GetBitMapAttr(&scr->BitMap, BMA_DEPTH);
340 if (depth < 15) ni->o = LoadPicture(name, scr);
341 if (ni->o != NULL)
343 GetDTAttrs(ni->o, PDTA_DestBitMap, (IPTR)&ni->bitmap, TAG_DONE);
344 if (ni->bitmap == NULL) GetDTAttrs(ni->o, PDTA_BitMap, (IPTR)&ni->bitmap, TAG_DONE);
346 if (ni->bitmap) GetDTAttrs(ni->o, PDTA_MaskPlane, (IPTR)&ni->mask, TAG_DONE);
351 DisposeDTObject(pic);
353 return ni;
358 BOOL ReadPropConfig(struct dt_node *data, struct Screen *scr) {
360 char buffer[256];
361 char *line, *v;
362 BPTR file;
364 file = Open(data->filename, MODE_OLDFILE);
365 if (file) {
366 do {
367 line = FGets(file, buffer, 256);
368 if (line) {
369 if ((v = strstr(line, "ContainerTop ")) == line) {
370 GetIntegers(v, &data->ContainerTop_o, &data->ContainerTop_s);
371 } else if ((v = strstr(line, "ContainerVertTile ")) == line) {
372 GetIntegers(v, &data->ContainerVertTile_o, &data->ContainerVertTile_s);
373 } else if ((v = strstr(line, "KnobTop ")) == line) {
374 GetIntegers(v, &data->KnobTop_o, &data->KnobTop_s);
375 } else if ((v = strstr(line, "KnobTileTop ")) == line) {
376 GetIntegers(v, &data->KnobTileTop_o, &data->KnobTileTop_s);
377 } else if ((v = strstr(line, "KnobVertGripper ")) == line) {
378 GetIntegers(v, &data->KnobVertGripper_o, &data->KnobVertGripper_s);
379 } else if ((v = strstr(line, "KnobTileBottom ")) == line) {
380 GetIntegers(v, &data->KnobTileBottom_o, &data->KnobTileBottom_s);
381 } else if ((v = strstr(line, "KnobBottom ")) == line) {
382 GetIntegers(v, &data->KnobBottom_o, &data->KnobBottom_s);
383 } else if ((v = strstr(line, "ContainerBottom ")) == line) {
384 GetIntegers(v, &data->ContainerBottom_o, &data->ContainerBottom_s);
385 } else if ((v = strstr(line, "ContainerLeft ")) == line) {
386 GetIntegers(v, &data->ContainerLeft_o, &data->ContainerLeft_s);
387 } else if ((v = strstr(line, "ContainerHorTile ")) == line) {
388 GetIntegers(v, &data->ContainerHorTile_o, &data->ContainerHorTile_s);
389 } else if ((v = strstr(line, "KnobLeft ")) == line) {
390 GetIntegers(v, &data->KnobLeft_o, &data->KnobLeft_s);
391 } else if ((v = strstr(line, "KnobTileLeft ")) == line) {
392 GetIntegers(v, &data->KnobTileLeft_o, &data->KnobTileLeft_s);
393 } else if ((v = strstr(line, "KnobHorGripper ")) == line) {
394 GetIntegers(v, &data->KnobHorGripper_o, &data->KnobHorGripper_s);
395 } else if ((v = strstr(line, "KnobTileRight ")) == line) {
396 GetIntegers(v, &data->KnobTileRight_o, &data->KnobTileRight_s);
397 } else if ((v = strstr(line, "KnobRight ")) == line) {
398 GetIntegers(v, &data->KnobRight_o, &data->KnobRight_s);
399 } else if ((v = strstr(line, "ContainerRight ")) == line) {
400 GetIntegers(v, &data->ContainerRight_o, &data->ContainerRight_s);
403 } while(line);
404 Close(file);
406 STRPTR path = allocPath(data->filename);
407 if (path)
409 BPTR lock = Lock(path, ACCESS_READ);
410 if (lock)
412 BPTR oldcd = CurrentDir(lock);
413 data->img_verticalcontainer = GetImageFromFile("Container/Vertical", scr);
414 data->img_verticalknob = GetImageFromFile("Knob/Vertical", scr);
415 data->img_horizontalcontainer = GetImageFromFile("Container/Horizontal", scr);
416 data->img_horizontalknob = GetImageFromFile("Knob/Horizontal", scr);
417 data->img_up = GetImageFromFile("ArrowUp/default", scr);
418 data->img_down = GetImageFromFile("ArrowDown/default", scr);
419 data->img_left = GetImageFromFile("ArrowLeft/default", scr);
420 data->img_right = GetImageFromFile("ArrowRight/default", scr);
422 CurrentDir(oldcd);
423 UnLock(lock);
426 freeString(path);
429 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;
430 return FALSE;
433 void FreePropConfig(struct dt_node *data)
435 DisposeImageContainer(data->img_verticalcontainer);
436 DisposeImageContainer(data->img_verticalknob);
437 DisposeImageContainer(data->img_horizontalcontainer);
438 DisposeImageContainer(data->img_horizontalknob);
439 DisposeImageContainer(data->img_up);
440 DisposeImageContainer(data->img_down);
441 DisposeImageContainer(data->img_left);
442 DisposeImageContainer(data->img_right);
446 struct dt_node *dt_load_picture(CONST_STRPTR filename, struct Screen *scr)
448 struct dt_node *node;
449 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
450 if (!dt_initialized)
452 NewList(&dt_list);
453 dt_initialized = 1;
456 node = List_First(&dt_list);
457 while (node)
459 if (!Stricmp(filename,node->filename) && scr == node->scr)
461 node->count++;
462 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
463 return node;
465 node = Node_Next(node);
468 if ((node = (struct dt_node*)AllocVec(sizeof(struct dt_node),MEMF_CLEAR)))
471 if ((node->filename = StrDup(filename)))
473 /* create the datatypes object */
474 D(bug("loading %s\n", filename));
475 if ((Stricmp(FilePart(filename), "prop.config") == 0) || (Stricmp(FilePart(filename), "config") == 0)) /* special configuration image for prop gadgets */
477 if (ReadPropConfig(node, scr))
480 node->mode = MODE_PROP;
481 node->scr = scr;
482 node->count = 1;
483 AddTail((struct List*)&dt_list,(struct Node*)node);
484 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
485 return node;
487 else
489 FreePropConfig(node);
492 else
494 if ((node->o = LoadPicture(filename,scr)))
496 struct BitMapHeader *bmhd;
497 GetDTAttrs(node->o,PDTA_BitMapHeader, (IPTR)&bmhd, TAG_DONE);
498 D(bug("picture %lx\n", node->o));
500 if (bmhd)
502 node->width = bmhd->bmh_Width;
503 node->height = bmhd->bmh_Height;
504 node->mask = bmhd->bmh_Masking;
505 D(bug("picture %lx = %ldx%ld\n", node->o, node->width, node->height));
507 node->scr = scr;
508 node->count = 1;
509 AddTail((struct List*)&dt_list,(struct Node*)node);
510 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
511 return node;
514 FreeVec(node->filename);
516 FreeVec(node);
518 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
519 return NULL;
522 void dt_dispose_picture(struct dt_node *node)
524 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
525 if (node && node->count)
527 node->count--;
528 if (!node->count)
530 Remove((struct Node*)node);
531 if (node->mode == MODE_PROP) FreePropConfig(node); else DisposeDTObject(node->o);
532 FreeVec(node->filename);
533 FreeVec(node);
536 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
539 int dt_width(struct dt_node *node)
541 if (node)
542 return node->width;
543 else
544 return 0;
547 int dt_height(struct dt_node *node)
549 if (node)
550 return node->height;
551 else
552 return 0;
556 void dt_put_on_rastport(struct dt_node *node, struct RastPort *rp, int x, int y)
558 struct BitMap *bitmap = NULL;
559 struct pdtBlitPixelArray pa;
560 ULONG depth = 0;
561 ULONG *img;
562 Object *o;
564 o = node->o;
565 if (NULL == o)
566 return;
568 depth = (ULONG) GetBitMapAttr(rp->BitMap, BMA_DEPTH);
569 if ((depth >= 15) && (node->mask == mskHasAlpha))
571 img = (ULONG *) AllocVec(dt_width(node) * dt_height(node) * 4, MEMF_ANY);
572 if (img)
574 pa.MethodID = PDTM_READPIXELARRAY;
575 pa.pbpa_PixelData = (UBYTE *) img;
576 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
577 pa.pbpa_PixelArrayMod = dt_width(node) * 4;
578 pa.pbpa_Left = 0;
579 pa.pbpa_Top = 0;
580 pa.pbpa_Width = dt_width(node);
581 pa.pbpa_Height = dt_height(node);
582 DoMethodA(o, (Msg) &pa);
583 WritePixelArrayAlpha(img, 0, 0, dt_width(node) * 4, rp, x, y, dt_width(node), dt_height(node), 0xffffffff);
584 FreeVec((APTR) img);
587 else
589 GetDTAttrs(o, PDTA_DestBitMap, (IPTR)&bitmap, TAG_DONE);
590 if (NULL == bitmap)
591 GetDTAttrs(o, PDTA_BitMap, (IPTR)&bitmap, TAG_DONE);
593 if (bitmap)
595 APTR mask = NULL;
597 GetDTAttrs(o, PDTA_MaskPlane, (IPTR)&mask, TAG_DONE);
598 if (mask)
600 #ifndef __AROS__
601 MyBltMaskBitMapRastPort(bitmap, 0, 0, rp, x, y,
602 dt_width(node), dt_height(node), 0xe0,
603 (PLANEPTR)mask);
604 #else
605 BltMaskBitMapRastPort(bitmap, 0, 0, rp, x, y,
606 dt_width(node), dt_height(node), 0xe0,
607 (PLANEPTR)mask);
608 #endif
610 else
611 BltBitMapRastPort(bitmap, 0, 0, rp, x, y,
612 dt_width(node), dt_height(node), 0xc0);
617 void dt_put_mim_on_rastport(struct dt_node *node, struct RastPort *rp, int x, int y,int state)
619 struct BitMap *bitmap = NULL;
620 struct pdtBlitPixelArray pa;
621 ULONG depth = 0;
622 ULONG *img;
624 Object *o;
626 o = node->o;
627 if (NULL == o)
628 return;
629 int width = dt_width(node) >> 1;
630 depth = (ULONG) GetBitMapAttr(rp->BitMap, BMA_DEPTH);
631 if ((depth >= 15) && (node->mask == mskHasAlpha))
633 img = (ULONG *) AllocVec(dt_width(node) * dt_height(node) * 4, MEMF_ANY);
634 if (img)
637 int height = dt_height(node);
638 pa.MethodID = PDTM_READPIXELARRAY;
639 pa.pbpa_PixelData = (UBYTE *) img;
640 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
641 pa.pbpa_PixelArrayMod = width * 4;
642 pa.pbpa_Left = state * width;
643 pa.pbpa_Top = 0;
644 pa.pbpa_Width = width;
645 pa.pbpa_Height = height;
646 DoMethodA(o, (Msg) &pa);
647 WritePixelArrayAlpha(img, 0, 0, width * 4, rp, x, y, width , height , 0xffffffff);
648 FreeVec((APTR) img);
651 else
653 GetDTAttrs(o, PDTA_DestBitMap, (IPTR)&bitmap, TAG_DONE);
654 if (NULL == bitmap)
655 GetDTAttrs(o, PDTA_BitMap, (IPTR)&bitmap, TAG_DONE);
658 if (bitmap)
660 APTR mask = NULL;
662 GetDTAttrs(o, PDTA_MaskPlane, (IPTR)&mask, TAG_DONE);
663 if (mask)
665 #ifndef __AROS__
666 MyBltMaskBitMapRastPort(bitmap, width*state, 0, rp, x, y,
667 width, dt_height(node), 0xe0,
668 (PLANEPTR)mask);
669 #else
670 BltMaskBitMapRastPort(bitmap, width*state, 0, rp, x, y,
671 width, dt_height(node), 0xe0,
672 (PLANEPTR)mask);
673 #endif
675 else
676 BltBitMapRastPort(bitmap, width*state, 0, rp, x, y,
677 width, dt_height(node), 0xc0);
685 #define RECTSIZEX(r) ((r)->MaxX-(r)->MinX+1)
686 #define RECTSIZEY(r) ((r)->MaxY-(r)->MinY+1)
688 #define MOD(x,y) ((x)<0 ? (y)-((-(x))%(y)) : (x)%(y))
690 struct BackFillMsg
692 struct Layer *Layer;
693 struct Rectangle Bounds;
694 LONG OffsetX;
695 LONG OffsetY;
698 struct BackFillOptions
700 WORD MaxCopyWidth; // maximum width for the copy
701 WORD MaxCopyHeight; // maximum height for the copy
702 // BOOL CenterX; // center the tiles horizontally?
703 // BOOL CenterY; // center the tiles vertically?
704 WORD OffsetX; // offset to add
705 WORD OffsetY; // offset to add
706 BOOL OffsetTitleY; // add the screen titlebar height to the vertical offset?
709 struct BackFillInfo
711 struct Hook Hook;
712 WORD Width;
713 WORD Height;
714 struct BitMap *BitMap;
715 /* struct Screen *Screen; */ /* Needed for centering */
716 WORD CopyWidth;
717 WORD CopyHeight;
718 struct BackFillOptions Options;
719 WORD OffsetX;
720 WORD OffsetY;
724 static void CopyTiledBitMap(struct BitMap *Src,WORD SrcOffsetX,WORD SrcOffsetY,WORD SrcSizeX,WORD SrcSizeY,struct BitMap *Dst,struct Rectangle *DstBounds)
726 WORD FirstSizeX; // the width of the rectangle to blit as the first column
727 WORD FirstSizeY; // the height of the rectangle to blit as the first row
728 WORD SecondMinX; // the left edge of the second column
729 WORD SecondMinY; // the top edge of the second column
730 WORD SecondSizeX; // the width of the second column
731 WORD SecondSizeY; // the height of the second column
732 WORD Pos; // used as starting position in the "exponential" blit
733 WORD Size; // used as bitmap size in the "exponential" blit
735 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
736 SecondMinX = DstBounds->MinX+FirstSizeX; // the start for the second tile (if used)
737 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)
739 FirstSizeY = MIN(SrcSizeY-SrcOffsetY,RECTSIZEY(DstBounds)); // the same values are calculated for y direction
740 SecondMinY = DstBounds->MinY+FirstSizeY;
741 SecondSizeY = MIN(SrcOffsetY,DstBounds->MaxY-SecondMinY+1);
743 BltBitMap(Src,SrcOffsetX,SrcOffsetY,Dst,DstBounds->MinX,DstBounds->MinY,FirstSizeX,FirstSizeY,0xC0,-1,NULL); // blit the first piece of the tile
744 if (SecondSizeX>0) // if SrcOffset was 0 or the dest rect was to narrow, we won't need a second column
745 BltBitMap(Src,0,SrcOffsetY,Dst,SecondMinX,DstBounds->MinY,SecondSizeX,FirstSizeY,0xC0,-1,NULL);
746 if (SecondSizeY>0) // is a second row necessary?
748 BltBitMap(Src,SrcOffsetX,0,Dst,DstBounds->MinX,SecondMinY,FirstSizeX,SecondSizeY,0xC0,-1,NULL);
749 if (SecondSizeX>0)
750 BltBitMap(Src,0,0,Dst,SecondMinX,SecondMinY,SecondSizeX,SecondSizeY,0xC0,-1,NULL);
753 // this loop generates the first row of the tiles
754 for (Pos = DstBounds->MinX+SrcSizeX,Size = MIN(SrcSizeX,DstBounds->MaxX-Pos+1);Pos<=DstBounds->MaxX;)
756 BltBitMap(Dst,DstBounds->MinX,DstBounds->MinY,Dst,Pos,DstBounds->MinY,Size,MIN(SrcSizeY,RECTSIZEY(DstBounds)),0xC0,-1,NULL);
757 Pos += Size;
758 Size = MIN(Size<<1,DstBounds->MaxX-Pos+1);
761 // this loop blit the first row down several times to fill the whole dest rect
762 for (Pos = DstBounds->MinY+SrcSizeY,Size = MIN(SrcSizeY,DstBounds->MaxY-Pos+1);Pos<=DstBounds->MaxY;)
764 BltBitMap(Dst,DstBounds->MinX,DstBounds->MinY,Dst,DstBounds->MinX,Pos,RECTSIZEX(DstBounds),Size,0xC0,-1,NULL);
765 Pos += Size;
766 Size = MIN(Size<<1,DstBounds->MaxY-Pos+1);
770 AROS_UFH3S(void, WindowPatternBackFillFunc,
771 AROS_UFHA(struct Hook *, Hook, A0),
772 AROS_UFHA(struct RastPort *, RP, A2),
773 AROS_UFHA(struct BackFillMsg *, BFM, A1))
775 AROS_USERFUNC_INIT
777 WORD OffsetX; // the offset within the tile in x direction
778 WORD OffsetY; // the offset within the tile in y direction
780 struct BackFillInfo *BFI = (struct BackFillInfo *)Hook; // get the data for our backfillhook
782 #ifdef __SASC
783 putreg(12,(long)Hook->h_Data);
784 #endif
786 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)
787 // if (BFI->Options.CenterX) // horizontal centering?
788 // OffsetX -= (BFI->Screen->Width-BFI->Width)/2;
790 OffsetY = BFM->Bounds.MinY-BFI->Options.OffsetY; // The same values are calculated for y direction
793 if (BFI->Options.OffsetTitleY) // shift the tiles down?
794 OffsetY -= BFI->Screen->BarHeight+1;
797 // if (BFI->Options.CenterY) // horizontal centering?
798 // OffsetY -= (BFI->Screen->Height - BFI->Height)/2;
800 CopyTiledBitMap(BFI->BitMap,MOD(OffsetX+BFI->OffsetX,BFI->Width),MOD(OffsetY+BFI->OffsetY,BFI->Height),BFI->CopyWidth,BFI->CopyHeight,RP->BitMap,&BFM->Bounds);
802 AROS_USERFUNC_EXIT
805 static void CalculateCopySizes(struct BackFillInfo *BFI)
807 BFI->CopyWidth = (BFI->Width>BFI->Options.MaxCopyWidth) ? BFI->Width : BFI->Options.MaxCopyWidth-BFI->Options.MaxCopyWidth%BFI->Width;
808 BFI->CopyHeight = (BFI->Height>BFI->Options.MaxCopyHeight) ? BFI->Height : BFI->Options.MaxCopyHeight-BFI->Options.MaxCopyHeight%BFI->Height;
811 **********************************************************/
813 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)
815 struct Screen *scr = node->scr;
816 struct BitMap *bitmap;
817 Object *o;
819 o = node->o;
820 if (!o) return;
822 GetDTAttrs(o, PDTA_DestBitMap, (IPTR)&bitmap, TAG_DONE);
823 if (NULL == bitmap)
824 GetDTAttrs(o, PDTA_BitMap, (IPTR)&bitmap, TAG_DONE);
825 if (NULL == bitmap)
826 return;
828 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
830 if (!node->bfi)
832 struct BackFillInfo *bfi = (struct BackFillInfo*)AllocVec(sizeof(struct BackFillInfo),MEMF_CLEAR);
833 if (bfi)
835 LONG depth = GetBitMapAttr(bitmap,BMA_DEPTH);
836 bfi->Hook.h_Entry = (ULONG (*)())WindowPatternBackFillFunc;
837 #ifdef __SASC
838 bfi->Hook.h_Data = (APTR)getreg(12); /* register A4 */
839 #endif
841 bfi->Options.MaxCopyWidth = 256;
842 bfi->Options.MaxCopyHeight = 256;
843 // bfi->Options.CenterX = FALSE; /* center the tiles horizontally? */
844 // bfi->Options.CenterY = FALSE; /* center the tiles vertically? */
845 bfi->Options.OffsetX = 0; /* offset to add */
846 bfi->Options.OffsetY = 0; /* offset to add */
847 bfi->Options.OffsetTitleY = TRUE; /* add the screen titlebar height to the vertical offset? */
848 bfi->Width = dt_width(node);
849 bfi->Height = dt_height(node);
851 CalculateCopySizes(bfi);
853 if((bfi->BitMap = AllocBitMap(bfi->CopyWidth,bfi->CopyHeight,depth, BMF_INTERLEAVED|BMF_MINPLANES,scr->RastPort.BitMap)))
855 struct Rectangle CopyBounds;
856 CopyBounds.MinX = 0;
857 CopyBounds.MinY = 0;
858 CopyBounds.MaxX = bfi->CopyWidth-1;
859 CopyBounds.MaxY = bfi->CopyHeight-1;
861 CopyTiledBitMap(bitmap,0,0,bfi->Width,bfi->Height,bfi->BitMap,&CopyBounds);
864 node->bfi = bfi;
867 if (node->bfi)
869 struct BackFillInfo *bfi = node->bfi;
870 struct Rectangle rect;
872 rect.MinX = x1;
873 rect.MinY = y1;
874 rect.MaxX = x2;
875 rect.MaxY = y2;
877 if (rp->Layer)
879 LockLayer(0, rp->Layer);
880 xoffset -= rp->Layer->bounds.MinX;
881 yoffset -= rp->Layer->bounds.MinY;
884 bfi->OffsetX = xoffset;
885 bfi->OffsetY = yoffset;
887 DoHookClipRects((struct Hook*)bfi,rp,&rect);
889 if (rp->Layer)
891 UnlockLayer(rp->Layer);
894 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);