1st attempt of Zunification of BHFormat.
[cake.git] / rom / hyperlayers / basicfuncs.c
blobd7ba59acb705464890364a6f9e3b6b46d7933d22
1 /*
2 Copyright © 1995-2001, 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 "../graphics/intregions.h"
27 #include "layers_intern.h"
28 #include "basicfuncs.h"
30 #define CLIPRECTS_OUTSIDE_OF_SHAPE 1
32 #define SCROLLSIGN +
34 #define USE_POOLS 1
37 * Sections:
39 * + Blitter
40 * + Hook
41 * + Layer
42 * + LayerInfo
43 * + Rectangle
44 * + Resource Handling
45 * + Miscellaneous
49 /***************************************************************************/
50 /* BLITTER */
51 /***************************************************************************/
53 #define CR2NR_NOBITMAP 0
54 #define CR2NR_BITMAP 1
56 #if !(AROS_FLAVOUR & AROS_FLAVOUR_NATIVE)
58 * These functions cause the infamous "fixed or forbidden register was spilled"
59 * bug/feature in m68k gcc, so these were written straight in asm. They can be
60 * found in config/m68k-native/layers, for the m68k AROSfA target. Other targets,
61 * that use stack passing, can use these versions.
64 void BltRPtoCR(struct RastPort * rp,
65 struct ClipRect * cr,
66 ULONG Mode,
67 struct LayersBase * LayersBase)
69 BltBitMap(rp->BitMap,
70 cr->bounds.MinX,
71 cr->bounds.MinY,
72 cr->BitMap,
73 ALIGN_OFFSET(cr->bounds.MinX), 0,
74 cr->bounds.MaxX - cr->bounds.MinX + 1,
75 cr->bounds.MaxY - cr->bounds.MinY + 1,
76 Mode,
77 ~0,
78 NULL);
82 void BltCRtoRP(struct RastPort * rp,
83 struct ClipRect * cr,
84 ULONG Mode,
85 struct LayersBase * LayersBase)
87 BltBitMap(cr->BitMap,
88 ALIGN_OFFSET(cr->bounds.MinX),
90 rp->BitMap,
91 cr->bounds.MinX,
92 cr->bounds.MinY,
93 cr->bounds.MaxX - cr->bounds.MinX + 1,
94 cr->bounds.MaxY - cr->bounds.MinY + 1,
95 Mode,
96 ~0,
97 NULL);
101 #endif /* if !native */
103 /***************************************************************************/
104 /* HOOK */
105 /***************************************************************************/
107 struct layerhookmsg
109 struct Layer *l;
110 /* struct Rectangle rect; (replaced by the next line!) */
111 WORD MinX, MinY, MaxX, MaxY;
112 LONG OffsetX, OffsetY;
115 void _CallLayerHook(struct Hook * h,
116 struct RastPort * rp,
117 struct Layer * L,
118 struct Rectangle * R,
119 WORD offsetX,
120 WORD offsetY,
121 struct LayersBase * LayersBase)
123 struct BitMap * bm = rp->BitMap;
125 if (L)
127 if (IL(L)->intflags & INTFLAG_AVOID_BACKFILL) return;
130 if (h == LAYERS_BACKFILL)
132 /* Use default backfill, which means that I will clear the area */
133 BltBitMap(bm,
137 R->MinX,
138 R->MinY,
139 R->MaxX - R->MinX + 1,
140 R->MaxY - R->MinY + 1,
141 0x000,
142 0xff,
143 NULL);
144 /* that's it */
145 return;
148 if (h != LAYERS_NOBACKFILL)
150 struct layerhookmsg msg;
151 msg.l = L;
152 msg.MinX = R->MinX;
153 msg.MinY = R->MinY;
154 msg.MaxX = R->MaxX;
155 msg.MaxY = R->MaxY;
156 msg.OffsetX = offsetX;
157 msg.OffsetY = offsetY;
159 AROS_UFC3(void, h->h_Entry,
160 AROS_UFCA(struct Hook *, h ,A0),
161 AROS_UFCA(struct RastPort *, rp ,A2),
162 AROS_UFCA(struct layerhookmsg *, &msg,A1)
169 /***************************************************************************/
170 /* LAYER */
171 /***************************************************************************/
174 * Free a layer and all its associated structures
176 void _FreeLayer(struct Layer * l, struct LayersBase *LayersBase)
178 struct ClipRect * cr = l->ClipRect, * _cr;
180 while (cr)
182 if (cr->BitMap)
183 FreeBitMap(cr->BitMap);
184 _cr = cr->Next;
185 #if USE_POOLS
186 ObtainSemaphore(&LayersBase->lb_MemLock);
187 FreePooled(LayersBase->lb_ClipRectPool, cr, sizeof(struct ClipRect));
188 ReleaseSemaphore(&LayersBase->lb_MemLock);
189 #else
190 FreeMem(cr, sizeof(struct ClipRect));
191 #endif
192 cr = _cr;
196 * also free all backed up cliprects.
198 cr = l->SuperSaveClipRects;
200 while (cr)
202 _cr = cr->Next;
203 #if USE_POOLS
204 ObtainSemaphore(&LayersBase->lb_MemLock);
205 FreePooled(LayersBase->lb_ClipRectPool, cr, sizeof(struct ClipRect));
206 ReleaseSemaphore(&LayersBase->lb_MemLock);
207 #else
208 FreeMem(cr, sizeof(struct ClipRect));
209 #endif
210 cr = _cr;
213 FreeRastPort(l->rp);
214 DisposeRegion(l->DamageList);
215 DisposeRegion(l->VisibleRegion);
216 DisposeRegion(l->shape);
217 DisposeRegion(l->visibleshape);
219 FreeMem(l, sizeof(struct IntLayer));
224 /***************************************************************************/
225 /* LAYERINFO */
226 /***************************************************************************/
228 /*-------------------------------------------------------------------------*/
230 * Allocate LayerInfo_extra and initialize its resource list. Layers uses
231 * this resource list to keep track of various memory allocations it makes
232 * for the layers. See ResourceNode and ResData in layers_intern.h for the
233 * node structure. See AddLayersResource for more information on the basic
234 * operation.
236 BOOL _AllocExtLayerInfo(struct Layer_Info * li, struct LayersBase *LayersBase)
238 if(++li->fatten_count != 0)
239 return TRUE;
241 if(!(li->LayerInfo_extra = AllocMem(sizeof(struct LayerInfo_extra),MEMF_PUBLIC|MEMF_CLEAR)))
242 return FALSE;
244 NewList((struct List *)&((struct LayerInfo_extra *)li->LayerInfo_extra)->lie_ResourceList);
246 return TRUE;
250 * Free LayerInfo_extra.
252 void _FreeExtLayerInfo(struct Layer_Info * li, struct LayersBase *LayersBase)
254 if(--li->fatten_count >= 0)
255 return;
257 /* Kill Root Layer */
259 if (li->check_lp)
260 DeleteLayer(0UL, li->check_lp);
261 li->check_lp = NULL;
263 if(li->LayerInfo_extra == NULL)
264 return;
266 FreeMem(li->LayerInfo_extra, sizeof(struct LayerInfo_extra));
268 li->LayerInfo_extra = NULL;
272 * Dynamically allocate LayerInfo_extra if it isn't already there.
274 BOOL SafeAllocExtLI(struct Layer_Info * li,
275 struct LayersBase * LayersBase)
277 LockLayerInfo(li);
279 /* Check to see if we can ignore the rest of this call. :-) */
280 if(li->Flags & NEWLAYERINFO_CALLED)
281 return TRUE;
283 if(_AllocExtLayerInfo(li, LayersBase))
284 return TRUE;
286 UnlockLayerInfo(li);
288 return FALSE;
292 * Free LayerInfo_extra if it was dynamically allocated, and unlock the LI.
294 void SafeFreeExtLI(struct Layer_Info * li,
295 struct LayersBase * LayersBase)
297 if(!(li->Flags & NEWLAYERINFO_CALLED))
298 _FreeExtLayerInfo(li, LayersBase);
300 UnlockLayerInfo(li);
303 /***************************************************************************/
304 /* RECTANGLE */
305 /***************************************************************************/
308 #define MAX(a,b) ((a) > (b) ? (a) : (b))
309 #define MIN(a,b) ((a) < (b) ? (a) : (b))
311 void _TranslateRect(struct Rectangle *rect, WORD dx, WORD dy)
313 rect->MinX += dx;
314 rect->MinY += dy;
315 rect->MaxX += dx;
316 rect->MaxY += dy;
320 /***************************************************************************/
321 /* RESOURCE HANDLING */
322 /***************************************************************************/
325 * Allocate memory for a ClipRect.
328 struct ClipRect * _AllocClipRect(struct Layer * L, struct LayersBase *LayersBase)
330 struct ClipRect * CR;
332 CR = L->SuperSaveClipRects;
334 if (NULL != CR)
336 /* I want to access the list of free ClipRects alone */
337 L->SuperSaveClipRects = CR->Next;
338 L->SuperSaveClipRectCounter--;
340 CR->Flags = 0;
341 CR->Next = NULL;
342 CR->lobs = NULL;
343 CR->BitMap = NULL;
344 return CR;
347 #if USE_POOLS
348 ObtainSemaphore(&LayersBase->lb_MemLock);
349 CR = (struct ClipRect *)AllocPooled(LayersBase->lb_ClipRectPool, sizeof(struct ClipRect));
350 ReleaseSemaphore(&LayersBase->lb_MemLock);
351 #else
352 CR = (struct ClipRect *) AllocMem(sizeof(struct ClipRect), MEMF_PUBLIC|MEMF_CLEAR);
353 #endif
354 return CR;
358 * Return memory of a ClipRect for later use.
361 void _FreeClipRect(struct ClipRect * CR,
362 struct Layer * L,
363 struct LayersBase * LayersBase)
365 if (L->SuperSaveClipRectCounter < MAXSUPERSAVECLIPRECTS)
367 /* Add the ClipRect to the front of the list */
368 CR -> Next = L -> SuperSaveClipRects;
369 L -> SuperSaveClipRects = CR;
370 L -> SuperSaveClipRectCounter++;
372 else
374 #if USE_POOLS
375 ObtainSemaphore(&LayersBase->lb_MemLock);
376 FreePooled(LayersBase->lb_ClipRectPool, CR, sizeof(struct ClipRect));
377 ReleaseSemaphore(&LayersBase->lb_MemLock);
378 #else
379 FreeMem(CR, sizeof(struct ClipRect));
380 #endif
385 * Free a whole list of cliprects including the allocated bitmaps (if any)
388 void _FreeClipRectListBM(struct Layer * L,
389 struct ClipRect * CR,
390 struct LayersBase *LayersBase)
392 struct ClipRect * _CR = CR;
393 BOOL isSmart;
394 if ((L->Flags & (LAYERSUPER|LAYERSMART)) == LAYERSMART)
395 isSmart = TRUE;
396 else
397 isSmart = FALSE;
400 * This function is not watching for the upper limit of
401 * pre allocated cliprects.
403 L->SuperSaveClipRectCounter++;
405 while (TRUE)
407 if (NULL != _CR->BitMap && TRUE == isSmart)
409 FreeBitMap(_CR->BitMap);
410 _CR->BitMap = NULL;
412 if (NULL != _CR->Next)
414 L->SuperSaveClipRectCounter++;
415 _CR = _CR->Next;
417 else
418 break;
420 /* _CR is the last ClipRect in the list. I concatenate the
421 currently preallocated list of ClipRects with that list. */
422 _CR->Next = L->SuperSaveClipRects;
424 /* CR is the head of the ClipRect list now */
425 L->SuperSaveClipRects = CR;
429 /***************************************************************************/
430 /* MISCELLANEOUS */
431 /***************************************************************************/
433 struct ClipRect * _CreateClipRectsFromRegion(struct Region *r,
434 struct Layer * l,
435 int invisible,
436 struct Region * inverter,
437 struct LayersBase *LayersBase)
439 int looped = FALSE;
440 struct ClipRect * firstcr = NULL, * cr;
441 struct BitMap * display_bm = l->rp->BitMap;
444 * From region r create cliprects
446 while (1)
448 struct RegionRectangle * rr = r->RegionRectangle;
449 while (rr)
451 cr = _AllocClipRect(l, LayersBase);
452 cr->bounds.MinX = rr->bounds.MinX + r->bounds.MinX;
453 cr->bounds.MinY = rr->bounds.MinY + r->bounds.MinY;
454 cr->bounds.MaxX = rr->bounds.MaxX + r->bounds.MinX;
455 cr->bounds.MaxY = rr->bounds.MaxY + r->bounds.MinY;
456 cr->lobs = (struct Layer *)invisible;
457 cr->Next = firstcr;
459 if (TRUE == invisible && IS_SMARTREFRESH(l))
461 cr->BitMap = AllocBitMap(
462 cr->bounds.MaxX - cr->bounds.MinX + 1 + 16,
463 cr->bounds.MaxY - cr->bounds.MinY + 1,
464 display_bm->Depth,
465 BMF_CLEAR,
466 display_bm);
469 #if 0
470 kprintf("\t\t%s: Created cliprect %d/%d-%d/%d invisible: %d\n",
471 __FUNCTION__,
472 cr->bounds.MinX,
473 cr->bounds.MinY,
474 cr->bounds.MaxX,
475 cr->bounds.MaxY,
476 invisible);
477 #endif
479 firstcr = cr;
481 rr = rr->Next;
484 if (FALSE == looped)
487 * Flip the shape to the opposite part and
488 * limit it to its own shape.
490 if (inverter)
491 XorRegionRegion(inverter, r);
492 else
493 XorRectRegion(r,&l->bounds);
495 #if !CLIPRECTS_OUTSIDE_OF_SHAPE
496 AndRegionRegion(l->shape,r);
497 #else
498 AndRectRegion(r,&l->bounds);
499 #endif
500 if (TRUE == invisible)
501 invisible = FALSE;
502 else
503 invisible = TRUE;
504 looped = TRUE;
506 else
507 break;
508 } /* while (1) */
510 return firstcr;
514 int _CopyClipRectsToClipRects(struct Layer * l,
515 struct ClipRect * oldcr,
516 struct ClipRect * newcr,
517 int srcdx,
518 int destdx,
519 int backupmode,
520 int freelist,
521 int addtodamagelist,
522 struct LayersBase *LayersBase)
524 struct BitMap * display_bm = l->rp->BitMap;
526 while (NULL != oldcr)
528 struct ClipRect * _cr = newcr;
529 int area = RECTAREA(&oldcr->bounds);
530 while ((NULL != _cr) && (0 != area) )
532 struct Rectangle intersect;
535 * Do the two rectangles overlap?
537 if (_AndRectRect(&_cr->bounds, &oldcr->bounds, &intersect))
539 LONG xSize = intersect.MaxX - intersect.MinX + 1;
540 LONG ySize = intersect.MaxY - intersect.MinY + 1;
543 * Is this new one supposed to be invisible?
545 if (NULL != _cr->lobs)
547 struct BitMap * srcbm;
549 * The new one is supposed to be invisible.
550 * So for SIMPLEREFRESH layers I don't have to
551 * do anything if
552 * a) not in backupmode or
553 * b) old cr was invisible
555 if (IS_SIMPLEREFRESH(l) && FALSE == backupmode && NULL == _cr->BitMap)
557 if (FALSE == addtodamagelist)
559 struct Rectangle rect = intersect;
561 _TranslateRect(&rect, -l->bounds.MinX, -l->bounds.MinY);
563 #warning: stegerg: Not sure if this is a good idea. What for example if updating is done in several passes? And CopyClipRectsToClipRects is used by all kinds of functions including BeginUpdate/EndUpdate/InstallClipRegion/etc.
564 ClearRectRegion(l->DamageList, &rect);
565 #if 0
566 kprintf("");
567 kprintf("%s: Removing %d/%d-%d/%d from damagelist!\t",
568 __FUNCTION__,
569 rect.MinX,
570 rect.MinY,
571 rect.MaxX,
572 rect.MaxY
574 kprintf("%s: Layer: %d/%d-%d/%d!\n",
575 __FUNCTION__,
576 l->bounds.MinX,
577 l->bounds.MinY,
578 l->bounds.MaxX,
579 l->bounds.MaxY
581 kprintf("%s: oldcr: %d/%d-%d/%d!\t",
582 __FUNCTION__,
583 oldcr->bounds.MinX,
584 oldcr->bounds.MinY,
585 oldcr->bounds.MaxX,
586 oldcr->bounds.MaxY
588 kprintf("%s: _cr: %d/%d-%d/%d!\n\n",
589 __FUNCTION__,
590 _cr->bounds.MinX,
591 _cr->bounds.MinY,
592 _cr->bounds.MaxX,
593 _cr->bounds.MaxY
595 #endif
598 else if (IS_SIMPLEREFRESH(l) && TRUE == backupmode && NULL != oldcr->lobs)
600 if (TRUE == addtodamagelist)
602 struct Rectangle rect = intersect;
603 _TranslateRect(&rect, -l->bounds.MinX, -l->bounds.MinY);
605 // FIXME (if possible)
606 // !!! Also areas where a child disappears beyond the
607 // boundaries of its parent are added here!
608 OrRectRegion(l->DamageList, &rect);
609 #if 0
610 kprintf("_cr->BitMap: %p ,_cr->lobs: %d\n",_cr->BitMap,_cr->lobs);
611 #endif
612 #if 0
613 kprintf("%s: Adding %d/%d-%d/%d to damagelist of l=%p!\t",
614 __FUNCTION__,
615 rect.MinX,
616 rect.MinY,
617 rect.MaxX,
618 rect.MaxY,
621 #endif
622 #if 0
623 kprintf("%s: Layer: %d/%d-%d/%d!\n",
624 __FUNCTION__,
625 l->bounds.MinX,
626 l->bounds.MinY,
627 l->bounds.MaxX,
628 l->bounds.MaxY
630 kprintf("%s: oldcr: %d/%d-%d/%d!\t",
631 __FUNCTION__,
632 oldcr->bounds.MinX,
633 oldcr->bounds.MinY,
634 oldcr->bounds.MaxX,
635 oldcr->bounds.MaxY
637 kprintf("%s: _cr: %d/%d-%d/%d!\n\n",
638 __FUNCTION__,
639 _cr->bounds.MinX,
640 _cr->bounds.MinY,
641 _cr->bounds.MaxX,
642 _cr->bounds.MaxY
644 #endif
645 } else {
646 //kprintf("Not adding to damage list for l=%p!\n",l);
649 else
651 LONG xSrc, xDest;
652 LONG ySrc, yDest;
653 struct BitMap * destbm;
655 if (IS_SUPERREFRESH(l))
656 destbm = l->SuperBitMap;
657 else
658 destbm = _cr->BitMap;
661 * Does the source rect have a bitmap (off screen)
662 * or is it on the screen.
664 if (oldcr->lobs && !IS_SUPERREFRESH(l))
667 * Copy from hidden bitmap to hidden bitmap
669 xSrc = (oldcr->bounds.MinX - _cr->bounds.MinX);
670 if (xSrc < 0)
673 * oldcr is further to the left
675 xSrc = -xSrc;
676 xDest = 0;
678 else
681 * oldcr is further to the right
683 xDest = xSrc;
684 xSrc = 0;
687 xSrc += ALIGN_OFFSET(oldcr->bounds.MinX + srcdx);
688 xDest += ALIGN_OFFSET(_cr->bounds.MinX + destdx);
690 ySrc = (oldcr->bounds.MinY - _cr->bounds.MinY);
691 if (ySrc < 0)
693 ySrc = -ySrc;
694 yDest = 0;
696 else
698 yDest = ySrc;
699 ySrc = 0;
701 //kprintf("Using old cr's BitMap!\n");
702 srcbm = oldcr->BitMap;
704 else
707 * Copy from screen.
709 if (oldcr->bounds.MinX > _cr->bounds.MinX)
711 xSrc = oldcr->bounds.MinX;
712 if (IS_SUPERREFRESH(l))
713 xDest = (oldcr->bounds.MinX - _cr->bounds.MinX) SCROLLSIGN l->Scroll_X;
714 else
715 xDest = (oldcr->bounds.MinX - _cr->bounds.MinX) + ALIGN_OFFSET((_cr->bounds.MinX + destdx));
717 else
719 xSrc = _cr->bounds.MinX;
720 if (IS_SUPERREFRESH(l))
721 xDest = SCROLLSIGN l->Scroll_X;
722 else
723 xDest = ALIGN_OFFSET((_cr->bounds.MinX + destdx));
726 if (oldcr->bounds.MinY > _cr->bounds.MinY)
728 ySrc = oldcr->bounds.MinY;
729 yDest = oldcr->bounds.MinY - _cr->bounds.MinY;
730 if (IS_SUPERREFRESH(l))
731 yDest = yDest SCROLLSIGN l->Scroll_Y;
733 else
735 ySrc = _cr->bounds.MinY;
736 yDest = 0;
737 if (IS_SUPERREFRESH(l))
738 yDest = yDest SCROLLSIGN l->Scroll_Y;
741 srcbm = l->rp->BitMap;
742 //kprintf("Using bitmap of screen!\n");
745 if (IS_SIMPLEREFRESH(l) &&
746 NULL == _cr->BitMap &&
747 TRUE == backupmode)
750 * Get a bitmap (if not there) and make a backup
752 _cr->BitMap = AllocBitMap(
753 _cr->bounds.MaxX - _cr->bounds.MinX + 1 + 16 ,
754 _cr->bounds.MaxY - _cr->bounds.MinY + 1,
755 display_bm->Depth,
756 BMF_CLEAR,
757 display_bm);
758 destbm = _cr->BitMap;
761 BltBitMap(srcbm,
762 xSrc,
763 ySrc,
764 destbm,
765 xDest,
766 yDest,
767 xSize,
768 ySize,
769 0x0c0,
770 0xff,
771 NULL);
772 #if 0
773 kprintf("%s: backing up: from %d/%d to %d/%d width:%d, height: %d\n",
774 __FUNCTION__,
775 xSrc,
776 ySrc,
777 xDest,
778 yDest,
779 xSize,
780 ySize);
781 #endif
783 area -= (xSize * ySize);
787 else //if (FALSE == backupmode)
790 * The new one is visible. if the old one was not visible
791 * then I have to show it.
792 * If it is a simple refresh layer and it has it
793 * backed up (only when moving!) then I must show
794 * this. If it has nothing backed up then I must
795 * add a part to the damage list.
797 if (IS_SIMPLEREFRESH(l) &&
798 (NULL != oldcr->lobs) &&
799 (NULL == oldcr->BitMap))
801 if (NULL != oldcr->lobs && NULL == oldcr->BitMap)
803 struct Rectangle rect = intersect;
805 _CallLayerHook(l->BackFill,
806 l->rp,
808 &rect,
809 rect.MinX,
810 rect.MinY,
811 LayersBase);
812 _TranslateRect(&rect, -l->bounds.MinX, -l->bounds.MinY);
813 OrRectRegion(l->DamageList, &rect);
814 #if 0
815 kprintf("Adding: %d\n",addtodamagelist);
816 kprintf("%s: Adding %d/%d-%d/%d to damagelist!\t",
817 __FUNCTION__,
818 rect.MinX,
819 rect.MinY,
820 rect.MaxX,
821 rect.MaxY
823 kprintf("%s: Layer: %d/%d-%d/%d!\n",
824 __FUNCTION__,
825 l->bounds.MinX,
826 l->bounds.MinY,
827 l->bounds.MaxX,
828 l->bounds.MaxY
830 kprintf("%s: oldcr: %d/%d-%d/%d!\t",
831 __FUNCTION__,
832 oldcr->bounds.MinX,
833 oldcr->bounds.MinY,
834 oldcr->bounds.MaxX,
835 oldcr->bounds.MaxY
837 kprintf("%s: _cr: %d/%d-%d/%d!\n",
838 __FUNCTION__,
839 _cr->bounds.MinX,
840 _cr->bounds.MinY,
841 _cr->bounds.MaxX,
842 _cr->bounds.MaxY
844 #endif
847 else
849 //kprintf("%s: Showing a part of a backed up bitmap!\n",__FUNCTION__);
850 if (NULL != oldcr->lobs)
853 * Copy out of hidden bitmap
855 LONG xSrc, xDest;
856 LONG ySrc, yDest;
857 struct BitMap * srcbm;
859 if (IS_SUPERREFRESH(l))
860 srcbm = l->SuperBitMap;
861 else
862 srcbm = oldcr->BitMap;
865 * I have to make the old one visible
866 * two cases left: SMART REFRESH and SUPERBITMAP
869 if (!IS_SUPERREFRESH(l))
872 * Copy from hidden BitMap to screen!
873 * If a simple refresh layer is moved it might
874 * also have a BitMap!!!
876 xSrc = (oldcr->bounds.MinX - _cr->bounds.MinX);
877 if (xSrc < 0)
880 * old cr is further to the left
882 xSrc = -xSrc + ALIGN_OFFSET(oldcr->bounds.MinX + srcdx);
883 xDest = _cr->bounds.MinX;
885 else
888 * oldcr is further to the right
890 xDest = oldcr->bounds.MinX;
891 xSrc = ALIGN_OFFSET(oldcr->bounds.MinX + srcdx);
894 ySrc = (oldcr->bounds.MinY - _cr->bounds.MinY);
895 if (ySrc < 0)
897 ySrc = -ySrc;
898 yDest = _cr->bounds.MinY;
900 else
902 yDest = oldcr->bounds.MinY;
903 ySrc = 0;
906 else
909 * superbitmap layer
911 xSrc = (oldcr->bounds.MinX > _cr->bounds.MinX) ?
912 oldcr->bounds.MinX - _cr->bounds.MinX SCROLLSIGN l->Scroll_X :
913 _cr->bounds.MinX - oldcr->bounds.MinX SCROLLSIGN l->Scroll_X;
914 xDest = _cr->bounds.MinX;
916 ySrc = (oldcr->bounds.MinY > _cr->bounds.MinY) ?
917 oldcr->bounds.MinY - _cr->bounds.MinY SCROLLSIGN l->Scroll_Y :
918 _cr->bounds.MinY - oldcr->bounds.MinY SCROLLSIGN l->Scroll_Y;
919 yDest = _cr->bounds.MinY;
923 #if 0
924 kprintf("\t\t%s: Show cliprect: %d/%d-%d/%d; blitting to %d/%d _cr->lobs: %d\n",
925 __FUNCTION__,
926 oldcr->bounds.MinX,
927 oldcr->bounds.MinY,
928 oldcr->bounds.MaxX,
929 oldcr->bounds.MaxY,
930 xDest,
931 yDest,
932 _cr->lobs);
933 #endif
935 #warning Must have oldcr->BitMap also for SuperBitMap layers!
937 BltBitMap(srcbm,
938 xSrc,
939 ySrc,
940 l->rp->BitMap,
941 xDest,
942 yDest,
943 xSize,
944 ySize,
945 0x0c0,
946 0xff,
947 NULL);
949 } /* if was hidden cliprect */
950 } /* if is simple else ... */
951 } /* if new cliprect is visible or invisible */
952 } /* if rectangles overlap */
953 else
956 if (IS_SMARTREFRESH(l) && TRUE == backupmode && NULL == _cr->BitMap && NULL != _cr->lobs)
958 _cr->BitMap = AllocBitMap(_cr->bounds.MaxX - _cr->bounds.MinX + 1 + 16 ,
959 _cr->bounds.MaxY - _cr->bounds.MinY + 1,
960 display_bm->Depth,
961 BMF_CLEAR,
962 display_bm);
965 _cr = _cr->Next;
966 } /* all new cliprects */
968 if (TRUE == freelist)
970 _cr = oldcr->Next;
971 if (oldcr->BitMap)
972 FreeBitMap(oldcr->BitMap);
973 _FreeClipRect(oldcr, l, LayersBase);
974 oldcr = _cr;
976 else
977 oldcr = oldcr->Next;
978 } /* for all old cliprects */
980 CHECKDAMAGELIST(l);
983 * If this is a simple refresh layer and I am not in
984 * backup mode and I am not adding to the damagelist
985 * the I must call the backfillhook for the
986 * area of the damage list of a simple refresh layer
989 if (IS_SIMPLEREFRESH(l) &&
990 (l->Flags & LAYERREFRESH) &&
991 FALSE == backupmode &&
992 FALSE == addtodamagelist)
994 struct Region * dr = l->DamageList;
995 struct RegionRectangle * rr;
997 _TranslateRect(&dr->bounds, l->bounds.MinX, l->bounds.MinY);
998 AndRectRegion(dr, &l->bounds);
999 AndRegionRegion(l->VisibleRegion, dr);
1000 AndRegionRegion(l->visibleshape, dr);
1002 _TranslateRect(&dr->bounds, -l->bounds.MinX, -l->bounds.MinY);
1004 rr = dr->RegionRectangle;
1005 while (rr)
1007 _TranslateRect(&rr->bounds,
1008 dr->bounds.MinX + l->bounds.MinX,
1009 dr->bounds.MinY + l->bounds.MinY);
1011 _CallLayerHook(l->BackFill,
1012 l->rp,
1014 &rr->bounds,
1015 rr->bounds.MinX,
1016 rr->bounds.MinY,
1017 LayersBase);
1019 _TranslateRect(&rr->bounds,
1020 -dr->bounds.MinX-l->bounds.MinX,
1021 -dr->bounds.MinY-l->bounds.MinY);
1022 rr = rr->Next;
1027 return TRUE;
1031 * Backup any parts of the layer that overlap with the backup_region
1032 * and that are not already backed up. Create the cliprects and
1033 * bitmaps if necessary.
1034 * Assumption: Only visible parts become invisible,
1035 * invisible parts will not become visible.
1037 * This function MUST not manipulate hide_region!!!!
1039 int _BackupPartsOfLayer(struct Layer * l,
1040 struct Region * hide_region,
1041 int dx,
1042 int backupsimplerefresh,
1043 struct LayersBase * LayersBase)
1045 struct ClipRect * newcr;
1046 struct Region *r, * clipregion;
1049 * Uninstall clipping region. This causes all pixels to
1050 * be copied into the cliprects that cover the complete
1051 * area of the layer.
1054 clipregion = _InternalInstallClipRegion(l, NULL, 0, 0, LayersBase);
1056 ClearRegionRegion(hide_region,l->VisibleRegion);
1057 r = AndRegionRegionND(l->visibleshape, l->VisibleRegion);
1059 if (r)
1061 newcr = _CreateClipRectsFromRegion(r,l,FALSE,NULL,LayersBase);
1062 DisposeRegion(r);
1064 if (newcr)
1066 _CopyClipRectsToClipRects(l,
1067 l->ClipRect /* source */,
1068 newcr /* destination */,
1071 backupsimplerefresh,
1072 TRUE,
1073 TRUE,
1074 LayersBase);
1076 l->ClipRect = newcr;
1081 * Reinstall the clipping region. This causes the
1082 * whole visible area of the layer to be copied
1083 * into the clipping regions cliprects. The
1084 * regular list of cliprects is still maintained.
1086 if (clipregion)
1087 _InternalInstallClipRegion(l, clipregion, dx, dx, LayersBase);
1089 return TRUE;
1093 * Show any parts of the layer that overlap with the backup_region
1094 * and that are not already show.
1096 * This function MUST not manipulate show_region!!!!
1099 int _ShowPartsOfLayer(struct Layer * l,
1100 struct Region * show_region,
1101 struct LayersBase * LayersBase)
1103 struct ClipRect * newcr;
1104 struct Region *r;
1105 struct Region * clipregion;
1107 //kprintf("%s called for %p\n",__FUNCTION__,l);
1110 * If there is a clipping region then the whole
1111 * window is currently backed up in l->ClipRect
1112 * That covers the complete area. I must first
1113 * make these visible, move them back to
1114 * l->_cliprects and recreate the clipping cliprects
1115 * according to the clipregion
1118 if (show_region == l->VisibleRegion)
1119 kprintf("ERROR - same regions!! %s\n",__FUNCTION__);
1121 clipregion = InstallClipRegion(l, NULL);
1123 OrRegionRegion(show_region,l->VisibleRegion);
1124 r = AndRegionRegionND(l->visibleshape, l->VisibleRegion);
1125 if (r != NULL)
1127 newcr = _CreateClipRectsFromRegion(r,l,FALSE,NULL,LayersBase);
1128 DisposeRegion(r);
1130 _CopyClipRectsToClipRects(l,
1131 l->ClipRect /* source */,
1132 newcr /* destination */,
1135 FALSE,
1136 TRUE,
1137 FALSE,
1138 LayersBase);
1141 l->ClipRect = newcr;
1143 if (clipregion)
1144 InstallClipRegion(l, clipregion);
1146 return TRUE;
1149 int _ShowLayer(struct Layer * l, struct LayersBase *LayersBase)
1151 struct Region *r;
1152 struct RegionRectangle * rr;
1153 struct ClipRect * prevcr = NULL;
1154 struct BitMap * bm = l->rp->BitMap;
1155 int invisible = FALSE;
1157 r = AndRegionRegionND(l->shape, l->VisibleRegion);
1158 AndRegionRegion(l->parent->shape, r);
1160 while (1)
1162 rr = r->RegionRectangle;
1164 while (NULL != rr)
1166 struct ClipRect * cr;
1168 #if USE_POOLS
1169 ObtainSemaphore(&LayersBase->lb_MemLock);
1170 cr = (struct ClipRect *)AllocPooled(LayersBase->lb_ClipRectPool, sizeof(struct ClipRect));
1171 ReleaseSemaphore(&LayersBase->lb_MemLock);
1172 #else
1173 cr = AllocMem(sizeof(struct ClipRect), MEMF_CLEAR);
1174 #endif
1176 //kprintf("\t\tinvisible: %d !!!!!!!!!!!!\n",invisible);
1178 MinX(cr) = MinX(rr) + MinX(r);
1179 MinY(cr) = MinY(rr) + MinY(r);
1180 MaxX(cr) = MaxX(rr) + MinX(r);
1181 MaxY(cr) = MaxY(rr) + MinY(r);
1182 cr->lobs = (struct Layer *)invisible;
1183 #if 0
1184 kprintf("\t\t%s: Created cliprect %d/%d-%d/%d invisible: %d\n",
1185 __FUNCTION__,
1186 cr->bounds.MinX,
1187 cr->bounds.MinY,
1188 cr->bounds.MaxX,
1189 cr->bounds.MaxY,
1190 invisible);
1191 #endif
1192 if (prevcr)
1193 prevcr->Next = cr;
1194 else
1195 l->ClipRect = cr;
1197 prevcr = cr;
1199 if (FALSE == invisible)
1201 #if 0
1202 kprintf("\t\tClearing background! %d/%d-%d/%d bitmap: %p\n",
1203 cr->bounds.MinX,
1204 cr->bounds.MinY,
1205 cr->bounds.MaxX,
1206 cr->bounds.MaxY,
1207 l->rp->BitMap
1209 #endif
1210 if (IS_SUPERREFRESH(l))
1212 BltBitMap(l->SuperBitMap,
1213 cr->bounds.MinX - l->bounds.MinX,
1214 cr->bounds.MinY - l->bounds.MinY,
1215 l->rp->BitMap,
1216 cr->bounds.MinX,
1217 cr->bounds.MinY,
1218 cr->bounds.MaxX - cr->bounds.MinX + 1,
1219 cr->bounds.MaxY - cr->bounds.MinY + 1,
1220 0x0c0,
1221 0xff,
1222 NULL);
1224 else
1226 _CallLayerHook(l->BackFill,
1227 l->rp,
1229 &cr->bounds,
1230 cr->bounds.MinX,
1231 cr->bounds.MinY,
1232 LayersBase);
1235 else
1238 * This part is to be invisible!
1240 if (IS_SMARTREFRESH(l))
1242 cr->BitMap = AllocBitMap(
1243 cr->bounds.MaxX - cr->bounds.MinX + 1 + 16,
1244 cr->bounds.MaxY - cr->bounds.MinY + 1,
1245 bm->Depth,
1246 BMF_CLEAR,
1247 bm);
1249 #warning stegerg: the backfill hook should be called for this bitmap! But _CallLayerHook always uses rp->BitMap
1253 rr=rr->Next;
1256 if (FALSE == invisible)
1258 XorRectRegion(r, &l->bounds);
1259 #if !CLIPRECTS_OUTSIDE_OF_SHAPE
1260 AndRegionRegion(l->shape, r);
1261 #endif
1262 invisible = TRUE;
1264 else
1265 break;
1268 DisposeRegion(r);
1270 return TRUE;
1274 * It is assumed that the region r is not needed anymore.
1276 void _BackFillRegion(struct Layer * l,
1277 struct Region * r,
1278 int addtodamagelist,
1279 struct LayersBase * LayersBase)
1281 struct RegionRectangle * RR;
1283 RR = r->RegionRectangle;
1284 if (NULL == RR) return;
1286 if (IS_SIMPLEREFRESH(l))
1288 /* Only for simple refresh layers, becuase smart refresh layers
1289 may have damage outside of visibleshape, like when being dragged
1290 off screen */
1292 AndRegionRegion(l->visibleshape, r);
1294 else
1296 /* Maybe not needed, but to be sure ... */
1298 AndRectRegion(r, &l->bounds);
1302 if (TRUE == addtodamagelist)
1304 l->Flags |= LAYERREFRESH;
1306 #if 1
1307 /* Region coords are screen relative, but damagelist coords are layer relative! */
1309 _TranslateRect(&r->bounds, -l->bounds.MinX, -l->bounds.MinY);
1310 OrRegionRegion(r, l->DamageList);
1311 _TranslateRect(&r->bounds, l->bounds.MinX, l->bounds.MinY);
1313 #else
1314 while (NULL != RR)
1316 struct Rectangle rect = RR->bounds;
1318 //kprintf("%s: adding to damagelist!\n",__FUNCTION__);
1320 /* Region coords are screen relative, but damagelist coords are layer relative! */
1322 _TranslateRect(&rect,
1323 r->bounds.MinX - l->bounds.MinX,
1324 r->bounds.MinY - l->bounds.MinY);
1325 #if 0
1326 kprintf("%s: Adding %d/%d-%d/%d to damagelist!\n",
1327 __FUNCTION__,
1328 rect.MinX,
1329 rect.MinY,
1330 rect.MaxX,
1331 rect.MaxY
1333 #endif
1334 OrRectRegion(l->DamageList, &rect);
1336 _TranslateRect(&rect,
1337 -r->bounds.MinX + l->bounds.MinX,
1338 -r->bounds.MinY + l->bounds.MinY);
1340 RR = RR->Next;
1342 } /* while (NULL != RR) */
1343 #endif
1345 } /* if (TRUE == addtodamagelist) */
1347 AndRegionRegion(l->VisibleRegion, r);
1348 if (l->shaperegion)
1350 /* shaperegion is layer relative, while r is screen relative */
1352 _TranslateRect(&r->bounds, -l->bounds.MinX, -l->bounds.MinY);
1353 AndRegionRegion(l->shaperegion, r);
1354 _TranslateRect(&r->bounds, l->bounds.MinX, l->bounds.MinY);
1357 RR = r->RegionRectangle;
1358 /* check if a region is empty */
1359 while (NULL != RR)
1361 _TranslateRect(&RR->bounds, r->bounds.MinX, r->bounds.MinY);
1363 #if 0
1364 kprintf("\t\t: %s Clearing rect : %d/%d-%d/%d layer: %p, hook: %p, bitmap: %p\n",
1365 __FUNCTION__,
1366 RR->bounds.MinX,
1367 RR->bounds.MinY,
1368 RR->bounds.MaxX,
1369 RR->bounds.MaxY,
1371 l->BackFill,
1372 l->rp->BitMap);
1373 #endif
1374 _CallLayerHook(l->BackFill,
1375 l->rp,
1377 &RR->bounds,
1378 RR->bounds.MinX,
1379 RR->bounds.MinY,
1380 LayersBase);
1381 RR = RR->Next;
1386 struct Region *_InternalInstallClipRegion(struct Layer *l, struct Region *region,
1387 WORD srcdx, WORD destdx,
1388 struct LayersBase *LayersBase)
1390 struct Region * OldRegion;
1391 BOOL updating = FALSE;
1392 OldRegion = l->ClipRegion;
1394 if ((OldRegion != NULL) || (region != NULL))
1396 if (l->Flags & LAYERUPDATING)
1398 /* InstallClipRegion does not work if the layer is in update state (BeginUpdate) */
1400 updating = TRUE;
1401 EndUpdate(l, FALSE);
1403 OldRegion = l->ClipRegion;
1406 /* is there a clipregion currently installed? */
1407 if (NULL != OldRegion)
1410 * Copy the contents of the region cliprects to the regular
1411 * cliprects if layer is a SMARTLAYER. Also free the list of
1412 * region cliprects.
1414 if (NULL != l->ClipRect)
1416 if (IS_SMARTREFRESH(l))
1417 _CopyClipRectsToClipRects(l,
1418 l->ClipRect,
1419 l->_cliprects,
1420 srcdx,
1421 destdx,
1422 FALSE,
1423 TRUE,
1424 FALSE,
1425 LayersBase);
1426 else
1427 _FreeClipRectListBM(l, l->ClipRect, LayersBase);
1430 /* restore the regular ClipRects */
1431 l->ClipRect = l->_cliprects;
1435 /* at this point the regular cliprects are in l->ClipRect in any case !*/
1437 /* if there's no new region to install then there's not much to do */
1438 l->ClipRegion = region;
1440 if (NULL == region)
1441 l->_cliprects = NULL;
1442 else
1444 struct Region *r;
1446 /* convert the region to a list of ClipRects */
1447 /* backup the old cliprects */
1448 l->_cliprects = l->ClipRect;
1450 _TranslateRect(&region->bounds, l->bounds.MinX, l->bounds.MinY);
1452 r = AndRegionRegionND(l->VisibleRegion, region);
1453 AndRegionRegion(l->shape, r);
1455 l->ClipRect = _CreateClipRectsFromRegion(r,
1457 FALSE,
1458 region,
1459 LayersBase);
1460 DisposeRegion(r);
1462 _CopyClipRectsToClipRects(l,
1463 l->_cliprects,
1464 l->ClipRect,
1465 srcdx,
1466 destdx,
1467 FALSE,
1468 FALSE,
1469 TRUE,
1470 LayersBase); /* stegerg: should be FALSE. but that does not work??? */
1472 _TranslateRect(&region->bounds, -l->bounds.MinX, -l->bounds.MinY);
1474 /* right now I am assuming that everything went alright */
1477 if (updating)
1478 BeginUpdate(l);
1480 } /* if ((OldRegion != NULL) || (region != NULL)) */
1482 return OldRegion;