Added a test for MUIA_Listview_SelectChange.
[AROS.git] / rom / hyperlayers / basicfuncs.c
blobcfaa41648576e2b8f4aff7d16ad3e839b9a47b38
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Basic support functions for layers.library.
6 Lang: English.
7 */
9 #include <aros/config.h>
10 #include <aros/asmcall.h>
11 #include <exec/memory.h>
12 #include <graphics/rastport.h>
13 #include <graphics/clip.h>
14 #include <graphics/regions.h>
15 #include <graphics/layers.h>
16 #include <graphics/gfx.h>
17 #include <utility/hooks.h>
18 #include <setjmp.h>
20 #include <proto/exec.h>
21 #include <proto/alib.h>
22 #include <proto/graphics.h>
23 #include <proto/layers.h>
24 #include <proto/arossupport.h>
26 #include "layers_intern.h"
27 #include "basicfuncs.h"
29 #define CLIPRECTS_OUTSIDE_OF_SHAPE 1
31 #define SCROLLSIGN +
34 * Sections:
36 * + Blitter
37 * + Hook
38 * + Layer
39 * + LayerInfo
40 * + Rectangle
41 * + Resource Handling
42 * + Miscellaneous
46 /***************************************************************************/
47 /* BLITTER */
48 /***************************************************************************/
50 #define CR2NR_NOBITMAP 0
51 #define CR2NR_BITMAP 1
53 #if !(AROS_FLAVOUR & AROS_FLAVOUR_NATIVE)
55 * These functions cause the infamous "fixed or forbidden register was spilled"
56 * bug/feature in m68k gcc, so these were written straight in asm. They can be
57 * found in config/m68k-native/layers, for the m68k AROSfA target. Other targets,
58 * that use stack passing, can use these versions.
61 void BltRPtoCR(struct RastPort * rp,
62 struct ClipRect * cr,
63 ULONG Mode,
64 struct LayersBase * LayersBase)
66 BltBitMap(rp->BitMap,
67 cr->bounds.MinX,
68 cr->bounds.MinY,
69 cr->BitMap,
70 ALIGN_OFFSET(cr->bounds.MinX), 0,
71 cr->bounds.MaxX - cr->bounds.MinX + 1,
72 cr->bounds.MaxY - cr->bounds.MinY + 1,
73 Mode,
74 ~0,
75 NULL);
79 void BltCRtoRP(struct RastPort * rp,
80 struct ClipRect * cr,
81 ULONG Mode,
82 struct LayersBase * LayersBase)
84 BltBitMap(cr->BitMap,
85 ALIGN_OFFSET(cr->bounds.MinX),
87 rp->BitMap,
88 cr->bounds.MinX,
89 cr->bounds.MinY,
90 cr->bounds.MaxX - cr->bounds.MinX + 1,
91 cr->bounds.MaxY - cr->bounds.MinY + 1,
92 Mode,
93 ~0,
94 NULL);
98 #endif /* if !native */
100 /***************************************************************************/
101 /* HOOK */
102 /***************************************************************************/
104 struct layerhookmsg
106 struct Layer *l;
107 /* struct Rectangle rect; (replaced by the next line!) */
108 WORD MinX, MinY, MaxX, MaxY;
109 LONG OffsetX, OffsetY;
112 void _CallLayerHook(struct Hook * h,
113 struct RastPort * rp,
114 struct Layer * L,
115 struct Rectangle * R,
116 WORD offsetX,
117 WORD offsetY,
118 struct LayersBase * LayersBase)
120 struct BitMap * bm = rp->BitMap;
122 if (L)
124 if (IL(L)->intflags & INTFLAG_AVOID_BACKFILL) return;
127 if (h == LAYERS_BACKFILL)
129 /* Use default backfill, which means that I will clear the area */
130 BltBitMap(bm,
134 R->MinX,
135 R->MinY,
136 R->MaxX - R->MinX + 1,
137 R->MaxY - R->MinY + 1,
138 0x000,
139 0xff,
140 NULL);
141 /* that's it */
142 return;
145 if (h != LAYERS_NOBACKFILL)
147 struct layerhookmsg msg;
148 msg.l = L;
149 msg.MinX = R->MinX;
150 msg.MinY = R->MinY;
151 msg.MaxX = R->MaxX;
152 msg.MaxY = R->MaxY;
153 msg.OffsetX = offsetX;
154 msg.OffsetY = offsetY;
156 AROS_UFC3NR(void, h->h_Entry,
157 AROS_UFCA(struct Hook *, h ,A0),
158 AROS_UFCA(struct RastPort *, rp ,A2),
159 AROS_UFCA(struct layerhookmsg *, &msg,A1)
166 /***************************************************************************/
167 /* LAYER */
168 /***************************************************************************/
171 * Free a layer and all its associated structures
173 void _FreeLayer(struct Layer * l, struct LayersBase *LayersBase)
175 struct ClipRect * cr = l->ClipRect, * _cr;
177 while (cr)
179 if (cr->BitMap)
180 FreeBitMap(cr->BitMap);
181 _cr = cr->Next;
183 FreePooled(LayersBase->lb_ClipRectPool, cr, sizeof(struct ClipRect));
185 cr = _cr;
189 * also free all backed up cliprects.
191 cr = l->SuperSaveClipRects;
193 while (cr)
195 _cr = cr->Next;
196 FreePooled(LayersBase->lb_ClipRectPool, cr, sizeof(struct ClipRect));
198 cr = _cr;
201 DisposeRegion(l->DamageList);
202 DisposeRegion(l->VisibleRegion);
203 DisposeRegion(l->shape);
204 DisposeRegion(l->visibleshape);
206 FreeMem(l, sizeof(struct IntLayer));
211 /***************************************************************************/
212 /* LAYERINFO */
213 /***************************************************************************/
215 /*-------------------------------------------------------------------------*/
217 * Allocate LayerInfo_extra and initialize its resource list. Layers uses
218 * this resource list to keep track of various memory allocations it makes
219 * for the layers. See ResourceNode and ResData in layers_intern.h for the
220 * node structure. See AddLayersResource for more information on the basic
221 * operation.
223 BOOL _AllocExtLayerInfo(struct Layer_Info * li, struct LayersBase *LayersBase)
225 if(++li->fatten_count != 0)
226 return TRUE;
228 if(!(li->LayerInfo_extra = AllocMem(sizeof(struct LayerInfo_extra),MEMF_PUBLIC|MEMF_CLEAR)))
229 return FALSE;
231 NewList((struct List *)&((struct LayerInfo_extra *)li->LayerInfo_extra)->lie_ResourceList);
233 return TRUE;
237 * Free LayerInfo_extra.
239 void _FreeExtLayerInfo(struct Layer_Info * li, struct LayersBase *LayersBase)
241 if(--li->fatten_count >= 0)
242 return;
244 /* Kill Root Layer */
246 if (li->check_lp)
247 DeleteLayer(0UL, li->check_lp);
248 li->check_lp = NULL;
250 if(li->LayerInfo_extra == NULL)
251 return;
253 FreeMem(li->LayerInfo_extra, sizeof(struct LayerInfo_extra));
255 li->LayerInfo_extra = NULL;
259 * Dynamically allocate LayerInfo_extra if it isn't already there.
261 BOOL SafeAllocExtLI(struct Layer_Info * li,
262 struct LayersBase * LayersBase)
264 LockLayerInfo(li);
266 /* Check to see if we can ignore the rest of this call. :-) */
267 if(li->Flags & NEWLAYERINFO_CALLED)
268 return TRUE;
270 if(_AllocExtLayerInfo(li, LayersBase))
271 return TRUE;
273 UnlockLayerInfo(li);
275 return FALSE;
279 * Free LayerInfo_extra if it was dynamically allocated, and unlock the LI.
281 void SafeFreeExtLI(struct Layer_Info * li,
282 struct LayersBase * LayersBase)
284 if(!(li->Flags & NEWLAYERINFO_CALLED))
285 _FreeExtLayerInfo(li, LayersBase);
287 UnlockLayerInfo(li);
290 /***************************************************************************/
291 /* RECTANGLE */
292 /***************************************************************************/
295 #define MAX(a,b) ((a) > (b) ? (a) : (b))
296 #define MIN(a,b) ((a) < (b) ? (a) : (b))
298 void _TranslateRect(struct Rectangle *rect, WORD dx, WORD dy)
300 rect->MinX += dx;
301 rect->MinY += dy;
302 rect->MaxX += dx;
303 rect->MaxY += dy;
307 /***************************************************************************/
308 /* RESOURCE HANDLING */
309 /***************************************************************************/
312 * Allocate memory for a ClipRect.
315 struct ClipRect * _AllocClipRect(struct Layer * L, struct LayersBase *LayersBase)
317 struct ClipRect * CR;
319 CR = L->SuperSaveClipRects;
321 if (NULL != CR)
323 /* I want to access the list of free ClipRects alone */
324 L->SuperSaveClipRects = CR->Next;
325 L->SuperSaveClipRectCounter--;
327 CR->Flags = 0;
328 CR->Next = NULL;
329 CR->lobs = NULL;
330 CR->BitMap = NULL;
331 return CR;
334 return AllocPooled(LayersBase->lb_ClipRectPool, sizeof(struct ClipRect));
338 * Return memory of a ClipRect for later use.
341 void _FreeClipRect(struct ClipRect * CR,
342 struct Layer * L,
343 struct LayersBase * LayersBase)
345 if (L->SuperSaveClipRectCounter < MAXSUPERSAVECLIPRECTS)
347 /* Add the ClipRect to the front of the list */
348 CR -> Next = L -> SuperSaveClipRects;
349 L -> SuperSaveClipRects = CR;
350 L -> SuperSaveClipRectCounter++;
352 else
354 FreePooled(LayersBase->lb_ClipRectPool, CR, sizeof(struct ClipRect));
359 * Free a whole list of cliprects including the allocated bitmaps (if any)
362 void _FreeClipRectListBM(struct Layer * L,
363 struct ClipRect * CR,
364 struct LayersBase *LayersBase)
366 struct ClipRect * _CR = CR;
367 BOOL isSmart;
368 if ((L->Flags & (LAYERSUPER|LAYERSMART)) == LAYERSMART)
369 isSmart = TRUE;
370 else
371 isSmart = FALSE;
374 * This function is not watching for the upper limit of
375 * pre allocated cliprects.
377 L->SuperSaveClipRectCounter++;
379 while (TRUE)
381 if (NULL != _CR->BitMap && TRUE == isSmart)
383 FreeBitMap(_CR->BitMap);
384 _CR->BitMap = NULL;
386 if (NULL != _CR->Next)
388 L->SuperSaveClipRectCounter++;
389 _CR = _CR->Next;
391 else
392 break;
394 /* _CR is the last ClipRect in the list. I concatenate the
395 currently preallocated list of ClipRects with that list. */
396 _CR->Next = L->SuperSaveClipRects;
398 /* CR is the head of the ClipRect list now */
399 L->SuperSaveClipRects = CR;
403 /***************************************************************************/
404 /* MISCELLANEOUS */
405 /***************************************************************************/
407 struct ClipRect * _CreateClipRectsFromRegion(struct Region *r,
408 struct Layer * l,
409 int invisible,
410 struct Region * inverter,
411 struct LayersBase *LayersBase)
413 int looped = FALSE;
414 struct ClipRect * firstcr = NULL, * cr;
415 struct BitMap * display_bm = l->rp->BitMap;
418 * From region r create cliprects
420 while (1)
422 struct RegionRectangle * rr = r->RegionRectangle;
423 while (rr)
425 cr = _AllocClipRect(l, LayersBase);
426 cr->bounds.MinX = rr->bounds.MinX + r->bounds.MinX;
427 cr->bounds.MinY = rr->bounds.MinY + r->bounds.MinY;
428 cr->bounds.MaxX = rr->bounds.MaxX + r->bounds.MinX;
429 cr->bounds.MaxY = rr->bounds.MaxY + r->bounds.MinY;
430 cr->lobs = (struct Layer *)(IPTR)invisible;
431 cr->Next = firstcr;
433 if (TRUE == invisible && IS_SMARTREFRESH(l))
435 cr->BitMap = AllocBitMap(
436 cr->bounds.MaxX - cr->bounds.MinX + 1 + 16,
437 cr->bounds.MaxY - cr->bounds.MinY + 1,
438 display_bm->Depth,
439 BMF_CLEAR,
440 display_bm);
443 #if 0
444 kprintf("\t\t%s: Created cliprect %d/%d-%d/%d invisible: %d\n",
445 __FUNCTION__,
446 cr->bounds.MinX,
447 cr->bounds.MinY,
448 cr->bounds.MaxX,
449 cr->bounds.MaxY,
450 invisible);
451 #endif
453 firstcr = cr;
455 rr = rr->Next;
458 if (FALSE == looped)
461 * Flip the shape to the opposite part and
462 * limit it to its own shape.
464 if (inverter)
465 XorRegionRegion(inverter, r);
466 else
467 XorRectRegion(r,&l->bounds);
469 #if !CLIPRECTS_OUTSIDE_OF_SHAPE
470 AndRegionRegion(l->shape,r);
471 #else
472 AndRectRegion(r,&l->bounds);
473 #endif
474 if (TRUE == invisible)
475 invisible = FALSE;
476 else
477 invisible = TRUE;
478 looped = TRUE;
480 else
481 break;
482 } /* while (1) */
484 return firstcr;
488 int _CopyClipRectsToClipRects(struct Layer * l,
489 struct ClipRect * oldcr,
490 struct ClipRect * newcr,
491 int srcdx,
492 int destdx,
493 int backupmode,
494 int freelist,
495 int addtodamagelist,
496 struct LayersBase *LayersBase)
498 struct BitMap * display_bm = l->rp->BitMap;
500 while (NULL != oldcr)
502 struct ClipRect * _cr = newcr;
503 int area = RECTAREA(&oldcr->bounds);
504 while ((NULL != _cr) && (0 != area) )
506 struct Rectangle intersect;
509 * Do the two rectangles overlap?
511 if (AndRectRect(&_cr->bounds, &oldcr->bounds, &intersect))
513 LONG xSize = intersect.MaxX - intersect.MinX + 1;
514 LONG ySize = intersect.MaxY - intersect.MinY + 1;
517 * Is this new one supposed to be invisible?
519 if (NULL != _cr->lobs)
521 struct BitMap * srcbm;
523 * The new one is supposed to be invisible.
524 * So for SIMPLEREFRESH layers I don't have to
525 * do anything if
526 * a) not in backupmode or
527 * b) old cr was invisible
529 if (IS_SIMPLEREFRESH(l) && FALSE == backupmode && NULL == _cr->BitMap)
531 if (FALSE == addtodamagelist)
533 struct Rectangle rect = intersect;
535 _TranslateRect(&rect, -l->bounds.MinX, -l->bounds.MinY);
537 /* FIXME:
538 * stegerg: Not sure if this is a good idea. What for example if
539 * updating is done in several passes? And CopyClipRectsToClipRects is
540 * used by all kinds of functions including BeginUpdate/EndUpdate/InstallClipRegion/etc.
542 ClearRectRegion(l->DamageList, &rect);
543 #if 0
544 kprintf("");
545 kprintf("%s: Removing %d/%d-%d/%d from damagelist!\t",
546 __FUNCTION__,
547 rect.MinX,
548 rect.MinY,
549 rect.MaxX,
550 rect.MaxY
552 kprintf("%s: Layer: %d/%d-%d/%d!\n",
553 __FUNCTION__,
554 l->bounds.MinX,
555 l->bounds.MinY,
556 l->bounds.MaxX,
557 l->bounds.MaxY
559 kprintf("%s: oldcr: %d/%d-%d/%d!\t",
560 __FUNCTION__,
561 oldcr->bounds.MinX,
562 oldcr->bounds.MinY,
563 oldcr->bounds.MaxX,
564 oldcr->bounds.MaxY
566 kprintf("%s: _cr: %d/%d-%d/%d!\n\n",
567 __FUNCTION__,
568 _cr->bounds.MinX,
569 _cr->bounds.MinY,
570 _cr->bounds.MaxX,
571 _cr->bounds.MaxY
573 #endif
576 else if (IS_SIMPLEREFRESH(l) && TRUE == backupmode && NULL != oldcr->lobs)
578 if (TRUE == addtodamagelist)
580 struct Rectangle rect = intersect;
581 _TranslateRect(&rect, -l->bounds.MinX, -l->bounds.MinY);
583 // FIXME (if possible)
584 // !!! Also areas where a child disappears beyond the
585 // boundaries of its parent are added here!
586 OrRectRegion(l->DamageList, &rect);
587 #if 0
588 kprintf("_cr->BitMap: %p ,_cr->lobs: %d\n",_cr->BitMap,_cr->lobs);
589 #endif
590 #if 0
591 kprintf("%s: Adding %d/%d-%d/%d to damagelist of l=%p!\t",
592 __FUNCTION__,
593 rect.MinX,
594 rect.MinY,
595 rect.MaxX,
596 rect.MaxY,
599 #endif
600 #if 0
601 kprintf("%s: Layer: %d/%d-%d/%d!\n",
602 __FUNCTION__,
603 l->bounds.MinX,
604 l->bounds.MinY,
605 l->bounds.MaxX,
606 l->bounds.MaxY
608 kprintf("%s: oldcr: %d/%d-%d/%d!\t",
609 __FUNCTION__,
610 oldcr->bounds.MinX,
611 oldcr->bounds.MinY,
612 oldcr->bounds.MaxX,
613 oldcr->bounds.MaxY
615 kprintf("%s: _cr: %d/%d-%d/%d!\n\n",
616 __FUNCTION__,
617 _cr->bounds.MinX,
618 _cr->bounds.MinY,
619 _cr->bounds.MaxX,
620 _cr->bounds.MaxY
622 #endif
623 } else {
624 //kprintf("Not adding to damage list for l=%p!\n",l);
627 else
629 LONG xSrc, xDest;
630 LONG ySrc, yDest;
631 struct BitMap * destbm;
633 if (IS_SUPERREFRESH(l))
634 destbm = l->SuperBitMap;
635 else
636 destbm = _cr->BitMap;
639 * Does the source rect have a bitmap (off screen)
640 * or is it on the screen.
642 if (oldcr->lobs && !IS_SUPERREFRESH(l))
645 * Copy from hidden bitmap to hidden bitmap
647 xSrc = (oldcr->bounds.MinX - _cr->bounds.MinX);
648 if (xSrc < 0)
651 * oldcr is further to the left
653 xSrc = -xSrc;
654 xDest = 0;
656 else
659 * oldcr is further to the right
661 xDest = xSrc;
662 xSrc = 0;
665 xSrc += ALIGN_OFFSET(oldcr->bounds.MinX + srcdx);
666 xDest += ALIGN_OFFSET(_cr->bounds.MinX + destdx);
668 ySrc = (oldcr->bounds.MinY - _cr->bounds.MinY);
669 if (ySrc < 0)
671 ySrc = -ySrc;
672 yDest = 0;
674 else
676 yDest = ySrc;
677 ySrc = 0;
679 //kprintf("Using old cr's BitMap!\n");
680 srcbm = oldcr->BitMap;
682 else
685 * Copy from screen.
687 if (oldcr->bounds.MinX > _cr->bounds.MinX)
689 xSrc = oldcr->bounds.MinX;
690 if (IS_SUPERREFRESH(l))
691 xDest = (oldcr->bounds.MinX - _cr->bounds.MinX) SCROLLSIGN l->Scroll_X;
692 else
693 xDest = (oldcr->bounds.MinX - _cr->bounds.MinX) + ALIGN_OFFSET((_cr->bounds.MinX + destdx));
695 else
697 xSrc = _cr->bounds.MinX;
698 if (IS_SUPERREFRESH(l))
699 xDest = SCROLLSIGN l->Scroll_X;
700 else
701 xDest = ALIGN_OFFSET((_cr->bounds.MinX + destdx));
704 if (oldcr->bounds.MinY > _cr->bounds.MinY)
706 ySrc = oldcr->bounds.MinY;
707 yDest = oldcr->bounds.MinY - _cr->bounds.MinY;
708 if (IS_SUPERREFRESH(l))
709 yDest = yDest SCROLLSIGN l->Scroll_Y;
711 else
713 ySrc = _cr->bounds.MinY;
714 yDest = 0;
715 if (IS_SUPERREFRESH(l))
716 yDest = yDest SCROLLSIGN l->Scroll_Y;
719 srcbm = l->rp->BitMap;
720 //kprintf("Using bitmap of screen!\n");
723 if (IS_SIMPLEREFRESH(l) &&
724 NULL == _cr->BitMap &&
725 TRUE == backupmode)
728 * Get a bitmap (if not there) and make a backup
730 _cr->BitMap = AllocBitMap(
731 _cr->bounds.MaxX - _cr->bounds.MinX + 1 + 16 ,
732 _cr->bounds.MaxY - _cr->bounds.MinY + 1,
733 display_bm->Depth,
734 BMF_CLEAR,
735 display_bm);
736 destbm = _cr->BitMap;
739 BltBitMap(srcbm,
740 xSrc,
741 ySrc,
742 destbm,
743 xDest,
744 yDest,
745 xSize,
746 ySize,
747 0x0c0,
748 0xff,
749 NULL);
750 #if 0
751 kprintf("%s: backing up: from %d/%d to %d/%d width:%d, height: %d\n",
752 __FUNCTION__,
753 xSrc,
754 ySrc,
755 xDest,
756 yDest,
757 xSize,
758 ySize);
759 #endif
761 area -= (xSize * ySize);
765 else //if (FALSE == backupmode)
768 * The new one is visible. if the old one was not visible
769 * then I have to show it.
770 * If it is a simple refresh layer and it has it
771 * backed up (only when moving!) then I must show
772 * this. If it has nothing backed up then I must
773 * add a part to the damage list.
775 if (IS_SIMPLEREFRESH(l) &&
776 (NULL != oldcr->lobs) &&
777 (NULL == oldcr->BitMap))
779 if (NULL != oldcr->lobs && NULL == oldcr->BitMap)
781 struct Rectangle rect = intersect;
783 _CallLayerHook(l->BackFill,
784 l->rp,
786 &rect,
787 rect.MinX,
788 rect.MinY,
789 LayersBase);
790 _TranslateRect(&rect, -l->bounds.MinX, -l->bounds.MinY);
791 OrRectRegion(l->DamageList, &rect);
792 #if 0
793 kprintf("Adding: %d\n",addtodamagelist);
794 kprintf("%s: Adding %d/%d-%d/%d to damagelist!\t",
795 __FUNCTION__,
796 rect.MinX,
797 rect.MinY,
798 rect.MaxX,
799 rect.MaxY
801 kprintf("%s: Layer: %d/%d-%d/%d!\n",
802 __FUNCTION__,
803 l->bounds.MinX,
804 l->bounds.MinY,
805 l->bounds.MaxX,
806 l->bounds.MaxY
808 kprintf("%s: oldcr: %d/%d-%d/%d!\t",
809 __FUNCTION__,
810 oldcr->bounds.MinX,
811 oldcr->bounds.MinY,
812 oldcr->bounds.MaxX,
813 oldcr->bounds.MaxY
815 kprintf("%s: _cr: %d/%d-%d/%d!\n",
816 __FUNCTION__,
817 _cr->bounds.MinX,
818 _cr->bounds.MinY,
819 _cr->bounds.MaxX,
820 _cr->bounds.MaxY
822 #endif
825 else
827 //kprintf("%s: Showing a part of a backed up bitmap!\n",__FUNCTION__);
828 if (NULL != oldcr->lobs)
831 * Copy out of hidden bitmap
833 LONG xSrc, xDest;
834 LONG ySrc, yDest;
835 struct BitMap * srcbm;
837 if (IS_SUPERREFRESH(l))
838 srcbm = l->SuperBitMap;
839 else
840 srcbm = oldcr->BitMap;
843 * I have to make the old one visible
844 * two cases left: SMART REFRESH and SUPERBITMAP
847 if (!IS_SUPERREFRESH(l))
850 * Copy from hidden BitMap to screen!
851 * If a simple refresh layer is moved it might
852 * also have a BitMap!!!
854 xSrc = (oldcr->bounds.MinX - _cr->bounds.MinX);
855 if (xSrc < 0)
858 * old cr is further to the left
860 xSrc = -xSrc + ALIGN_OFFSET(oldcr->bounds.MinX + srcdx);
861 xDest = _cr->bounds.MinX;
863 else
866 * oldcr is further to the right
868 xDest = oldcr->bounds.MinX;
869 xSrc = ALIGN_OFFSET(oldcr->bounds.MinX + srcdx);
872 ySrc = (oldcr->bounds.MinY - _cr->bounds.MinY);
873 if (ySrc < 0)
875 ySrc = -ySrc;
876 yDest = _cr->bounds.MinY;
878 else
880 yDest = oldcr->bounds.MinY;
881 ySrc = 0;
884 else
887 * superbitmap layer
889 xSrc = (oldcr->bounds.MinX > _cr->bounds.MinX) ?
890 oldcr->bounds.MinX - _cr->bounds.MinX SCROLLSIGN l->Scroll_X :
891 _cr->bounds.MinX - oldcr->bounds.MinX SCROLLSIGN l->Scroll_X;
892 xDest = _cr->bounds.MinX;
894 ySrc = (oldcr->bounds.MinY > _cr->bounds.MinY) ?
895 oldcr->bounds.MinY - _cr->bounds.MinY SCROLLSIGN l->Scroll_Y :
896 _cr->bounds.MinY - oldcr->bounds.MinY SCROLLSIGN l->Scroll_Y;
897 yDest = _cr->bounds.MinY;
901 #if 0
902 kprintf("\t\t%s: Show cliprect: %d/%d-%d/%d; blitting to %d/%d _cr->lobs: %d\n",
903 __FUNCTION__,
904 oldcr->bounds.MinX,
905 oldcr->bounds.MinY,
906 oldcr->bounds.MaxX,
907 oldcr->bounds.MaxY,
908 xDest,
909 yDest,
910 _cr->lobs);
911 #endif
913 /* FIXME: Must have oldcr->BitMap also for SuperBitMap layers! */
915 BltBitMap(srcbm,
916 xSrc,
917 ySrc,
918 l->rp->BitMap,
919 xDest,
920 yDest,
921 xSize,
922 ySize,
923 0x0c0,
924 0xff,
925 NULL);
927 } /* if was hidden cliprect */
928 } /* if is simple else ... */
929 } /* if new cliprect is visible or invisible */
930 } /* if rectangles overlap */
931 else
934 if (IS_SMARTREFRESH(l) && TRUE == backupmode && NULL == _cr->BitMap && NULL != _cr->lobs)
936 _cr->BitMap = AllocBitMap(_cr->bounds.MaxX - _cr->bounds.MinX + 1 + 16 ,
937 _cr->bounds.MaxY - _cr->bounds.MinY + 1,
938 display_bm->Depth,
939 BMF_CLEAR,
940 display_bm);
943 _cr = _cr->Next;
944 } /* all new cliprects */
946 if (TRUE == freelist)
948 _cr = oldcr->Next;
949 if (oldcr->BitMap)
950 FreeBitMap(oldcr->BitMap);
951 _FreeClipRect(oldcr, l, LayersBase);
952 oldcr = _cr;
954 else
955 oldcr = oldcr->Next;
956 } /* for all old cliprects */
958 if (IS_EMPTYREGION(l->DamageList))
959 l->Flags &= ~LAYERREFRESH;
960 else
961 l->Flags |= LAYERREFRESH;
964 * If this is a simple refresh layer and I am not in
965 * backup mode and I am not adding to the damagelist
966 * then I must call the backfillhook for the
967 * area of the damage list of a simple refresh layer
970 if (IS_SIMPLEREFRESH(l) &&
971 (l->Flags & LAYERREFRESH) &&
972 FALSE == backupmode &&
973 FALSE == addtodamagelist)
975 struct Region * dr = l->DamageList;
976 struct RegionRectangle * rr;
978 _TranslateRect(&dr->bounds, l->bounds.MinX, l->bounds.MinY);
979 AndRectRegion(dr, &l->bounds);
980 AndRegionRegion(l->VisibleRegion, dr);
981 AndRegionRegion(l->visibleshape, dr);
983 _TranslateRect(&dr->bounds, -l->bounds.MinX, -l->bounds.MinY);
985 rr = dr->RegionRectangle;
986 while (rr)
988 _TranslateRect(&rr->bounds,
989 dr->bounds.MinX + l->bounds.MinX,
990 dr->bounds.MinY + l->bounds.MinY);
992 _CallLayerHook(l->BackFill,
993 l->rp,
995 &rr->bounds,
996 rr->bounds.MinX,
997 rr->bounds.MinY,
998 LayersBase);
1000 _TranslateRect(&rr->bounds,
1001 -dr->bounds.MinX-l->bounds.MinX,
1002 -dr->bounds.MinY-l->bounds.MinY);
1003 rr = rr->Next;
1008 return TRUE;
1012 * Backup any parts of the layer that overlap with the backup_region
1013 * and that are not already backed up. Create the cliprects and
1014 * bitmaps if necessary.
1015 * Assumption: Only visible parts become invisible,
1016 * invisible parts will not become visible.
1018 * This function MUST not manipulate hide_region!!!!
1020 int _BackupPartsOfLayer(struct Layer * l,
1021 struct Region * hide_region,
1022 int dx,
1023 int backupsimplerefresh,
1024 struct LayersBase * LayersBase)
1026 struct ClipRect * newcr;
1027 struct Region *r, * clipregion;
1030 * Uninstall clipping region. This causes all pixels to
1031 * be copied into the cliprects that cover the complete
1032 * area of the layer.
1035 clipregion = _InternalInstallClipRegion(l, NULL, 0, 0, LayersBase);
1037 ClearRegionRegion(hide_region,l->VisibleRegion);
1038 r = AndRegionRegionND(l->visibleshape, l->VisibleRegion);
1040 if (r)
1042 newcr = _CreateClipRectsFromRegion(r,l,FALSE,NULL,LayersBase);
1043 DisposeRegion(r);
1045 if (newcr)
1047 _CopyClipRectsToClipRects(l,
1048 l->ClipRect /* source */,
1049 newcr /* destination */,
1052 backupsimplerefresh,
1053 TRUE,
1054 TRUE,
1055 LayersBase);
1057 l->ClipRect = newcr;
1062 * Reinstall the clipping region. This causes the
1063 * whole visible area of the layer to be copied
1064 * into the clipping regions cliprects. The
1065 * regular list of cliprects is still maintained.
1067 if (clipregion)
1068 _InternalInstallClipRegion(l, clipregion, dx, dx, LayersBase);
1070 return TRUE;
1074 * Show any parts of the layer that overlap with the backup_region
1075 * and that are not already show.
1077 * This function MUST not manipulate show_region!!!!
1080 int _ShowPartsOfLayer(struct Layer * l,
1081 struct Region * show_region,
1082 struct LayersBase * LayersBase)
1084 struct ClipRect * newcr;
1085 struct Region *r;
1086 struct Region * clipregion;
1088 //kprintf("%s called for %p\n",__FUNCTION__,l);
1091 * If there is a clipping region then the whole
1092 * window is currently backed up in l->ClipRect
1093 * That covers the complete area. I must first
1094 * make these visible, move them back to
1095 * l->_cliprects and recreate the clipping cliprects
1096 * according to the clipregion
1099 if (show_region == l->VisibleRegion)
1100 kprintf("ERROR - same regions!! %s\n",__FUNCTION__);
1102 clipregion = InstallClipRegion(l, NULL);
1104 OrRegionRegion(show_region,l->VisibleRegion);
1105 r = AndRegionRegionND(l->visibleshape, l->VisibleRegion);
1106 if (r != NULL)
1108 newcr = _CreateClipRectsFromRegion(r,l,FALSE,NULL,LayersBase);
1109 DisposeRegion(r);
1111 _CopyClipRectsToClipRects(l,
1112 l->ClipRect /* source */,
1113 newcr /* destination */,
1116 FALSE,
1117 TRUE,
1118 FALSE,
1119 LayersBase);
1122 l->ClipRect = newcr;
1124 if (clipregion)
1125 InstallClipRegion(l, clipregion);
1127 return TRUE;
1130 int _ShowLayer(struct Layer * l, struct LayersBase *LayersBase)
1132 struct Region *r;
1133 struct RegionRectangle * rr;
1134 struct ClipRect * prevcr = NULL;
1135 struct BitMap * bm = l->rp->BitMap;
1136 int invisible = FALSE;
1138 r = AndRegionRegionND(l->shape, l->VisibleRegion);
1139 AndRegionRegion(l->parent->shape, r);
1141 while (1)
1143 rr = r->RegionRectangle;
1145 while (NULL != rr)
1147 struct ClipRect * cr;
1149 cr = (struct ClipRect *)AllocPooled(LayersBase->lb_ClipRectPool, sizeof(struct ClipRect));
1151 //kprintf("\t\tinvisible: %d !!!!!!!!!!!!\n",invisible);
1153 MinX(cr) = MinX(rr) + MinX(r);
1154 MinY(cr) = MinY(rr) + MinY(r);
1155 MaxX(cr) = MaxX(rr) + MinX(r);
1156 MaxY(cr) = MaxY(rr) + MinY(r);
1157 cr->lobs = (struct Layer *)(IPTR)invisible;
1158 #if 0
1159 kprintf("\t\t%s: Created cliprect %d/%d-%d/%d invisible: %d\n",
1160 __FUNCTION__,
1161 cr->bounds.MinX,
1162 cr->bounds.MinY,
1163 cr->bounds.MaxX,
1164 cr->bounds.MaxY,
1165 invisible);
1166 #endif
1167 if (prevcr)
1168 prevcr->Next = cr;
1169 else
1170 l->ClipRect = cr;
1172 prevcr = cr;
1174 if (FALSE == invisible)
1176 #if 0
1177 kprintf("\t\tClearing background! %d/%d-%d/%d bitmap: %p\n",
1178 cr->bounds.MinX,
1179 cr->bounds.MinY,
1180 cr->bounds.MaxX,
1181 cr->bounds.MaxY,
1182 l->rp->BitMap
1184 #endif
1185 if (IS_SUPERREFRESH(l))
1187 BltBitMap(l->SuperBitMap,
1188 cr->bounds.MinX - l->bounds.MinX,
1189 cr->bounds.MinY - l->bounds.MinY,
1190 l->rp->BitMap,
1191 cr->bounds.MinX,
1192 cr->bounds.MinY,
1193 cr->bounds.MaxX - cr->bounds.MinX + 1,
1194 cr->bounds.MaxY - cr->bounds.MinY + 1,
1195 0x0c0,
1196 0xff,
1197 NULL);
1199 else
1201 _CallLayerHook(l->BackFill,
1202 l->rp,
1204 &cr->bounds,
1205 cr->bounds.MinX,
1206 cr->bounds.MinY,
1207 LayersBase);
1210 else
1213 * This part is to be invisible!
1215 if (IS_SMARTREFRESH(l))
1217 cr->BitMap = AllocBitMap(
1218 cr->bounds.MaxX - cr->bounds.MinX + 1 + 16,
1219 cr->bounds.MaxY - cr->bounds.MinY + 1,
1220 bm->Depth,
1221 BMF_CLEAR,
1222 bm);
1224 /* FIXME:
1225 * stegerg: the backfill hook should be called for this bitmap!
1226 * But _CallLayerHook always uses rp->BitMap
1231 rr=rr->Next;
1234 if (FALSE == invisible)
1236 XorRectRegion(r, &l->bounds);
1237 #if !CLIPRECTS_OUTSIDE_OF_SHAPE
1238 AndRegionRegion(l->shape, r);
1239 #endif
1240 invisible = TRUE;
1242 else
1243 break;
1246 DisposeRegion(r);
1248 return TRUE;
1252 * It is assumed that the region r is not needed anymore.
1254 void _BackFillRegion(struct Layer * l,
1255 struct Region * r,
1256 int addtodamagelist,
1257 struct LayersBase * LayersBase)
1259 struct RegionRectangle * RR;
1261 RR = r->RegionRectangle;
1262 if (NULL == RR) return;
1264 if (IS_SIMPLEREFRESH(l))
1266 /* Only for simple refresh layers, becuase smart refresh layers
1267 may have damage outside of visibleshape, like when being dragged
1268 off screen */
1270 AndRegionRegion(l->visibleshape, r);
1272 else
1274 /* Maybe not needed, but to be sure ... */
1276 AndRectRegion(r, &l->bounds);
1280 if (TRUE == addtodamagelist)
1282 l->Flags |= LAYERREFRESH;
1284 #if 1
1285 /* Region coords are screen relative, but damagelist coords are layer relative! */
1287 _TranslateRect(&r->bounds, -l->bounds.MinX, -l->bounds.MinY);
1288 OrRegionRegion(r, l->DamageList);
1289 _TranslateRect(&r->bounds, l->bounds.MinX, l->bounds.MinY);
1291 #else
1292 while (NULL != RR)
1294 struct Rectangle rect = RR->bounds;
1296 //kprintf("%s: adding to damagelist!\n",__FUNCTION__);
1298 /* Region coords are screen relative, but damagelist coords are layer relative! */
1300 _TranslateRect(&rect,
1301 r->bounds.MinX - l->bounds.MinX,
1302 r->bounds.MinY - l->bounds.MinY);
1303 #if 0
1304 kprintf("%s: Adding %d/%d-%d/%d to damagelist!\n",
1305 __FUNCTION__,
1306 rect.MinX,
1307 rect.MinY,
1308 rect.MaxX,
1309 rect.MaxY
1311 #endif
1312 OrRectRegion(l->DamageList, &rect);
1314 _TranslateRect(&rect,
1315 -r->bounds.MinX + l->bounds.MinX,
1316 -r->bounds.MinY + l->bounds.MinY);
1318 RR = RR->Next;
1320 } /* while (NULL != RR) */
1321 #endif
1323 } /* if (TRUE == addtodamagelist) */
1325 AndRegionRegion(l->VisibleRegion, r);
1326 if (l->shaperegion)
1328 /* shaperegion is layer relative, while r is screen relative */
1330 _TranslateRect(&r->bounds, -l->bounds.MinX, -l->bounds.MinY);
1331 AndRegionRegion(l->shaperegion, r);
1332 _TranslateRect(&r->bounds, l->bounds.MinX, l->bounds.MinY);
1335 RR = r->RegionRectangle;
1336 /* check if a region is empty */
1337 while (NULL != RR)
1339 _TranslateRect(&RR->bounds, r->bounds.MinX, r->bounds.MinY);
1341 #if 0
1342 kprintf("\t\t: %s Clearing rect : %d/%d-%d/%d layer: %p, hook: %p, bitmap: %p\n",
1343 __FUNCTION__,
1344 RR->bounds.MinX,
1345 RR->bounds.MinY,
1346 RR->bounds.MaxX,
1347 RR->bounds.MaxY,
1349 l->BackFill,
1350 l->rp->BitMap);
1351 #endif
1352 _CallLayerHook(l->BackFill,
1353 l->rp,
1355 &RR->bounds,
1356 RR->bounds.MinX,
1357 RR->bounds.MinY,
1358 LayersBase);
1359 RR = RR->Next;
1364 struct Region *_InternalInstallClipRegion(struct Layer *l, struct Region *region,
1365 WORD srcdx, WORD destdx,
1366 struct LayersBase *LayersBase)
1368 struct Region * OldRegion;
1369 BOOL updating = FALSE;
1370 OldRegion = l->ClipRegion;
1372 if ((OldRegion != NULL) || (region != NULL))
1374 if (l->Flags & LAYERUPDATING)
1376 /* InstallClipRegion does not work if the layer is in update state (BeginUpdate) */
1378 updating = TRUE;
1379 EndUpdate(l, FALSE);
1381 OldRegion = l->ClipRegion;
1384 /* is there a clipregion currently installed? */
1385 if (NULL != OldRegion)
1388 * Copy the contents of the region cliprects to the regular
1389 * cliprects if layer is a SMARTLAYER. Also free the list of
1390 * region cliprects.
1392 if (NULL != l->ClipRect)
1394 if (IS_SMARTREFRESH(l))
1395 _CopyClipRectsToClipRects(l,
1396 l->ClipRect,
1397 l->_cliprects,
1398 srcdx,
1399 destdx,
1400 FALSE,
1401 TRUE,
1402 FALSE,
1403 LayersBase);
1404 else
1405 _FreeClipRectListBM(l, l->ClipRect, LayersBase);
1408 /* restore the regular ClipRects */
1409 l->ClipRect = l->_cliprects;
1413 /* at this point the regular cliprects are in l->ClipRect in any case !*/
1415 /* if there's no new region to install then there's not much to do */
1416 l->ClipRegion = region;
1418 if (NULL == region)
1419 l->_cliprects = NULL;
1420 else
1422 struct Region *r;
1424 /* convert the region to a list of ClipRects */
1425 /* backup the old cliprects */
1426 l->_cliprects = l->ClipRect;
1428 _TranslateRect(&region->bounds, l->bounds.MinX, l->bounds.MinY);
1430 r = AndRegionRegionND(l->VisibleRegion, region);
1431 AndRegionRegion(l->shape, r);
1433 l->ClipRect = _CreateClipRectsFromRegion(r,
1435 FALSE,
1436 region,
1437 LayersBase);
1438 DisposeRegion(r);
1440 _CopyClipRectsToClipRects(l,
1441 l->_cliprects,
1442 l->ClipRect,
1443 srcdx,
1444 destdx,
1445 FALSE,
1446 FALSE,
1447 TRUE,
1448 LayersBase); /* stegerg: should be FALSE. but that does not work??? */
1450 _TranslateRect(&region->bounds, -l->bounds.MinX, -l->bounds.MinY);
1452 /* right now I am assuming that everything went alright */
1455 if (updating)
1456 BeginUpdate(l);
1458 } /* if ((OldRegion != NULL) || (region != NULL)) */
1460 return OldRegion;