LCOV - code coverage report
Current view: top level - compositor - mpeg4_form.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 307 322 95.3 %
Date: 2021-04-29 23:48:07 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Compositor sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : 
      28             : #include "nodes_stacks.h"
      29             : #include "mpeg4_grouping.h"
      30             : #include "visual_manager.h"
      31             : 
      32             : #ifndef GPAC_DISABLE_VRML
      33             : 
      34             : 
      35             : typedef struct
      36             : {
      37             :         PARENT_MPEG4_STACK_2D
      38             : 
      39             :         GF_List *grouplist;
      40             :         GF_Rect clip;
      41             : } FormStack;
      42             : 
      43             : /*storage of group info*/
      44             : typedef struct
      45             : {
      46             :         GF_List *children;
      47             :         GF_Rect origin, final;
      48             : } FormGroup;
      49             : 
      50             : 
      51         188 : static void form_reset(FormStack *st)
      52             : {
      53        1213 :         while (gf_list_count(st->grouplist)) {
      54        1025 :                 FormGroup * fg = (FormGroup *) gf_list_get(st->grouplist, 0);
      55        1025 :                 gf_list_rem(st->grouplist, 0);
      56        1025 :                 gf_list_del(fg->children);
      57        1025 :                 gf_free(fg);
      58             :         }
      59         188 : }
      60             : 
      61        1025 : static FormGroup *form_new_group(FormStack *st)
      62             : {
      63             :         FormGroup *fg;
      64        1025 :         GF_SAFEALLOC(fg, FormGroup);
      65        1025 :         if (!fg) {
      66           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate form group\n"));
      67             :                 return NULL;
      68             :         }
      69        1025 :         fg->children = gf_list_new();
      70        1025 :         gf_list_add(st->grouplist, fg);
      71             :         return fg;
      72             : }
      73             : 
      74             : static GFINLINE FormGroup *form_get_group(FormStack *st, u32 i)
      75             : {
      76        4306 :         return (FormGroup *) gf_list_get(st->grouplist, i);
      77             : }
      78             : 
      79        9165 : static void fg_compute_bounds(FormGroup *fg)
      80             : {
      81             :         ChildGroup *cg;
      82        9165 :         u32 i=0;
      83        9165 :         memset(&fg->origin, 0, sizeof(GF_Rect));
      84       24889 :         while ((cg = (ChildGroup *)gf_list_enum(fg->children, &i))) {
      85       15724 :                 gf_rect_union(&fg->origin, &cg->final);
      86             :         }
      87        9165 :         fg->final = fg->origin;
      88        9165 : }
      89         961 : static void fg_update_bounds(FormGroup *fg)
      90             : {
      91             :         ChildGroup *cg;
      92         961 :         u32 i=0;
      93             :         Fixed x, y;
      94         961 :         x = fg->final.x - fg->origin.x;
      95         961 :         y = fg->final.y - fg->origin.y;
      96        3522 :         while ((cg = (ChildGroup *)gf_list_enum(fg->children, &i))) {
      97        1600 :                 cg->final.x += x;
      98        1600 :                 cg->final.y += y;
      99             :         }
     100         961 :         fg_compute_bounds(fg);
     101         961 : }
     102             : 
     103             : 
     104             : static void shin_apply(FormStack *st, u32 *group_idx, u32 count);
     105             : static void sh_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count);
     106             : static void svin_apply(FormStack *st, u32 *group_idx, u32 count);
     107             : static void sv_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count);
     108             : static void al_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count);
     109             : static void ar_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count);
     110             : static void at_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count);
     111             : static void ab_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count);
     112             : static void ah_apply(FormStack *st, u32 *group_idx, u32 count);
     113             : static void av_apply(FormStack *st, u32 *group_idx, u32 count);
     114             : 
     115         260 : static void form_apply(FormStack *st, const char *constraint, u32 *group_idx, u32 count)
     116             : {
     117             :         Float val;
     118         520 :         if (!constraint || !strlen(constraint)) return;
     119             : 
     120             :         /*SHin*/
     121         260 :         if (!strnicmp(constraint, "SHin", 4)) {
     122          96 :                 shin_apply(st, group_idx, count);
     123          96 :                 return;
     124             :         }
     125             :         /*SH*/
     126         164 :         if (!strnicmp(constraint, "SH", 2)) {
     127          15 :                 if (sscanf(constraint, "SH %f", &val)==1) {
     128          14 :                         sh_apply(st, FLT2FIX(val), group_idx, count);
     129             :                 } else {
     130           1 :                         sh_apply(st, -FIX_ONE, group_idx, count);
     131             :                 }
     132             :                 return;
     133             :         }
     134             :         /*SVin*/
     135         149 :         if (!strnicmp(constraint, "SVin", 4)) {
     136          16 :                 svin_apply(st, group_idx, count);
     137          16 :                 return;
     138             :         }
     139             :         /*SV*/
     140         133 :         if (!strnicmp(constraint, "SV", 2)) {
     141          35 :                 if (sscanf(constraint, "SV %f", &val)==1) {
     142          34 :                         sv_apply(st, FLT2FIX(val), group_idx, count);
     143             :                 } else {
     144           1 :                         sv_apply(st, -FIX_ONE, group_idx, count);
     145             :                 }
     146             :                 return;
     147             :         }
     148             :         /*AL*/
     149          98 :         if (!strnicmp(constraint, "AL", 2)) {
     150           7 :                 if (sscanf(constraint, "AL %f", &val)==1) {
     151           1 :                         al_apply(st, FLT2FIX(val), group_idx, count);
     152             :                 } else {
     153           6 :                         al_apply(st, -FIX_ONE, group_idx, count);
     154             :                 }
     155             :                 return;
     156             :         }
     157             :         /*AR*/
     158          91 :         if (!strnicmp(constraint, "AR", 2)) {
     159           6 :                 if (sscanf(constraint, "AR %f", &val)==1) {
     160           1 :                         ar_apply(st, FLT2FIX(val), group_idx, count);
     161             :                 } else {
     162           5 :                         ar_apply(st, -FIX_ONE, group_idx, count);
     163             :                 }
     164             :                 return;
     165             :         }
     166             :         /*AT*/
     167          85 :         if (!strnicmp(constraint, "AT", 2)) {
     168           7 :                 if (sscanf(constraint, "AT %f", &val)==1) {
     169           1 :                         at_apply(st, FLT2FIX(val), group_idx, count);
     170             :                 } else {
     171           6 :                         at_apply(st, -FIX_ONE, group_idx, count);
     172             :                 }
     173             :                 return;
     174             :         }
     175             :         /*AB*/
     176          78 :         if (!strnicmp(constraint, "AB", 2)) {
     177          39 :                 if (sscanf(constraint, "AB %f", &val)==1) {
     178           1 :                         ab_apply(st, FLT2FIX(val), group_idx, count);
     179             :                 } else {
     180          38 :                         ab_apply(st, -FIX_ONE, group_idx, count);
     181             :                 }
     182             :                 return;
     183             :         }
     184             :         /*AH*/
     185          39 :         if (!strnicmp(constraint, "AH", 2)) {
     186          36 :                 ah_apply(st, group_idx, count);
     187          36 :                 return;
     188             :         }
     189             :         /*AV*/
     190           3 :         if (!strnicmp(constraint, "AV", 2)) {
     191           3 :                 av_apply(st, group_idx, count);
     192           3 :                 return;
     193             :         }
     194             : }
     195             : 
     196             : 
     197             : #ifndef MAX_FORM_GROUP_INDEX
     198             : #define MAX_FORM_GROUP_INDEX    100
     199             : #endif
     200             : 
     201             : /*define to 1 to let the form object clip its children (not specified in spec)*/
     202             : #define FORM_CLIPS      1
     203             : 
     204         527 : static void TraverseForm(GF_Node *n, void *rs, Bool is_destroy)
     205             : {
     206             : #if FORM_CLIPS
     207             :         GF_Rect prev_clipper;
     208             :         Bool had_clip;
     209             :         GF_IRect prev_clip;
     210             : #endif
     211             :         Bool recompute_form;
     212             :         u32 idx[MAX_FORM_GROUP_INDEX];
     213             :         u32 i, index, last_ind, j;
     214             :         u32 mode_bckup;
     215             :         ParentNode2D *parent_bck;
     216             :         FormGroup *fg;
     217             :         ChildGroup *cg;
     218             :         M_Form *fm = (M_Form *) n;
     219         527 :         FormStack *st = (FormStack *)gf_node_get_private(n);
     220             :         GF_TraverseState *tr_state = (GF_TraverseState *) rs;
     221             : 
     222         527 :         if (is_destroy) {
     223          48 :                 form_reset(st);
     224          48 :                 gf_list_del(st->grouplist);
     225          48 :                 parent_node_predestroy((ParentNode2D *)st);
     226          48 :                 gf_free(st);
     227         569 :                 return;
     228             :         }
     229             :         /*update cliper*/
     230         479 :         if ((gf_node_dirty_get(n) & GF_SG_NODE_DIRTY)) {
     231             :                 /*get visual size*/
     232          48 :                 visual_get_size_info(tr_state, &st->clip.width, &st->clip.height);
     233             :                 /*setup bounds in local coord system*/
     234          48 :                 if (fm->size.x>=0) st->clip.width = fm->size.x;
     235          48 :                 if (fm->size.y>=0) st->clip.height = fm->size.y;
     236          48 :                 st->bounds = st->clip = gf_rect_center(st->clip.width, st->clip.height);
     237             :         }
     238             :         recompute_form = GF_FALSE;
     239         479 :         if (gf_node_dirty_get(n)) recompute_form = GF_TRUE;
     240             : 
     241             : #if FORM_CLIPS
     242         479 :         if ((tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) && !tr_state->for_node) {
     243           0 :                 tr_state->bounds = st->clip;
     244             : #ifndef GPAC_DISABLE_3D
     245           0 :                 gf_bbox_from_rect(&tr_state->bbox, &st->clip);
     246             : #endif
     247           0 :                 return;
     248             :         }
     249             : #endif
     250             : 
     251         479 :         if (recompute_form) {
     252             :                 GF_Rect bounds;
     253          70 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Form] Recomputing positions\n"));
     254             : 
     255          70 :                 parent_node_reset((ParentNode2D*)st);
     256             : 
     257          70 :                 bounds.width = bounds.height = 0;
     258             : 
     259             :                 /*init traversing state*/
     260          70 :                 parent_bck = tr_state->parent;
     261          70 :                 mode_bckup = tr_state->traversing_mode;
     262          70 :                 tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
     263          70 :                 tr_state->parent = (ParentNode2D *) st;
     264             : 
     265          70 :                 parent_node_traverse(n, (ParentNode2D *)st, tr_state);
     266             : 
     267             :                 /*restore traversing state*/
     268          70 :                 tr_state->parent = parent_bck;
     269          70 :                 tr_state->traversing_mode = mode_bckup;
     270             : 
     271             :                 /*center all nodes*/
     272          70 :                 i=0;
     273         918 :                 while ((cg = (ChildGroup *)gf_list_enum(st->groups, &i))) {
     274         778 :                         cg->final.x = - cg->final.width/2;
     275         778 :                         cg->final.y = cg->final.height/2;
     276             :                 }
     277             :                 /*build groups*/
     278          70 :                 form_reset(st);
     279          70 :                 fg = form_new_group(st);
     280          70 :                 fg->origin = fg->final = st->clip;
     281             :                 fg = NULL;
     282        2594 :                 for (i=0; i<fm->groups.count; i++) {
     283        2530 :                         if (!fg) {
     284         955 :                                 fg = form_new_group(st);
     285             :                         }
     286        2530 :                         if (fm->groups.vals[i]==-1) {
     287         949 :                                 fg_compute_bounds(fg);
     288             :                                 fg = NULL;
     289         949 :                                 continue;
     290             :                         }
     291             :                         /*broken form*/
     292        1581 :                         if ((u32) fm->groups.vals[i]>gf_list_count(st->groups)) goto err_exit;
     293        1575 :                         cg = (ChildGroup *)gf_list_get(st->groups, fm->groups.vals[i]-1);
     294        1575 :                         gf_list_add(fg->children, cg);
     295             :                 }
     296             : 
     297             :                 memset(idx, 0, sizeof(u32)*MAX_FORM_GROUP_INDEX);
     298             :                 last_ind = 0;
     299         260 :                 for (i=0; i<fm->constraints.count; i++) {
     300             :                         index = 0;
     301             :                         while (1) {
     302        2470 :                                 if (last_ind+index > fm->groupsIndex.count) goto err_exit;
     303        1365 :                                 if (fm->groupsIndex.vals[last_ind+index]==-1) break;
     304        1105 :                                 if (index>=MAX_FORM_GROUP_INDEX) goto err_exit;
     305        1105 :                                 idx[index] = fm->groupsIndex.vals[last_ind+index];
     306        1105 :                                 index++;
     307             :                         }
     308             :                         /*apply*/
     309         260 :                         form_apply(st, fm->constraints.vals[i], idx, index);
     310         260 :                         index++;
     311         260 :                         last_ind += index;
     312             : 
     313             :                         /*refresh all group bounds*/
     314         260 :                         j=1;
     315        7775 :                         while ((fg = (FormGroup*)gf_list_enum(st->grouplist, &j))) {
     316        7255 :                                 fg_compute_bounds(fg);
     317        7255 :                                 gf_rect_union(&bounds, &fg->final);
     318             :                         }
     319             :                         /*done*/
     320         260 :                         if (last_ind>=fm->groupsIndex.count) break;
     321             :                 }
     322          64 :                 form_reset(st);
     323             : 
     324             : #if !FORM_CLIPS
     325             :                 st->clip = bounds;
     326             : #endif
     327             :         }
     328             : 
     329             :         /*check picking*/
     330         473 :         if ((tr_state->traversing_mode==TRAVERSE_PICK) && !gf_sc_pick_in_clipper(tr_state, &st->clip))
     331             :                 return;
     332             : 
     333             : #if !FORM_CLIPS
     334             :         if ((tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) && !tr_state->for_node) {
     335             :                 tr_state->bounds = st->clip;
     336             :                 gf_bbox_from_rect(&tr_state->bbox, &st->clip);
     337             :                 return;
     338             :         }
     339             : #endif
     340             :         /*According to the spec clipping is not required on form so we don't do it*/
     341             : #if FORM_CLIPS
     342             :         /*update clipper*/
     343         454 :         if (tr_state->traversing_mode==TRAVERSE_SORT) {
     344         286 :                 prev_clip = tr_state->visual->top_clipper;
     345         286 :                 compositor_2d_update_clipper(tr_state, st->clip, &had_clip, &prev_clipper, GF_FALSE);
     346         286 :                 if (tr_state->has_clip) {
     347         286 :                         tr_state->visual->top_clipper = gf_rect_pixelize(&tr_state->clipper);
     348         286 :                         gf_irect_intersect(&tr_state->visual->top_clipper, &prev_clip);
     349             :                 }
     350             : 
     351             : #ifndef GPAC_DISABLE_3D
     352         286 :                 if (tr_state->visual->type_3d)
     353         140 :                         visual_3d_reset_clipper_2d(tr_state->visual);
     354             : #endif
     355             : 
     356         286 :                 i=0;
     357        1800 :                 while ((cg = (ChildGroup*)gf_list_enum(st->groups, &i))) {
     358        1228 :                         parent_node_child_traverse(cg, tr_state);
     359             :                 }
     360             : 
     361             : #ifndef GPAC_DISABLE_3D
     362         286 :                 if (tr_state->visual->type_3d)
     363         140 :                         visual_3d_reset_clipper_2d(tr_state->visual);
     364             : #endif
     365         286 :                 tr_state->visual->top_clipper = prev_clip;
     366         286 :                 if (had_clip) tr_state->clipper = prev_clipper;
     367         286 :                 tr_state->has_clip = had_clip;
     368             :         } else
     369             : #endif
     370             :         {
     371         168 :                 i=0;
     372        7730 :                 while ((cg = (ChildGroup*)gf_list_enum(st->groups, &i))) {
     373        7394 :                         parent_node_child_traverse(cg, tr_state);
     374             :                 }
     375             :         }
     376             : 
     377             :         return;
     378             : 
     379             : err_exit:
     380           6 :         parent_node_reset((ParentNode2D*)st);
     381           6 :         form_reset(st);
     382             : }
     383             : 
     384          48 : void compositor_init_form(GF_Compositor *compositor, GF_Node *node)
     385             : {
     386             :         FormStack *stack;
     387          48 :         GF_SAFEALLOC(stack, FormStack);
     388          48 :         if (!stack) {
     389           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate form stack\n"));
     390             :                 return;
     391             :         }
     392             : 
     393          48 :         parent_node_setup((ParentNode2D*)stack);
     394          48 :         stack->grouplist = gf_list_new();
     395          48 :         gf_node_set_private(node, stack);
     396          48 :         gf_node_set_callback_function(node, TraverseForm);
     397             : }
     398             : 
     399             : 
     400             : /*
     401             :                         FORM CONSTRAINTS
     402             : */
     403             : 
     404             : 
     405          96 : static void shin_apply(FormStack *st, u32 *group_idx, u32 count)
     406             : {
     407             :         u32 i, len;
     408             :         Fixed tot_len, inter_space;
     409             :         tot_len = 0;
     410          96 :         inter_space = st->clip.width;
     411             : 
     412             :         len = 0;
     413         783 :         for (i=0; i<count; i++) {
     414         687 :                 if (group_idx[i] != 0) {
     415        1374 :                         tot_len += form_get_group(st, group_idx[i])->final.width;
     416         687 :                         len++;
     417             :                 }
     418             :         }
     419          96 :         inter_space -= tot_len;
     420          96 :         inter_space /= (len+1);
     421             : 
     422         783 :         for (i=0; i<count; i++) {
     423         687 :                 if(group_idx[i] == 0) continue;
     424         687 :                 if (!i) {
     425         192 :                         form_get_group(st, group_idx[0])->final.x = st->clip.x + inter_space;
     426             :                 } else {
     427        1182 :                         form_get_group(st, group_idx[i])->final.x =
     428        1773 :                             form_get_group(st, group_idx[i-1])->final.x + form_get_group(st, group_idx[i-1])->final.width
     429         591 :                             + inter_space;
     430             :                 }
     431        1374 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     432             :         }
     433          96 : }
     434             : 
     435          15 : static void sh_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count)
     436             : {
     437             :         u32 i, k;
     438             :         GF_Rect *l, *r;
     439             :         Fixed inter_space, tot_len;
     440             : 
     441             :         tot_len = 0;
     442          15 :         if (space == -FIX_ONE) {
     443           1 :                 r = &form_get_group(st, group_idx[count-1])->final;
     444           1 :                 l = &form_get_group(st, group_idx[0])->final;
     445           1 :                 inter_space = r->x - l->x;
     446           1 :                 if(group_idx[0] != 0) inter_space -= l->width;
     447           2 :                 for (i=1; i<count-1; i++) tot_len += form_get_group(st, group_idx[i])->final.width;
     448           1 :                 inter_space -= tot_len;
     449           1 :                 inter_space /= (count-1);
     450             :         } else {
     451             :                 inter_space = space;
     452             :         }
     453             : 
     454          15 :         k = count - 1;
     455          15 :         if (space != -1) k += 1;
     456          31 :         for (i=1; i<k; i++) {
     457          16 :                 if (group_idx[i] ==0) continue;
     458          16 :                 l = &form_get_group(st, group_idx[i-1])->final;
     459          16 :                 r = &form_get_group(st, group_idx[i])->final;
     460          16 :                 r->x = l->x + inter_space;
     461          16 :                 if(group_idx[i-1] != 0) r->x += l->width;
     462          32 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     463             :         }
     464          15 : }
     465             : 
     466          16 : static void svin_apply(FormStack *st, u32 *group_idx, u32 count)
     467             : {
     468             :         u32 i, len;
     469             :         Fixed tot_len, inter_space;
     470             :         tot_len = 0;
     471          16 :         inter_space = st->clip.height;
     472             :         len = 0;
     473         114 :         for (i=0; i<count; i++) {
     474          98 :                 if (group_idx[i] != 0) {
     475         196 :                         tot_len += form_get_group(st, group_idx[i])->final.height;
     476          98 :                         len++;
     477             :                 }
     478             :         }
     479          16 :         inter_space -= tot_len;
     480          16 :         inter_space /= (len+1);
     481             : 
     482         114 :         for (i=0; i<count; i++) {
     483          98 :                 if (group_idx[i] == 0) continue;
     484          98 :                 if (!i) {
     485          32 :                         form_get_group(st, group_idx[0])->final.y = st->clip.y - inter_space;
     486             :                 } else {
     487         164 :                         form_get_group(st, group_idx[i])->final.y =
     488         328 :                             form_get_group(st, group_idx[i-1])->final.y - form_get_group(st, group_idx[i-1])->final.height -
     489             :                             inter_space;
     490             :                 }
     491         196 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     492             :         }
     493          16 : }
     494             : 
     495          35 : static void sv_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count)
     496             : {
     497             :         u32 i, k;
     498             :         Fixed tot_len, inter_space;
     499             : 
     500             :         tot_len = 0;
     501          35 :         if(space > -FIX_ONE) {
     502             :                 inter_space = space;
     503             :         } else {
     504           1 :                 GF_Rect *t = &form_get_group(st, group_idx[count-1])->final;
     505           1 :                 GF_Rect *b = &form_get_group(st, group_idx[0])->final;
     506           1 :                 inter_space = b->y - t->y;
     507           1 :                 if (group_idx[0]!=0) inter_space -= t->height;
     508           2 :                 for (i=1; i<count-1; i++) tot_len += form_get_group(st, group_idx[i])->final.height;
     509           1 :                 inter_space -= tot_len;
     510           1 :                 inter_space /= count-1;
     511             :         }
     512             : 
     513          35 :         k = count-1;
     514          35 :         if (space > -1) k += 1;
     515          81 :         for (i=1; i<k; i++) {
     516          46 :                 if (group_idx[i] == 0) continue;
     517         138 :                 form_get_group(st, group_idx[i])->final.y = form_get_group(st, group_idx[i-1])->final.y - inter_space;
     518          46 :                 if (group_idx[i-1] != 0) {
     519          39 :                         form_get_group(st, group_idx[i])->final.y -= form_get_group(st, group_idx[i-1])->final.height;
     520             :                 }
     521          92 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     522             :         }
     523          35 : }
     524             : 
     525           7 : static void al_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count)
     526             : {
     527             :         Fixed min_x;
     528             :         GF_Rect *rc;
     529             :         u32 i, start;
     530             : 
     531             :         start = 0;
     532          14 :         min_x = form_get_group(st, group_idx[0])->final.x;
     533           7 :         if (space>-FIX_ONE) {
     534             :                 start = 1;
     535           1 :                 min_x += space;
     536             :         } else {
     537           6 :                 for (i=1; i<count; i++) {
     538           6 :                         rc = &form_get_group(st, group_idx[0])->final;
     539           6 :                         if (group_idx[i]==0) {
     540           0 :                                 min_x = rc->x;
     541           0 :                                 break;
     542             :                         }
     543           6 :                         if (rc->x < min_x) min_x = rc->x;
     544             :                 }
     545             :         }
     546          20 :         for (i=start; i<count; i++) {
     547          13 :                 if( group_idx[i] == 0) continue;
     548          14 :                 form_get_group(st, group_idx[i])->final.x = min_x;
     549          14 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     550             :         }
     551           7 : }
     552             : 
     553           6 : static void ar_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count)
     554             : {
     555             :         Fixed max_x;
     556             :         u32 i, start;
     557             :         GF_Rect *rc;
     558             : 
     559             :         start = 0;
     560           6 :         rc = &form_get_group(st, group_idx[0])->final;
     561           6 :         max_x = rc->x + rc->width;
     562             : 
     563           6 :         if(space>-FIX_ONE) {
     564           1 :                 max_x -= space;
     565             :                 start = 1;
     566             :         } else {
     567           5 :                 for (i=1; i<count; i++) {
     568           5 :                         rc = &form_get_group(st, group_idx[i])->final;
     569           5 :                         if (group_idx[i]==0) {
     570           0 :                                 max_x = rc->x + rc->width;
     571           0 :                                 break;
     572             :                         }
     573           5 :                         if (rc->x + rc->width > max_x) max_x = rc->x + rc->width;
     574             :                 }
     575             :         }
     576          17 :         for (i=start; i<count; i++) {
     577          11 :                 if(group_idx[i] == 0) continue;
     578           6 :                 rc = &form_get_group(st, group_idx[i])->final;
     579           6 :                 rc->x = max_x - rc->width;
     580          12 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     581             :         }
     582           6 : }
     583             : 
     584           7 : static void at_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count)
     585             : {
     586             :         Fixed max_y;
     587             :         u32 i, start;
     588             :         GF_Rect *rc;
     589             : 
     590             :         start = 0;
     591          14 :         max_y = form_get_group(st, group_idx[0])->final.y;
     592           7 :         if(space>-FIX_ONE) {
     593             :                 start = 1;
     594           1 :                 max_y -= space;
     595             :         } else {
     596           6 :                 for (i=1; i<count; i++) {
     597           6 :                         rc = &form_get_group(st, group_idx[i])->final;
     598           6 :                         if (group_idx[i]==0) {
     599           0 :                                 max_y = rc->y;
     600           0 :                                 break;
     601             :                         }
     602           6 :                         if (rc->y > max_y) max_y = rc->y;
     603             :                 }
     604             :         }
     605             : 
     606          20 :         for (i=start; i<count; i++) {
     607          13 :                 if(group_idx[i] == 0) continue;
     608          14 :                 form_get_group(st, group_idx[i])->final.y = max_y;
     609          14 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     610             :         }
     611           7 : }
     612             : 
     613          39 : static void ab_apply(FormStack *st, Fixed space, u32 *group_idx, u32 count)
     614             : {
     615             :         Fixed min_y;
     616             :         u32 i, start;
     617             :         GF_Rect *rc;
     618             : 
     619             :         start = 0;
     620          39 :         rc = &form_get_group(st, group_idx[0])->final;
     621          39 :         min_y = rc->y - rc->height;
     622          39 :         if(space>-FIX_ONE) {
     623             :                 start = 1;
     624           1 :                 min_y += space;
     625             :         } else {
     626          38 :                 for (i=1; i<count; i++) {
     627          38 :                         rc = &form_get_group(st, group_idx[i])->final;
     628          38 :                         if (group_idx[i]==0) {
     629           0 :                                 min_y = rc->y - rc->height;
     630           0 :                                 break;
     631             :                         }
     632          38 :                         if (rc->y - rc->height < min_y) min_y = rc->y - rc->height;
     633             :                 }
     634             :         }
     635         116 :         for (i=start; i<count; i++) {
     636          77 :                 if(group_idx[i] == 0) continue;
     637          39 :                 rc = &form_get_group(st, group_idx[i])->final;
     638          39 :                 rc->y = min_y + rc->height;
     639          78 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     640             :         }
     641          39 : }
     642             : 
     643          36 : static void ah_apply(FormStack *st, u32 *group_idx, u32 count)
     644             : {
     645             :         GF_Rect *rc;
     646             :         u32 i;
     647             :         Fixed left, right, center;
     648             :         left = right = center = 0;
     649             : 
     650          42 :         for (i=0; i<count; i++) {
     651          39 :                 rc = &form_get_group(st, group_idx[i])->final;
     652          39 :                 if(group_idx[i] == 0) {
     653          33 :                         center = rc->x + rc->width / 2;
     654          33 :                         break;
     655             :                 }
     656           6 :                 if (left > rc->x) left = rc->x;
     657           6 :                 if (right < rc->x + rc->width) right = rc->x + rc->width;
     658           6 :                 center = (left+right)/2;
     659             :         }
     660             : 
     661         118 :         for (i=0; i<count; i++) {
     662          82 :                 if(group_idx[i] == 0) continue;
     663          49 :                 rc = &form_get_group(st, group_idx[i])->final;
     664          49 :                 rc->x = center - rc->width/2;
     665          98 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     666             :         }
     667          36 : }
     668             : 
     669           3 : static void av_apply(FormStack *st, u32 *group_idx, u32 count)
     670             : {
     671             :         u32 i;
     672             :         Fixed top, bottom, center;
     673             :         GF_Rect *rc;
     674             :         top = bottom = center = 0;
     675             : 
     676           9 :         for (i=0; i<count; i++) {
     677           6 :                 rc = &form_get_group(st, group_idx[i])->final;
     678           6 :                 if (group_idx[i] == 0) {
     679           0 :                         center = rc->y - rc->height / 2;
     680           0 :                         break;
     681             :                 }
     682           6 :                 if (top < rc->y) top = rc->y;
     683           6 :                 if (bottom > rc->y - rc->height) bottom = rc->y - rc->height;
     684           6 :                 center = (top+bottom)/2;
     685             :         }
     686             : 
     687           9 :         for (i=0; i<count; i++) {
     688           6 :                 if(group_idx[i] == 0) continue;
     689           6 :                 rc = &form_get_group(st, group_idx[i])->final;
     690           6 :                 rc->y = center + rc->height/2;
     691          12 :                 fg_update_bounds(form_get_group(st, group_idx[i]));
     692             :         }
     693           3 : }
     694             : 
     695             : #endif /*GPAC_DISABLE_VRML*/

Generated by: LCOV version 1.13