r4493@vps: verhaegs | 2007-04-19 14:44:00 -0400
[AROS.git] / rom / hyperlayers / createlayertaglist.c
blobdc2990790fc792f967ab23750bd12e20eaff28cc
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/libcall.h>
7 #include <graphics/clip.h>
8 #include <graphics/layers.h>
9 #include <utility/tagitem.h>
10 #include <proto/exec.h>
11 #include <proto/utility.h>
12 #include <proto/graphics.h>
13 #include "basicfuncs.h"
15 /*****************************************************************************
17 NAME */
18 #include <proto/layers.h>
19 AROS_LH8(struct Layer *, CreateLayerTagList,
21 /* SYNOPSIS */
22 AROS_LHA(struct Layer_Info *, li, A0),
23 AROS_LHA(struct BitMap *, bm, A1),
24 AROS_LHA(LONG , x0, D0),
25 AROS_LHA(LONG , y0, D1),
26 AROS_LHA(LONG , x1, D2),
27 AROS_LHA(LONG , y1, D3),
28 AROS_LHA(LONG , flags, D4),
29 AROS_LHA(struct TagItem *, tagList, A2),
31 /* LOCATION */
32 struct LayersBase *, LayersBase, 37, Layers)
34 /* FUNCTION
35 Create a new layer according to the tags given.
37 INPUTS
38 li - pointer to LayerInfo structure
39 bm - pointer to common bitmap
40 x0,y0 - upper left corner of the layer (in parent layer coords)
41 x1,y1 - lower right corner of the layer (in parent layer coords)
42 flags - choose the type of layer by setting some flags
43 If it is to be a super bitmap layer then the tag
44 LA_SUPERBITMAP must be provided along with a
45 pointer to a valid super bitmap.
46 tagList - a list of tags that specify the properties of the
47 layer. The following tags are currently supported:
48 LA_PRIORITY : priority class of the layer. The
49 higher the number the further the
50 layer will be in front of everything
51 else.
52 Default value is UPFRONTPRIORITY.
53 LA_HOOK : Backfill hook
54 LA_SUPERBITMAP : pointer to a superbitmap. The flags
55 must also represent that this
56 layer is supposed to be a superbitmap
57 layer.
58 LA_CHILDOF : pointer to parent layer. If NULL then
59 this layer will be created as a old-style
60 layer.
61 LA_INFRONTOF : pointer to a layer in front of which
62 this layer is to be created.
63 LA_BEHIND : pointer to a layer behind which this layer
64 is to be created. Must not give both LA_INFRONTOF
65 and LA_BEHIND.
66 LA_VISIBLE : FALSE if this layer is to be invisible.
67 Default value is TRUE
68 LA_SHAPE : The region of the layer that comprises its shape.
69 This value is optional. The region must be relative to the layer.
72 RESULT
73 Pointer to the newly created layer. NULL if layer could not be
74 created (Probably out of memory).
75 If the layer is created successful you must not free its shape.
76 The shape is automatically freed when the layer is deleted.
78 NOTES
80 EXAMPLE
82 BUGS
84 SEE ALSO
86 INTERNALS
88 *****************************************************************************/
90 AROS_LIBFUNC_INIT
91 AROS_LIBBASE_EXT_DECL(struct LayersBase *,LayersBase)
93 struct BitMap * superbitmap = NULL;
94 struct Hook * hook = NULL, *shapehook = NULL;
95 int priority = UPFRONTPRIORITY;
96 int visible = TRUE;
97 struct Layer * behind = NULL, * infrontof = NULL, * parent = NULL;
98 struct Layer * l;
99 struct RastPort * rp;
100 struct Region * layershape = NULL, *shape;
101 struct TagItem *tag, *tstate = tagList;
103 while((tag = NextTagItem(&tstate)))
105 switch (tag->ti_Tag)
107 case LA_Priority:
108 priority = tag->ti_Data;
109 break;
111 case LA_Hook:
112 hook = (struct Hook *)tag->ti_Data;
113 break;
115 case LA_SuperBitMap:
116 superbitmap = (struct BitMap *)tag->ti_Data;
117 break;
119 case LA_ChildOf:
120 parent = (struct Layer *)tag->ti_Data;
121 break;
123 case LA_InFrontOf:
124 if (infrontof)
125 return NULL;
126 infrontof = (struct Layer *)tag->ti_Data;
127 break;
129 case LA_Behind:
130 if (behind)
131 return NULL;
132 behind = (struct Layer *)tag->ti_Data;
133 break;
135 case LA_Visible:
136 visible = tag->ti_Data;
137 break;
139 case LA_Shape:
140 layershape = (struct Region *)tag->ti_Data;
141 break;
143 case LA_ShapeHook:
144 shapehook = (struct Hook *)tag->ti_Data;
145 break;
149 } /* while((tag = NextTagItem(&tstate))) */
151 if ((flags & LAYERSUPER) && (NULL == superbitmap))
152 return NULL;
154 if (!parent)
156 parent = li->check_lp;
157 if (!parent)
159 /* Root layer not yet installed */
161 if (!(flags & LAYER_ROOT_LAYER)) /* avoid endless recursion */
163 struct TagItem tags[] =
165 {LA_Visible , FALSE },
166 {LA_Priority, ROOTPRIORITY },
167 {TAG_DONE }
170 if (!(CreateLayerTagList(li,
174 GetBitMapAttr(bm, BMA_WIDTH) - 1,
175 GetBitMapAttr(bm, BMA_HEIGHT) - 1,
176 LAYER_ROOT_LAYER,
177 tags)))
179 li->check_lp = NULL;
180 return NULL;
183 parent = li->check_lp;
189 * User gives coordinates reltive to parent.
190 * Adjust the shape to the absolute coordinates
191 * If this is the root layer, I don't have to
192 * do anything. I recognize the root layer if there
193 * is no parent.
196 if (infrontof && infrontof->priority > priority)
197 return NULL;
199 if (behind && behind->priority < priority)
200 return NULL;
202 /* First create the shape region relative to nothing, that is 0,0 origin */
204 shape = NewRectRegion(0, 0, x1 - x0, y1 - y0);
205 if (!shape)
206 return NULL;
208 if (shapehook)
210 struct ShapeHookMsg msg;
212 msg.Action = SHAPEHOOKACTION_CREATELAYER;
213 msg.Layer = 0;
214 msg.ActualShape = layershape;
215 msg.NewBounds.MinX = x0;
216 msg.NewBounds.MinY = y0;
217 msg.NewBounds.MaxX = x1;
218 msg.NewBounds.MaxY = y1;
219 msg.OldBounds.MinX = 0;
220 msg.OldBounds.MinY = 0;
221 msg.OldBounds.MaxX = 0;
222 msg.OldBounds.MaxY = 0;
224 layershape = (struct Region *)CallHookPkt(shapehook, NULL, &msg);
227 if (layershape) if (!AndRegionRegion(layershape, shape))
229 DisposeRegion(shape);
230 return NULL;
233 if (parent)
235 /* Convert from parent layer relative coords to screen relative coords */
237 x0 += parent->bounds.MinX;
238 y0 += parent->bounds.MinY;
239 x1 += parent->bounds.MinX;
240 y1 += parent->bounds.MinY;
243 /* Make shape region relative to screen */
244 _TranslateRect(&shape->bounds, x0, y0);
246 l = AllocMem(sizeof(struct IntLayer), MEMF_CLEAR|MEMF_PUBLIC);
247 rp = CreateRastPort();
250 if (l && rp)
252 l->shape = shape;
253 IL(l)->shapehook = shapehook;
254 l->shaperegion = layershape;
255 l->rp = rp;
257 rp->Layer = l;
258 rp->BitMap = bm;
260 l->bounds.MinX = x0;
261 l->bounds.MaxX = x1;
262 l->bounds.MinY = y0;
263 l->bounds.MaxY = y1;
265 l->Flags = (WORD) flags;
266 l->LayerInfo = li;
267 l->Width = x1 - x0 + 1;
268 l->Height = y1 - y0 + 1;
270 l->SuperBitMap = superbitmap;
271 l->BackFill = hook;
272 l->priority = priority;
274 InitSemaphore(&l->Lock);
275 LockLayer(0, l);
277 if (NULL == (l->DamageList = NewRegion()))
278 goto failexit;
279 if (NULL == (l->VisibleRegion = NewRegion()))
280 goto failexit;
281 if (NULL == (l->visibleshape = NewRegion()))
282 goto failexit;
284 l->visible = visible;
286 if (NULL == li->check_lp)
287 li->check_lp = l;
289 l->parent = parent;
291 if (parent)
292 l->nesting = parent->nesting+1;
293 else
294 l->nesting = 0;
296 LockLayers(li);
300 * If neither a layer in front or behind is
301 * given the search for the place according to
302 * the priority and insert it there. I
303 * determine behind or infrontof here!
305 if (NULL != li->top_layer)
307 if (!infrontof && !behind)
309 int end = FALSE;
310 struct Layer * lastgood;
311 infrontof = parent;
315 lastgood = infrontof;
316 infrontof = infrontof->front;
317 if (NULL == infrontof)
319 infrontof = lastgood;
320 break;
322 if (infrontof->parent != l->parent)
324 infrontof = lastgood;
325 break;
327 while (infrontof->nesting >= l->nesting)
329 lastgood = infrontof;
330 infrontof = infrontof->front;
331 if (NULL == infrontof ||
332 infrontof->priority > l->priority)
334 infrontof = lastgood;
335 end = TRUE;
336 break;
342 while (FALSE == end);
347 if (infrontof || (NULL == behind))
349 if (NULL == infrontof)
350 infrontof = li->top_layer;
352 if (li->top_layer == infrontof)
354 li->top_layer = l;
355 l->front = NULL;
356 l->back = infrontof;
357 if (NULL != infrontof)
358 infrontof->front = l;
360 else
362 l->front = infrontof->front;
363 l->back = infrontof;
364 infrontof->front->back = l;
365 infrontof->front = l;
368 else if (behind)
370 l->front = behind;
371 l->back = behind->back;
372 if (l->back)
373 l->back->front = l;
374 behind->back = l;
379 SetRegion(l->shape, l->visibleshape);
380 if (l->parent)
381 AndRegionRegion(l->parent->shape, l->visibleshape);
384 if (IS_VISIBLE(l))
387 * layer is to be visible
389 struct Layer * _l = l->back;
390 struct Layer * lparent = l->parent;
393 * Does this layer have a layer in front of it?
394 * If yes, then take that layer's VisibleRegion and
395 * cut out that layer's shape. This is then the
396 * VisibleRegion of my layer.
398 if (l->front)
400 SetRegion(l->front->VisibleRegion, l->VisibleRegion);
401 ClearRegionRegion(l->front->visibleshape, l->VisibleRegion);
403 else
404 SetRegion(li->check_lp->shape, l->VisibleRegion);
408 * First tell all layers behind this layer to
409 * back up their parts that the new layer will
410 * be hiding.
412 while (1)
414 if (IS_VISIBLE(_l) && DO_OVERLAP(&l->shape->bounds, &_l->shape->bounds))
415 _BackupPartsOfLayer(_l, l->visibleshape, 0, FALSE, LayersBase);
416 else
417 ClearRegionRegion(l->visibleshape, _l->VisibleRegion);
419 if (_l == lparent)
421 if (IS_VISIBLE(_l) || (NULL == lparent->parent))
422 break;
423 else
424 lparent = lparent->parent;
426 _l = _l->back;
431 * Show the layer according to its visible area
432 * This function creates the cliprects in the area
433 * of the layer.
434 * This also works for invisible layers since their Visible
435 * Region is non existent.
437 if (!IS_ROOTLAYER(l))
438 _ShowLayer(l, LayersBase);
440 else
441 goto failexit;
443 UnlockLayers(li);
445 return l;
447 failexit:
448 if (l)
450 if (l->VisibleRegion)
451 DisposeRegion(l->VisibleRegion);
452 if (l->DamageList)
453 DisposeRegion(l->DamageList);
454 if (l->visibleshape)
455 DisposeRegion(l->visibleshape);
456 FreeMem(l, sizeof(struct IntLayer));
459 if (rp)
460 FreeRastPort(rp);
462 return NULL;
464 AROS_LIBFUNC_EXIT
465 } /* CreateBehindHookLayer */