LCOV - code coverage report
Current view: top level - compositor - svg_base.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 74 93 79.6 %
Date: 2021-04-29 23:48:07 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Cyril Concolato - Jean le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2005-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 "visual_manager.h"
      27             : 
      28             : #ifndef GPAC_DISABLE_SVG
      29             : #include "nodes_stacks.h"
      30             : #include <gpac/iso639.h>
      31             : 
      32             : 
      33             : /*
      34             :         This is the generic routine for children traversing
      35             : */
      36       10352 : void compositor_svg_traverse_children(GF_ChildNodeItem *children, GF_TraverseState *tr_state)
      37             : {
      38       73146 :         while (children) {
      39       52442 :                 gf_node_traverse(children->node, tr_state);
      40       52442 :                 children = children->next;
      41             :         }
      42       10352 : }
      43             : 
      44       38509 : Bool compositor_svg_is_display_off(SVGPropertiesPointers *props)
      45             : {
      46       38509 :         return (props->display && (*(props->display) == SVG_DISPLAY_NONE)) ? GF_TRUE : GF_FALSE;
      47             : }
      48             : 
      49             : 
      50       36257 : void compositor_svg_apply_local_transformation(GF_TraverseState *tr_state, SVGAllAttributes *atts, GF_Matrix2D *backup_matrix_2d, GF_Matrix *backup_matrix)
      51             : {
      52             : #ifndef GPAC_DISABLE_3D
      53       36257 :         if (tr_state->visual->type_3d && backup_matrix) {
      54          13 :                 Bool is_draw = (tr_state->traversing_mode==TRAVERSE_SORT) ? GF_TRUE : GF_FALSE;
      55          13 :                 gf_mx_copy(*backup_matrix, tr_state->model_matrix);
      56             : 
      57          13 :                 if (atts->transform && atts->transform->is_ref) {
      58           0 :                         gf_mx_from_mx2d(&tr_state->model_matrix, &tr_state->vb_transform);
      59           0 :                         if (is_draw) {
      60           0 :                                 gf_mx_init(tr_state->model_matrix);
      61           0 :                                 gf_mx_add_translation(&tr_state->model_matrix, -tr_state->camera->width/2, tr_state->camera->height/2, 0);
      62           0 :                                 gf_mx_add_scale(&tr_state->model_matrix, FIX_ONE, -FIX_ONE, FIX_ONE);
      63           0 :                                 gf_mx_add_matrix_2d(&tr_state->model_matrix, &tr_state->vb_transform);
      64             :                         }
      65             :                 }
      66             : 
      67          13 :                 if (atts->motionTransform) {
      68           0 :                         gf_mx_add_matrix_2d(&tr_state->model_matrix, atts->motionTransform);
      69             :                 }
      70             : 
      71          13 :                 if (atts->transform) {
      72           0 :                         gf_mx_add_matrix_2d(&tr_state->model_matrix, &atts->transform->mat);
      73             :                 }
      74             :                 return;
      75             :         }
      76             : #endif
      77       36244 :         gf_mx2d_copy(*backup_matrix_2d, tr_state->transform);
      78             : 
      79       36244 :         if (atts->transform && atts->transform->is_ref)
      80           0 :                 gf_mx2d_copy(tr_state->transform, tr_state->vb_transform);
      81             : 
      82       36244 :         if (atts->motionTransform)
      83         300 :                 gf_mx2d_pre_multiply(&tr_state->transform, atts->motionTransform);
      84             : 
      85       36244 :         if (atts->transform)
      86        4255 :                 gf_mx2d_pre_multiply(&tr_state->transform, &atts->transform->mat);
      87             : 
      88             : }
      89             : 
      90       36257 : void compositor_svg_restore_parent_transformation(GF_TraverseState *tr_state, GF_Matrix2D *backup_matrix_2d, GF_Matrix *backup_matrix)
      91             : {
      92             : #ifndef GPAC_DISABLE_3D
      93       36257 :         if (tr_state->visual->type_3d && backup_matrix) {
      94          13 :                 gf_mx_copy(tr_state->model_matrix, *backup_matrix);
      95             :                 return;
      96             :         }
      97             : #endif
      98       36244 :         gf_mx2d_copy(tr_state->transform, *backup_matrix_2d);
      99             : }
     100             : 
     101             : #ifdef GPAC_UNUSED_FUNC
     102             : static void gf_svg_apply_inheritance_no_inheritance(SVGAllAttributes *all_atts, SVGPropertiesPointers *render_svg_props)
     103             : {
     104             : #define CHECK_PROP(a, b) if (b) a = b;
     105             : 
     106             :         render_svg_props->audio_level = NULL;
     107             :         CHECK_PROP(render_svg_props->display, all_atts->display);
     108             :         CHECK_PROP(render_svg_props->fill, all_atts->fill);
     109             :         CHECK_PROP(render_svg_props->fill_opacity, all_atts->fill_opacity);
     110             :         CHECK_PROP(render_svg_props->fill_rule, all_atts->fill_rule);
     111             :         CHECK_PROP(render_svg_props->solid_color, all_atts->solid_color);
     112             :         CHECK_PROP(render_svg_props->solid_opacity, all_atts->solid_opacity);
     113             :         CHECK_PROP(render_svg_props->stop_color, all_atts->stop_color);
     114             :         CHECK_PROP(render_svg_props->stop_opacity, all_atts->stop_opacity);
     115             :         CHECK_PROP(render_svg_props->stroke, all_atts->stroke);
     116             :         CHECK_PROP(render_svg_props->stroke_dasharray, all_atts->stroke_dasharray);
     117             :         CHECK_PROP(render_svg_props->stroke_dashoffset, all_atts->stroke_dashoffset);
     118             :         CHECK_PROP(render_svg_props->stroke_linecap, all_atts->stroke_linecap);
     119             :         CHECK_PROP(render_svg_props->stroke_linejoin, all_atts->stroke_linejoin);
     120             :         CHECK_PROP(render_svg_props->stroke_miterlimit, all_atts->stroke_miterlimit);
     121             :         CHECK_PROP(render_svg_props->stroke_opacity, all_atts->stroke_opacity);
     122             :         CHECK_PROP(render_svg_props->stroke_width, all_atts->stroke_width);
     123             :         CHECK_PROP(render_svg_props->visibility, all_atts->visibility);
     124             : }
     125             : #endif /*GPAC_UNUSED_FUNC*/
     126             : 
     127             : static const struct svg_11_feature {
     128             :         const char *name;
     129             :         Bool supported;
     130             : } svg11_features[] =
     131             : {
     132             :         { "Animation", GF_TRUE},
     133             :         { "AnimationEventsAttribute", GF_TRUE},
     134             :         { "BasicClip", GF_FALSE},
     135             :         { "BasicFilter", GF_FALSE},
     136             :         { "BasicFont", GF_TRUE},
     137             :         { "BasicGraphicsAttribute", GF_TRUE},
     138             :         { "BasicPaintAttribute", GF_TRUE},
     139             :         { "BasicStructure", GF_TRUE},
     140             :         { "BasicText", GF_TRUE},
     141             :         { "Clip", GF_FALSE},
     142             :         { "ColorProfile", GF_FALSE},
     143             :         { "ConditionalProcessing", GF_TRUE},
     144             :         { "ContainerAttribute", GF_TRUE},
     145             :         { "CoreAttribute", GF_TRUE},
     146             :         { "Cursor", GF_FALSE},
     147             :         { "DocumentEventsAttribute", GF_TRUE},
     148             :         { "Extensibility", GF_TRUE},
     149             :         { "ExternalResourcesRequired", GF_FALSE},
     150             :         { "Font", GF_TRUE},
     151             :         { "Filter", GF_FALSE},
     152             :         { "Gradient", GF_TRUE},
     153             :         { "GraphicalEventsAttribute", GF_TRUE},
     154             :         { "GraphicsAttribute", GF_TRUE},
     155             :         { "Hyperlinking", GF_TRUE},
     156             :         { "Image", GF_TRUE},
     157             :         { "Marker", GF_FALSE},
     158             :         { "Mask", GF_FALSE},
     159             :         { "OpacityAttribute", GF_TRUE},
     160             :         { "PaintAttribute", GF_TRUE},
     161             :         { "Pattern", GF_FALSE},
     162             :         { "Script", GF_TRUE},
     163             :         { "Scripting", GF_TRUE},
     164             :         { "Shape", GF_TRUE},
     165             :         { "View", GF_FALSE},  /*no support for <view> element, the rest is OK ...*/
     166             :         { "ViewportAttribute", GF_TRUE},
     167             :         { "Structure", GF_TRUE},
     168             :         { "Style", GF_FALSE},
     169             :         { "Text", GF_TRUE},
     170             :         { "View", GF_TRUE},
     171             :         { "XlinkAttribute", GF_TRUE},
     172             : 
     173             :         { "SVG", GF_TRUE},
     174             :         { "SVG-animation", GF_TRUE},
     175             :         { "SVG-dynamic", GF_TRUE},
     176             :         { "SVG-static", GF_TRUE},
     177             :         /*we don't support SVG DOM, only uDOM*/
     178             :         { "SVGDOM", GF_FALSE},
     179             :         { "SVGDOM-animation", GF_FALSE},
     180             :         { "SVGDOM-dynamic", GF_FALSE},
     181             :         { "SVGDOM-static", GF_FALSE},
     182             : };
     183             : static const struct svg_12_feature {
     184             :         const char *name;
     185             :         Bool supported;
     186             : } svg12_features[] =
     187             : {
     188             :         { "CoreAttribute", GF_TRUE},
     189             :         { "NavigationAttribute", GF_TRUE},
     190             :         { "Structure", GF_TRUE},
     191             :         { "ConditionalProcessing", GF_TRUE},
     192             :         { "ConditionalProcessingAttribute", GF_TRUE},
     193             :         { "Image", GF_TRUE},
     194             :         { "Prefetch", GF_TRUE},
     195             :         { "Discard", GF_TRUE},
     196             :         { "Shape", GF_TRUE},
     197             :         { "Text", GF_TRUE},
     198             :         { "PaintAttribute", GF_TRUE},
     199             :         { "OpacityAttribute", GF_TRUE},
     200             :         { "GraphicsAttribute", GF_TRUE},
     201             :         { "Gradient", GF_TRUE},
     202             :         { "SolidColor", GF_TRUE},
     203             :         { "Hyperlinking", GF_TRUE},
     204             :         { "XlinkAttribute", GF_TRUE},
     205             :         { "ExternalResourcesRequired", GF_TRUE},
     206             :         { "Scripting", GF_TRUE},
     207             :         { "Handler", GF_TRUE},
     208             :         { "Listener", GF_TRUE},
     209             :         { "TimedAnimation", GF_TRUE},
     210             :         { "Animation", GF_TRUE},
     211             :         { "Audio", GF_TRUE},
     212             :         { "Video", GF_TRUE},
     213             :         { "Font", GF_TRUE},
     214             :         { "Extensibility", GF_TRUE},
     215             :         { "MediaAttribute", GF_TRUE},
     216             :         { "TextFlow", GF_TRUE},
     217             :         { "TransformedVideo", GF_TRUE},
     218             :         { "ComposedVideo", GF_TRUE},
     219             :         { "EditableTextAttribute", GF_TRUE},
     220             : 
     221             :         { "SVG-static", GF_TRUE},
     222             :         { "SVG-static-DOM", GF_TRUE},
     223             :         { "SVG-animated", GF_TRUE},
     224             :         { "SVG-all", GF_TRUE},
     225             :         { "SVG-interactive", GF_TRUE},
     226             : };
     227             : 
     228             : 
     229         960 : Bool compositor_svg_evaluate_conditional(GF_Compositor *compositor, SVGAllAttributes *atts)
     230             : {
     231             :         u32 i, count;
     232             :         Bool found;
     233             :         s32 lang_idx;
     234             : 
     235             :         /*process required features*/
     236         960 :         count = atts->requiredFeatures ? gf_list_count(*atts->requiredFeatures) : 0;
     237        1014 :         for (i=0; i<count; i++) {
     238             :                 char *feat = NULL;
     239         207 :                 XMLRI *iri = (XMLRI*)gf_list_get(*atts->requiredFeatures, i);
     240         207 :                 if (!iri->string) continue;
     241             : 
     242         207 :                 if (!strnicmp(iri->string, "org.w3c.svg", 11)) {
     243           0 :                         feat = iri->string+12;
     244           0 :                         if (feat) {
     245           0 :                                 if (!stricmp(feat, "animation")) {}
     246           0 :                                 else if (!stricmp(feat, "dynamic")) {}
     247             :                                 /*no support for filters, clipping & co - SVG 1.0 featureStrings are badly designed*/
     248             :                                 else return GF_FALSE;
     249             :                         }
     250             :                 }
     251         207 :                 else if (!strnicmp(iri->string, "http://www.w3.org/TR/SVG11/feature", 34)) {
     252           0 :                         feat = iri->string+35;
     253           0 :                         if (feat) {
     254             :                                 u32 j, nbf;
     255             :                                 found = GF_FALSE;
     256             :                                 nbf  = sizeof(svg11_features) / sizeof(struct svg_11_feature);
     257           0 :                                 for (j=0; j<nbf; j++) {
     258           0 :                                         if (!strcmp(svg11_features[j].name, feat)) {
     259             :                                                 found = GF_TRUE;
     260           0 :                                                 if (!svg11_features[j].supported) return GF_FALSE;
     261             :                                                 break;
     262             :                                         }
     263             :                                 }
     264             :                                 if (!found) return GF_FALSE;
     265             :                         }
     266             :                 }
     267         207 :                 else if (!strnicmp(iri->string, "http://www.w3.org/Graphics/SVG/feature/1.2/", 43)) {
     268          55 :                         feat = iri->string+44;
     269          55 :                         if (feat) {
     270             :                                 u32 j, nbf;
     271             :                                 found = GF_FALSE;
     272             :                                 nbf  = sizeof(svg12_features) / sizeof(struct svg_12_feature);
     273         676 :                                 for (j=0; j<nbf; j++) {
     274         730 :                                         if (!strcmp(svg12_features[j].name, feat)) {
     275             :                                                 found = GF_TRUE;
     276          54 :                                                 if (!svg12_features[j].supported) return GF_FALSE;
     277             :                                                 break;
     278             :                                         }
     279             :                                 }
     280             :                                 if (!found) return GF_FALSE;
     281             :                         }
     282             :                 }
     283             :                 /*unrecognized feature*/
     284             :                 else {
     285             :                         return GF_FALSE;
     286             :                 }
     287             :         }
     288             : 
     289             :         /*process required extensions*/
     290         807 :         count = atts->requiredExtensions ? gf_list_count(*atts->requiredExtensions) : 0;
     291         150 :         if (count) return GF_FALSE;
     292             : 
     293             :         /*process system language*/
     294         657 :         count = atts->systemLanguage ? gf_list_count(*atts->systemLanguage) : 0;
     295         301 :         if (count) {
     296             :                 found = GF_FALSE;
     297         301 :                 const char *lang = gf_opts_get_key("core", "lang");
     298         301 :                 lang_idx = lang ? gf_lang_find(lang) : -1;
     299             :         } else {
     300             :                 lang_idx = -1;
     301             :                 found = GF_TRUE;
     302             :         }
     303             : 
     304         958 :         for (i=0; i<count; i++) {
     305         301 :                 char *lang = (char*)gf_list_get(*atts->systemLanguage, i);
     306         301 :                 s32 pref_lang_idx = lang ? gf_lang_find(lang) : -1;
     307         301 :                 if (pref_lang_idx==lang_idx) {
     308             :                         found = GF_TRUE;
     309             :                         break;
     310             :                 }
     311             :         }
     312         657 :         if (!found) return GF_FALSE;
     313             : 
     314             :         /*process required formats*/
     315         356 :         count = atts->requiredFormats ? gf_list_count(*atts->requiredFormats) : 0;
     316         150 :         if (count) {
     317         150 :                 for (i=0; i<count; i++) {
     318             :                         Bool mime_ok;
     319         150 :                         char *mime = (char*)gf_list_get(*atts->requiredFormats, i);
     320         150 :                         char *sep = strchr(mime, ';');
     321         150 :                         if (sep) sep[0] = 0;
     322         150 :                         mime_ok = gf_filter_is_supported_mime(compositor->filter, mime);
     323         150 :                         if (sep) sep[0] = ';';
     324         150 :                         if (!mime_ok) return GF_FALSE;
     325             :                 }
     326             :         }
     327             : 
     328             :         /*process required fonts*/
     329         356 :         count = atts->requiredFonts ? gf_list_count(*atts->requiredFonts) : 0;
     330         150 :         if (count) {
     331           0 :                 for (i=0; i<count; i++) {
     332         150 :                         char *font = (char*)gf_list_get(*atts->requiredFonts, i);
     333         150 :                         if (gf_font_manager_set_font_ex(compositor->font_manager, &font, 1, 0, GF_TRUE)==NULL)
     334         150 :                                 return GF_FALSE;
     335             :                 }
     336             :         }
     337             : 
     338             :         /*OK, we can render this one*/
     339             :         return GF_TRUE;
     340             : }
     341             : 
     342       41113 : Bool compositor_svg_traverse_base(GF_Node *node, SVGAllAttributes *atts, GF_TraverseState *tr_state,
     343             :                                   SVGPropertiesPointers *backup_props, u32 *backup_flags)
     344             : {
     345             :         u32 inherited_flags_mask, flags;
     346             : 
     347       41113 :         if (atts->requiredFeatures || atts->requiredExtensions || atts->systemLanguage
     348       40325 :                 || atts->requiredFonts || atts->requiredFormats) {
     349         938 :                 if (!compositor_svg_evaluate_conditional(tr_state->visual->compositor, atts))
     350             :                         return GF_FALSE;
     351             :         }
     352             : 
     353       40361 :         memcpy(backup_props, tr_state->svg_props, sizeof(SVGPropertiesPointers));
     354       40361 :         *backup_flags = tr_state->svg_flags;
     355             : 
     356             : #if 0
     357             :         // applying inheritance and determining which group of properties are being inherited
     358             :         inherited_flags_mask = gf_svg_apply_inheritance(atts, tr_state->svg_props);
     359             :         gf_svg_apply_animations(node, tr_state->svg_props); // including again inheritance if values are 'inherit'
     360             : #else
     361             :         /* animation (including possibly inheritance) then full inheritance */
     362       40361 :         gf_svg_apply_animations(node, tr_state->svg_props);
     363       40361 :         inherited_flags_mask = gf_svg_apply_inheritance(atts, tr_state->svg_props);
     364             : //      gf_svg_apply_inheritance_no_inheritance(atts, tr_state->svg_props);
     365             : //      inherited_flags_mask = 0xFFFFFFFF;
     366             : #endif
     367       40361 :         tr_state->svg_flags &= inherited_flags_mask;
     368       40361 :         flags = gf_node_dirty_get(node);
     369       40361 :         tr_state->svg_flags |= flags;
     370             : 
     371       40361 :         return GF_TRUE;
     372             : }
     373             : #endif
     374             : 
     375             : 

Generated by: LCOV version 1.13