2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
6 #include <aros/libcall.h>
7 #include <graphics/clip.h>
8 #include <graphics/layers.h>
9 #include <intuition/extensions.h>
10 #include <utility/tagitem.h>
11 #include <proto/exec.h>
12 #include <proto/utility.h>
13 #include <proto/graphics.h>
14 #include <proto/layers.h>
16 #include "basicfuncs.h"
17 #include "layers_intern.h"
20 * LA_InFrontOf and LA_Behind are intentionally left
21 * because they allow to implement AmigaOS4-compatible functionality.
23 struct Layer
*CreateLayerTagList(struct Layer_Info
*li
, struct BitMap
*bm
, LONG x0
, LONG y0
,
24 LONG x1
, LONG y1
, LONG flags
, int priority
, struct TagItem
*tagList
,
25 struct LayersBase
*LayersBase
)
27 struct BitMap
* superbitmap
= NULL
;
28 struct Hook
* hook
= NULL
, *shapehook
= NULL
;
31 struct Layer
* behind
= NULL
, * infrontof
= NULL
, * parent
= NULL
;
34 struct Region
* layershape
= NULL
, *shape
;
35 const struct TagItem
*tstate
= tagList
;
38 while((tag
= NextTagItem(&tstate
)))
43 hook
= (struct Hook
*)tag
->ti_Data
;
47 superbitmap
= (struct BitMap
*)tag
->ti_Data
;
51 parent
= (struct Layer
*)tag
->ti_Data
;
55 infrontof
= (struct Layer
*)tag
->ti_Data
;
59 behind
= (struct Layer
*)tag
->ti_Data
;
63 visible
= !tag
->ti_Data
;
67 layershape
= (struct Region
*)tag
->ti_Data
;
71 shapehook
= (struct Hook
*)tag
->ti_Data
;
75 win
= (APTR
)tag
->ti_Data
;
80 } /* while((tag = NextTagItem(&tstate))) */
82 if ((flags
& LAYERSUPER
) && (NULL
== superbitmap
))
87 parent
= li
->check_lp
;
90 /* Root layer not yet installed */
92 if (priority
!= ROOTPRIORITY
) /* avoid endless recursion */
94 struct TagItem tags
[] =
100 if (!(CreateLayerTagList(li
,
104 GetBitMapAttr(bm
, BMA_WIDTH
) - 1,
105 GetBitMapAttr(bm
, BMA_HEIGHT
) - 1,
115 parent
= li
->check_lp
;
121 * User gives coordinates reltive to parent.
122 * Adjust the shape to the absolute coordinates
123 * If this is the root layer, I don't have to
124 * do anything. I recognize the root layer if there
128 if (infrontof
&& infrontof
->priority
> priority
)
131 if (behind
&& behind
->priority
< priority
)
134 /* First create the shape region relative to nothing, that is 0,0 origin */
136 shape
= NewRectRegion(0, 0, x1
- x0
, y1
- y0
);
142 struct ShapeHookMsg msg
;
143 struct Rectangle NewBounds
, OldBounds
;
145 msg
.NewShape
= layershape
;
146 msg
.OldShape
= layershape
;
147 msg
.NewBounds
= &NewBounds
;
148 msg
.OldBounds
= &OldBounds
;
159 if (CallHookPkt(shapehook
, NULL
, &msg
))
160 layershape
= msg
.NewShape
;
163 if (layershape
) if (!AndRegionRegion(layershape
, shape
))
165 DisposeRegion(shape
);
171 /* Convert from parent layer relative coords to screen relative coords */
173 x0
+= parent
->bounds
.MinX
;
174 y0
+= parent
->bounds
.MinY
;
175 x1
+= parent
->bounds
.MinX
;
176 y1
+= parent
->bounds
.MinY
;
179 /* Make shape region relative to screen */
180 _TranslateRect(&shape
->bounds
, x0
, y0
);
182 l
= AllocMem(sizeof(struct IntLayer
), MEMF_CLEAR
|MEMF_PUBLIC
);
183 rp
= CreateRastPort();
188 IL(l
)->shapehook
= shapehook
;
190 l
->shaperegion
= layershape
;
196 l
->Flags
= (WORD
) flags
;
199 l
->SuperBitMap
= superbitmap
;
201 l
->priority
= priority
;
203 InitSemaphore(&l
->Lock
);
210 l
->Width
= x1
- x0
+ 1;
211 l
->Height
= y1
- y0
+ 1;
215 if (NULL
== (l
->DamageList
= NewRegion()))
217 if (NULL
== (l
->VisibleRegion
= NewRegion()))
219 if (NULL
== (l
->visibleshape
= NewRegion()))
222 l
->visible
= visible
;
224 if (NULL
== li
->check_lp
)
230 l
->nesting
= parent
->nesting
+1;
238 * If neither a layer in front or behind is
239 * given the search for the place according to
240 * the priority and insert it there. I
241 * determine behind or infrontof here!
243 if (NULL
!= li
->top_layer
)
245 if (!infrontof
&& !behind
)
248 struct Layer
* lastgood
;
253 lastgood
= infrontof
;
254 infrontof
= infrontof
->front
;
255 if (NULL
== infrontof
)
257 infrontof
= lastgood
;
260 if (infrontof
->parent
!= l
->parent
)
262 infrontof
= lastgood
;
265 while (infrontof
->nesting
>= l
->nesting
)
267 lastgood
= infrontof
;
268 infrontof
= infrontof
->front
;
269 if (NULL
== infrontof
||
270 infrontof
->priority
> l
->priority
)
272 infrontof
= lastgood
;
280 while (FALSE
== end
);
285 if (infrontof
|| (NULL
== behind
))
287 if (NULL
== infrontof
)
288 infrontof
= li
->top_layer
;
290 if (li
->top_layer
== infrontof
)
295 if (NULL
!= infrontof
)
296 infrontof
->front
= l
;
300 l
->front
= infrontof
->front
;
302 infrontof
->front
->back
= l
;
303 infrontof
->front
= l
;
309 l
->back
= behind
->back
;
317 SetRegion(l
->shape
, l
->visibleshape
);
319 AndRegionRegion(l
->parent
->shape
, l
->visibleshape
);
325 * layer is to be visible
327 struct Layer
* _l
= l
->back
;
328 struct Layer
* lparent
= l
->parent
;
331 * Does this layer have a layer in front of it?
332 * If yes, then take that layer's VisibleRegion and
333 * cut out that layer's shape. This is then the
334 * VisibleRegion of my layer.
338 SetRegion(l
->front
->VisibleRegion
, l
->VisibleRegion
);
339 ClearRegionRegion(l
->front
->visibleshape
, l
->VisibleRegion
);
342 SetRegion(li
->check_lp
->shape
, l
->VisibleRegion
);
346 * First tell all layers behind this layer to
347 * back up their parts that the new layer will
352 if (IS_VISIBLE(_l
) && DO_OVERLAP(&l
->shape
->bounds
, &_l
->shape
->bounds
))
353 _BackupPartsOfLayer(_l
, l
->visibleshape
, 0, FALSE
, LayersBase
);
355 ClearRegionRegion(l
->visibleshape
, _l
->VisibleRegion
);
359 if (IS_VISIBLE(_l
) || (NULL
== lparent
->parent
))
362 lparent
= lparent
->parent
;
369 * Show the layer according to its visible area
370 * This function creates the cliprects in the area
372 * This also works for invisible layers since their Visible
373 * Region is non existent.
375 if (!IS_ROOTLAYER(l
))
376 _ShowLayer(l
, LayersBase
);
388 if (l
->VisibleRegion
)
389 DisposeRegion(l
->VisibleRegion
);
391 DisposeRegion(l
->DamageList
);
393 DisposeRegion(l
->visibleshape
);
394 FreeMem(l
, sizeof(struct IntLayer
));
401 } /* CreateBehindHookLayer */