LCOV - code coverage report
Current view: top level - compositor - mpeg4_path_layout.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 89 118 75.4 %
Date: 2021-04-29 23:48:07 Functions: 2 2 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             : #include "nodes_stacks.h"
      27             : #include "mpeg4_grouping.h"
      28             : #include "visual_manager.h"
      29             : 
      30             : #ifndef GPAC_DISABLE_VRML
      31             : 
      32             : typedef struct
      33             : {
      34             :         PARENT_MPEG4_STACK_2D
      35             : 
      36             :         GF_Node *last_geom;
      37             :         GF_PathIterator *iter;
      38             : } PathLayoutStack;
      39             : 
      40             : 
      41             : 
      42             : 
      43         489 : static void TraversePathLayout(GF_Node *node, void *rs, Bool is_destroy)
      44             : {
      45             :         u32 i, count, minor, major, int_bck;
      46             :         Fixed length, offset, length_after_point;
      47             :         Bool res;
      48             :         u32 mode_bckup;
      49             :         ChildGroup *cg;
      50             : #ifndef GPAC_DISABLE_3D
      51             :         GF_Matrix mat;
      52             : #endif
      53             :         GF_Matrix2D mx2d;
      54             :         ParentNode2D *parent_bck;
      55         489 :         PathLayoutStack *gr = (PathLayoutStack*) gf_node_get_private(node);
      56             :         M_PathLayout *pl = (M_PathLayout *)node;
      57             :         GF_TraverseState *tr_state = (GF_TraverseState *) rs;
      58             : 
      59         489 :         if (is_destroy) {
      60           8 :                 parent_node_predestroy((ParentNode2D *)gr);
      61           8 :                 if (gr->iter) gf_path_iterator_del(gr->iter);
      62           8 :                 gf_free(gr);
      63           8 :                 return;
      64             :         }
      65         481 :         if (!pl->geometry) return;
      66             : 
      67             :         /*only low-level primitives allowed*/
      68         339 :         switch (gf_node_get_tag((GF_Node *) pl->geometry)) {
      69             :         case TAG_MPEG4_Rectangle:
      70             :                 return;
      71             :         case TAG_MPEG4_Circle:
      72             :                 return;
      73             :         case TAG_MPEG4_Ellipse:
      74             :                 return;
      75             :         }
      76             : 
      77             :         /*store traversing state*/
      78             : #ifndef GPAC_DISABLE_3D
      79         339 :         gf_mx_copy(mat, tr_state->model_matrix);
      80         678 :         gf_mx_init(tr_state->model_matrix);
      81             : #endif
      82             : 
      83         339 :         gf_mx2d_copy(mx2d, tr_state->transform);
      84         339 :         gf_mx2d_init(tr_state->transform);
      85             : 
      86         339 :         parent_bck = tr_state->parent;
      87         339 :         tr_state->parent = NULL;
      88             : 
      89             :         /*check geom changes*/
      90         339 :         if ((pl->geometry != gr->last_geom) || gf_node_dirty_get(pl->geometry)) {
      91         339 :                 if (gr->iter) gf_path_iterator_del(gr->iter);
      92         339 :                 gr->iter = NULL;
      93             : 
      94         339 :                 int_bck = tr_state->switched_off;
      95         339 :                 mode_bckup = tr_state->traversing_mode;
      96         339 :                 tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
      97         339 :                 tr_state->switched_off = 1;
      98         339 :                 gf_node_traverse((GF_Node *)pl->geometry, tr_state);
      99         339 :                 tr_state->traversing_mode = mode_bckup;
     100         339 :                 tr_state->switched_off = int_bck;
     101             :         }
     102             : 
     103         339 :         if (!gr->iter) {
     104             :                 Drawable *dr = NULL;
     105             :                 /*get the drawable */
     106         339 :                 switch (gf_node_get_tag(pl->geometry) ) {
     107         339 :                 case TAG_MPEG4_Circle:
     108             :                 case TAG_MPEG4_Curve2D:
     109             :                 case TAG_MPEG4_XCurve2D:
     110             :                 case TAG_MPEG4_Ellipse:
     111             :                 case TAG_MPEG4_IndexedLineSet2D:
     112             :                 case TAG_MPEG4_IndexedFaceSet2D:
     113             :                 case TAG_MPEG4_Rectangle:
     114             : #ifndef GPAC_DISABLE_X3D
     115             :                 case TAG_X3D_Disk2D:
     116             :                 case TAG_X3D_Arc2D:
     117             :                 case TAG_X3D_Polyline2D:
     118             :                 case TAG_X3D_TriangleSet2D:
     119             : #endif
     120         339 :                         dr = (Drawable *) gf_node_get_private( (GF_Node *) pl->geometry);
     121             :                         break;
     122             :                 default:
     123             :                         break;
     124             :                 }
     125             :                 /*init iteration*/
     126         339 :                 if (!dr || !dr->path) return;
     127         339 :                 gr->iter = gf_path_iterator_new(dr->path);
     128         339 :                 if (!gr->iter) return;
     129             :         }
     130             : 
     131         339 :         tr_state->parent = (ParentNode2D *) gr;
     132         339 :         int_bck = tr_state->text_split_mode;
     133         339 :         tr_state->text_split_mode = 2;
     134         339 :         mode_bckup = tr_state->traversing_mode;
     135         339 :         tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
     136         339 :         parent_node_traverse(node, (ParentNode2D *) gr, tr_state);
     137         339 :         tr_state->text_split_mode = int_bck;
     138         339 :         tr_state->traversing_mode = mode_bckup;
     139             : 
     140             :         /*restore traversing state*/
     141             : #ifndef GPAC_DISABLE_3D
     142             :         gf_mx_copy(tr_state->model_matrix, mat);
     143             : #endif
     144         339 :         tr_state->parent = parent_bck;
     145             :         gf_mx2d_copy(tr_state->transform, mx2d);
     146             : 
     147         339 :         count = gf_list_count(gr->groups);
     148             : 
     149         339 :         length = gf_path_iterator_get_length(gr->iter);
     150             :         /*place all children*/
     151         339 :         offset = gf_mulfix(length, pl->pathOffset);
     152             : 
     153         339 :         major = pl->alignment.count ? pl->alignment.vals[0] : 0;
     154         339 :         minor = (pl->alignment.count==2) ? pl->alignment.vals[1] : 0;
     155             : 
     156         339 :         if (pl->wrapMode==1) {
     157          48 :                 while (offset<0) offset += length;
     158             :         }
     159             : 
     160        4548 :         for (i=0; i<count; i++) {
     161        4548 :                 cg = (ChildGroup*)gf_list_get(gr->groups, i);
     162        4548 :                 if (cg->original.width>length) break;
     163             : 
     164             :                 /*first set our center and baseline*/
     165        4548 :                 gf_mx2d_init(mx2d);
     166             : 
     167             :                 /*major align*/
     168        4548 :                 switch (major) {
     169           0 :                 case 2:
     170           0 :                         if (cg->ascent) gf_mx2d_add_translation(&mx2d, -cg->original.x - cg->original.width, 0);
     171           0 :                         else gf_mx2d_add_translation(&mx2d, -cg->original.width/2, 0);
     172             :                         length_after_point = 0;
     173             :                         break;
     174           0 :                 case 1:
     175           0 :                         length_after_point = cg->original.width/2;
     176           0 :                         if (cg->ascent) gf_mx2d_add_translation(&mx2d, -cg->original.x - cg->original.width / 2, 0);
     177             :                         break;
     178        4548 :                 default:
     179             :                 case 0:
     180        4548 :                         if (cg->ascent) gf_mx2d_add_translation(&mx2d, cg->original.x, 0);
     181        1044 :                         else gf_mx2d_add_translation(&mx2d, cg->original.width/2, 0);
     182        4548 :                         length_after_point = cg->original.width;
     183        4548 :                         break;
     184             :                 }
     185             : 
     186             :                 /*if wrapping and out of path, restart*/
     187        4548 :                 if ((pl->wrapMode==1) && (offset+length_after_point>=length)) {
     188             :                         offset += length_after_point;
     189          48 :                         offset -= length;
     190          48 :                         i--;
     191          48 :                         continue;
     192             :                 }
     193             :                 /*if not wrapping and not yet in path skip */
     194        4500 :                 if (!pl->wrapMode && (offset+length_after_point < 0)) {
     195        1094 :                         parent_node_child_traverse_matrix(cg, (GF_TraverseState *)rs, NULL);
     196        1094 :                         goto next;
     197             :                 }
     198             : 
     199             :                 /*minor justify*/
     200        3406 :                 switch (minor) {
     201             :                 /*top alignment*/
     202           0 :                 case 3:
     203           0 :                         if (cg->ascent)
     204           0 :                                 gf_mx2d_add_translation(&mx2d, 0, -1 * cg->ascent);
     205             :                         else
     206           0 :                                 gf_mx2d_add_translation(&mx2d, 0, -1 * cg->original.height / 2);
     207             : 
     208             :                         break;
     209             :                 /*baseline*/
     210        3406 :                 case 1:
     211             :                         /*move to bottom align if not text*/
     212        3406 :                         if (!cg->ascent)
     213         727 :                                 gf_mx2d_add_translation(&mx2d, 0, cg->original.height / 2);
     214             :                         break;
     215             :                 /*middle*/
     216           0 :                 case 2:
     217             :                         /*if text use (asc+desc) /2 as line height since glyph height differ*/
     218           0 :                         if (cg->ascent)
     219           0 :                                 gf_mx2d_add_translation(&mx2d, 0, cg->descent - (cg->ascent + cg->descent) / 2);
     220             :                         break;
     221             :                 /*bottomline alignment*/
     222           0 :                 case 0:
     223             :                 default:
     224           0 :                         if (cg->ascent)
     225           0 :                                 gf_mx2d_add_translation(&mx2d, 0, cg->descent);
     226             :                         else
     227           0 :                                 gf_mx2d_add_translation(&mx2d, 0, cg->original.height / 2);
     228             : 
     229             :                         break;
     230             :                 }
     231        3406 :                 res = gf_path_iterator_get_transform(gr->iter, offset, (Bool) (pl->wrapMode==2), &mx2d, 1, length_after_point);
     232        3406 :                 if (!res) break;
     233             : 
     234        3406 :                 parent_node_child_traverse_matrix(cg, (GF_TraverseState *)rs, &mx2d);
     235             : 
     236        4500 : next:
     237        4500 :                 if (i+1<count) {
     238        4161 :                         ChildGroup *cg_next = (ChildGroup*)gf_list_get(gr->groups, i+1);
     239             : 
     240             :                         /*update offset according to major alignment */
     241        4161 :                         switch (major) {
     242           0 :                         case 2:
     243           0 :                                 if (cg_next->ascent) offset += gf_mulfix(pl->spacing , cg_next->original.x);
     244           0 :                                 offset += gf_mulfix(pl->spacing , cg_next->original.width);
     245           0 :                                 break;
     246           0 :                         case 1:
     247           0 :                                 if (cg->ascent) offset += gf_mulfix(pl->spacing, cg->original.x) / 2;
     248           0 :                                 offset += gf_mulfix(pl->spacing, cg->original.width) / 2;
     249           0 :                                 offset += cg_next->original.width / 2;
     250           0 :                                 break;
     251        4161 :                         default:
     252             :                         case 0:
     253        4161 :                                 if (cg->ascent) offset += gf_mulfix(pl->spacing, cg->original.x);
     254        4161 :                                 offset += gf_mulfix(pl->spacing , cg->original.width);
     255        4161 :                                 break;
     256             :                         }
     257         339 :                 }
     258             :                 /*wrap*/
     259        4500 :                 if ((pl->wrapMode==1) && (offset>=length)) offset-=length;
     260             :         }
     261             : 
     262             :         /*undrawn nodes*/
     263           0 :         for (; i<count; i++) {
     264           0 :                 cg = (ChildGroup*)gf_list_get(gr->groups, i);
     265           0 :                 parent_node_child_traverse_matrix(cg, (GF_TraverseState *)rs, NULL);
     266             :         }
     267             : 
     268         339 :         parent_node_reset((ParentNode2D *) gr);
     269             : }
     270             : 
     271           8 : void compositor_init_path_layout(GF_Compositor *compositor, GF_Node *node)
     272             : {
     273             :         PathLayoutStack *stack;
     274           8 :         GF_SAFEALLOC(stack, PathLayoutStack);
     275           8 :         if (!stack) return;
     276             :         
     277           8 :         parent_node_setup((ParentNode2D*)stack);
     278           8 :         gf_node_set_private(node, stack);
     279           8 :         gf_node_set_callback_function(node, TraversePathLayout);
     280             : }
     281             : 
     282             : #endif /*GPAC_DISABLE_VRML*/

Generated by: LCOV version 1.13