revert between 56095 -> 55830 in arch
[AROS.git] / rom / hyperlayers / createlayertaglist.c
blob9d9ed4e8ac816a55252bd0a34bb1e3f7417f8681
1 /*
2 Copyright © 1995-2011, 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 <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;
29 APTR win = 0;
30 int visible = TRUE;
31 struct Layer * behind = NULL, * infrontof = NULL, * parent = NULL;
32 struct Layer * l;
33 struct Region * layershape = NULL, *shape;
34 struct TagItem *tag, *tstate = tagList;
36 while((tag = NextTagItem(&tstate)))
38 switch (tag->ti_Tag)
40 case LA_BackfillHook:
41 hook = (struct Hook *)tag->ti_Data;
42 break;
44 case LA_SuperBitMap:
45 superbitmap = (struct BitMap *)tag->ti_Data;
46 break;
48 case LA_ChildOf:
49 parent = (struct Layer *)tag->ti_Data;
50 break;
52 case LA_InFrontOf:
53 infrontof = (struct Layer *)tag->ti_Data;
54 break;
56 case LA_Behind:
57 behind = (struct Layer *)tag->ti_Data;
58 break;
60 case LA_Hidden:
61 visible = !tag->ti_Data;
62 break;
64 case LA_ShapeRegion:
65 layershape = (struct Region *)tag->ti_Data;
66 break;
68 case LA_ShapeHook:
69 shapehook = (struct Hook *)tag->ti_Data;
70 break;
72 case LA_WindowPtr:
73 win = (APTR)tag->ti_Data;
74 break;
78 } /* while((tag = NextTagItem(&tstate))) */
80 if ((flags & LAYERSUPER) && (NULL == superbitmap))
81 return NULL;
83 if (!parent)
85 parent = li->check_lp;
86 if (!parent)
88 /* Root layer not yet installed */
90 if (priority != ROOTPRIORITY) /* avoid endless recursion */
92 struct TagItem tags[] =
94 {LA_Hidden, TRUE },
95 {TAG_DONE }
98 if (!(CreateLayerTagList(li,
99 bm,
102 GetBitMapAttr(bm, BMA_WIDTH) - 1,
103 GetBitMapAttr(bm, BMA_HEIGHT) - 1,
105 ROOTPRIORITY,
106 tags,
107 LayersBase)))
109 li->check_lp = NULL;
110 return NULL;
113 parent = li->check_lp;
119 * User gives coordinates reltive to parent.
120 * Adjust the shape to the absolute coordinates
121 * If this is the root layer, I don't have to
122 * do anything. I recognize the root layer if there
123 * is no parent.
126 if (infrontof && infrontof->priority > priority)
127 return NULL;
129 if (behind && behind->priority < priority)
130 return NULL;
132 /* First create the shape region relative to nothing, that is 0,0 origin */
134 shape = NewRectRegion(0, 0, x1 - x0, y1 - y0);
135 if (!shape)
136 return NULL;
138 if (shapehook)
140 struct ShapeHookMsg msg;
141 struct Rectangle NewBounds, OldBounds;
143 msg.NewShape = layershape;
144 msg.OldShape = layershape;
145 msg.NewBounds = &NewBounds;
146 msg.OldBounds = &OldBounds;
148 NewBounds.MinX = x0;
149 NewBounds.MinY = y0;
150 NewBounds.MaxX = x1;
151 NewBounds.MaxY = y1;
152 OldBounds.MinX = 0;
153 OldBounds.MinY = 0;
154 OldBounds.MaxX = 0;
155 OldBounds.MaxY = 0;
157 if (CallHookPkt(shapehook, NULL, &msg))
158 layershape = msg.NewShape;
161 if (layershape) if (!AndRegionRegion(layershape, shape))
163 DisposeRegion(shape);
164 return NULL;
167 if (parent)
169 /* Convert from parent layer relative coords to screen relative coords */
171 x0 += parent->bounds.MinX;
172 y0 += parent->bounds.MinY;
173 x1 += parent->bounds.MinX;
174 y1 += parent->bounds.MinY;
177 /* Make shape region relative to screen */
178 _TranslateRect(&shape->bounds, x0, y0);
180 l = AllocMem(sizeof(struct IntLayer), MEMF_CLEAR|MEMF_PUBLIC);
181 if (l)
183 IL(l)->shapehook = shapehook;
184 l->Window = win;
185 l->shaperegion = layershape;
186 l->rp = &IL(l)->rp;
188 InitRastPort(l->rp);
189 l->rp->Layer = l;
190 l->rp->BitMap = bm;
192 l->Flags = (WORD) flags;
193 l->LayerInfo = li;
195 l->SuperBitMap = superbitmap;
196 l->BackFill = hook;
197 l->priority = priority;
199 InitSemaphore(&l->Lock);
201 l->shape = shape;
202 l->bounds.MinX = x0;
203 l->bounds.MaxX = x1;
204 l->bounds.MinY = y0;
205 l->bounds.MaxY = y1;
206 l->Width = x1 - x0 + 1;
207 l->Height = y1 - y0 + 1;
209 LockLayer(0, l);
211 if (NULL == (l->DamageList = NewRegion()))
212 goto failexit;
213 if (NULL == (l->VisibleRegion = NewRegion()))
214 goto failexit;
215 if (NULL == (l->visibleshape = NewRegion()))
216 goto failexit;
218 l->visible = visible;
220 if (NULL == li->check_lp)
221 li->check_lp = l;
223 l->parent = parent;
225 if (parent)
226 l->nesting = parent->nesting+1;
227 else
228 l->nesting = 0;
230 LockLayers(li);
234 * If neither a layer in front or behind is
235 * given the search for the place according to
236 * the priority and insert it there. I
237 * determine behind or infrontof here!
239 if (NULL != li->top_layer)
241 if (!infrontof && !behind)
243 int end = FALSE;
244 struct Layer * lastgood;
245 infrontof = parent;
249 lastgood = infrontof;
250 infrontof = infrontof->front;
251 if (NULL == infrontof)
253 infrontof = lastgood;
254 break;
256 if (infrontof->parent != l->parent)
258 infrontof = lastgood;
259 break;
261 while (infrontof->nesting >= l->nesting)
263 lastgood = infrontof;
264 infrontof = infrontof->front;
265 if (NULL == infrontof ||
266 infrontof->priority > l->priority)
268 infrontof = lastgood;
269 end = TRUE;
270 break;
276 while (FALSE == end);
281 if (infrontof || (NULL == behind))
283 if (NULL == infrontof)
284 infrontof = li->top_layer;
286 if (li->top_layer == infrontof)
288 li->top_layer = l;
289 l->front = NULL;
290 l->back = infrontof;
291 if (NULL != infrontof)
292 infrontof->front = l;
294 else
296 l->front = infrontof->front;
297 l->back = infrontof;
298 infrontof->front->back = l;
299 infrontof->front = l;
302 else if (behind)
304 l->front = behind;
305 l->back = behind->back;
306 if (l->back)
307 l->back->front = l;
308 behind->back = l;
313 SetRegion(l->shape, l->visibleshape);
314 if (l->parent)
315 AndRegionRegion(l->parent->shape, l->visibleshape);
318 if (IS_VISIBLE(l))
321 * layer is to be visible
323 struct Layer * _l = l->back;
324 struct Layer * lparent = l->parent;
327 * Does this layer have a layer in front of it?
328 * If yes, then take that layer's VisibleRegion and
329 * cut out that layer's shape. This is then the
330 * VisibleRegion of my layer.
332 if (l->front)
334 SetRegion(l->front->VisibleRegion, l->VisibleRegion);
335 ClearRegionRegion(l->front->visibleshape, l->VisibleRegion);
337 else
338 SetRegion(li->check_lp->shape, l->VisibleRegion);
342 * First tell all layers behind this layer to
343 * back up their parts that the new layer will
344 * be hiding.
346 while (1)
348 if (IS_VISIBLE(_l) && DO_OVERLAP(&l->shape->bounds, &_l->shape->bounds))
349 _BackupPartsOfLayer(_l, l->visibleshape, 0, FALSE, LayersBase);
350 else
351 ClearRegionRegion(l->visibleshape, _l->VisibleRegion);
353 if (_l == lparent)
355 if (IS_VISIBLE(_l) || (NULL == lparent->parent))
356 break;
357 else
358 lparent = lparent->parent;
360 _l = _l->back;
365 * Show the layer according to its visible area
366 * This function creates the cliprects in the area
367 * of the layer.
368 * This also works for invisible layers since their Visible
369 * Region is non existent.
371 if (!IS_ROOTLAYER(l))
372 _ShowLayer(l, LayersBase);
374 else
375 goto failexit;
377 UnlockLayers(li);
379 return l;
381 failexit:
382 if (l)
384 if (l->VisibleRegion)
385 DisposeRegion(l->VisibleRegion);
386 if (l->DamageList)
387 DisposeRegion(l->DamageList);
388 if (l->visibleshape)
389 DisposeRegion(l->visibleshape);
390 FreeMem(l, sizeof(struct IntLayer));
393 return NULL;
394 } /* CreateBehindHookLayer */