LCOV - code coverage report
Current view: top level - compositor - svg_font.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 133 304 43.8 %
Date: 2021-04-29 23:48:07 Functions: 7 13 53.8 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2007-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 <gpac/utf.h>
      27             : 
      28             : #ifndef GPAC_DISABLE_SVG
      29             : 
      30             : #include "visual_manager.h"
      31             : #include "nodes_stacks.h"
      32             : 
      33             : typedef struct
      34             : {
      35             :         u16 *unicode;
      36             :         u16 uni_len;
      37             : 
      38             :         GF_Glyph glyph;
      39             :         GF_Font *font;
      40             : } SVG_GlyphStack;
      41             : 
      42             : 
      43             : /*translate string to glyph sequence*/
      44           2 : static GF_Err svg_font_get_glyphs(void *udta, const char *utf_string, u32 *glyph_buffer, u32 *io_glyph_buffer_size, const char *lang, Bool *is_rtl)
      45             : {
      46             :         u32 prev_c;
      47             :         size_t len;
      48             :         u32 i, gl_idx;
      49             :         u16 *utf_res;
      50             :         GF_Node *node = (GF_Node *)udta;
      51             :         GF_ChildNodeItem *child;
      52           2 :         char *utf8 = (char*) utf_string;
      53             : 
      54             :         /*FIXME - use glyphs unicode attributes for glyph substitution*/
      55           2 :         len = utf_string ? (u32) strlen(utf_string) : 0;
      56           2 :         if (!len) {
      57           0 :                 *io_glyph_buffer_size = 0;
      58           0 :                 return GF_OK;
      59             :         }
      60             : 
      61           2 :         if (*io_glyph_buffer_size < len+1) {
      62           0 :                 *io_glyph_buffer_size = (u32) len+1;
      63           0 :                 return GF_BUFFER_TOO_SMALL;
      64             :         }
      65             : 
      66           2 :         len = gf_utf8_mbstowcs((u16*) glyph_buffer, *io_glyph_buffer_size, (const char**)&utf8);
      67           2 :         if (len == (size_t) -1) return GF_IO_ERR;
      68             :         /*should not happen*/
      69           2 :         if (utf8) return GF_IO_ERR;
      70             : 
      71             :         /*perform bidi relayout*/
      72             :         utf_res = (u16 *) glyph_buffer;
      73           2 :         *is_rtl = gf_utf8_reorder_bidi(utf_res, (u32) len);
      74             : 
      75             :         /*move 16bit buffer to 32bit*/
      76          14 :         for (i=(u32)len; i>0; i--) {
      77          10 :                 glyph_buffer[i-1] = utf_res[i-1];
      78             :         }
      79             : 
      80             :         gl_idx = 0;
      81             :         prev_c = 0;
      82          10 :         for (i=0; i<len; i++) {
      83             :                 SVG_GlyphStack *missing_glyph = NULL;
      84             :                 SVG_GlyphStack *st = NULL;
      85          10 :                 child = ((GF_ParentNode *) node)->children;
      86          60 :                 while (child) {
      87          50 :                         u32 tag = gf_node_get_tag(child->node);
      88          50 :                         if (tag==TAG_SVG_missing_glyph) {
      89          10 :                                 missing_glyph = gf_node_get_private(child->node);
      90          40 :                         } else if (tag ==TAG_SVG_glyph) {
      91             :                                 Bool glyph_ok = 0;
      92             :                                 SVGAllAttributes atts;
      93             : 
      94          30 :                                 st = gf_node_get_private(child->node);
      95          30 :                                 if (!st) {
      96           0 :                                         child = child->next;
      97           0 :                                         continue;
      98             :                                 }
      99             : 
     100          30 :                                 if (st->glyph.utf_name==glyph_buffer[i]) {
     101             :                                         u32 j, count;
     102          10 :                                         gf_svg_flatten_attributes((SVG_Element*)child->node, &atts);
     103          10 :                                         if (!lang) {
     104             :                                                 glyph_ok = 1;
     105             :                                         } else {
     106           0 :                                                 if (!atts.lang) {
     107             :                                                         glyph_ok = 1;
     108             :                                                 } else {
     109           0 :                                                         count = gf_list_count(*atts.lang);
     110           0 :                                                         for (j=0; j<count; j++) {
     111           0 :                                                                 char *name = gf_list_get(*atts.lang, j);
     112           0 :                                                                 if (!stricmp(name, lang) || strstr(lang, name)) {
     113             :                                                                         glyph_ok = 1;
     114             :                                                                         break;
     115             :                                                                 }
     116             :                                                         }
     117             :                                                 }
     118             :                                         }
     119          10 :                                         if (atts.arabic_form) {
     120           0 :                                                 Bool first = (!prev_c || (prev_c==' ')) ? 1 : 0;
     121           0 :                                                 Bool last = ((i+1==len) || (glyph_buffer[i+1]==' ') ) ? 1 : 0;
     122           0 :                                                 if (!strcmp(*atts.arabic_form, "isolated")) {
     123           0 :                                                         if (!first || !last) glyph_ok = 0;
     124             :                                                 }
     125           0 :                                                 if (!strcmp(*atts.arabic_form, "initial")) {
     126           0 :                                                         if (!first) glyph_ok = 0;
     127             :                                                 }
     128           0 :                                                 if (!strcmp(*atts.arabic_form, "medial")) {
     129           0 :                                                         if (first || last) glyph_ok = 0;
     130             :                                                 }
     131           0 :                                                 if (!strcmp(*atts.arabic_form, "terminal")) {
     132           0 :                                                         if (!last) glyph_ok = 0;
     133             :                                                 }
     134             :                                         }
     135          10 :                                         if (glyph_ok) break;
     136             :                                 }
     137             :                                 /*perform glyph substitution*/
     138          20 :                                 else if (st->uni_len>1) {
     139             :                                         u32 j;
     140           0 :                                         for (j=0; j<st->uni_len; j++) {
     141           0 :                                                 if (i+j>=len) break;
     142           0 :                                                 if (glyph_buffer[i+j] != st->unicode[j]) break;
     143             :                                         }
     144           0 :                                         if (j==st->uni_len)
     145             :                                                 break;
     146             :                                 }
     147             :                                 st = NULL;
     148             :                         }
     149          40 :                         child = child->next;
     150             :                 }
     151          10 :                 prev_c = glyph_buffer[i];
     152             : 
     153          10 :                 if (!st)
     154             :                         st = missing_glyph;
     155          10 :                 glyph_buffer[gl_idx] = st ? st->glyph.ID : 0;
     156          10 :                 if (st && st->uni_len>1) i++;
     157             : 
     158          10 :                 gl_idx++;
     159             :         }
     160           2 :         *io_glyph_buffer_size = /* len = */ gl_idx;
     161             : 
     162           2 :         return GF_OK;
     163             : }
     164             : 
     165             : /*loads glyph by name - returns NULL if glyph cannot be found*/
     166           0 : static GF_Glyph *svg_font_load_glyph(void *udta, u32 glyph_name)
     167             : {
     168           0 :         GF_ChildNodeItem *child = ((GF_ParentNode *) udta)->children;
     169             : 
     170           0 :         while (child) {
     171           0 :                 if (gf_node_get_tag(child->node)==TAG_SVG_glyph) {
     172           0 :                         SVG_GlyphStack *st = gf_node_get_private(child->node);
     173           0 :                         if (st->glyph.ID==glyph_name) {
     174           0 :                                 return &st->glyph;
     175             :                         }
     176             :                 }
     177           0 :                 child = child->next;
     178             :         }
     179             : 
     180             :         return NULL;
     181             : }
     182             : 
     183           1 : static void svg_traverse_font(GF_Node *node, void *rs, Bool is_destroy)
     184             : {
     185           1 :         if (is_destroy) {
     186           1 :                 GF_Font *font = gf_node_get_private(node);
     187           1 :                 if (font) {
     188           1 :                         gf_font_manager_unregister_font(font->ft_mgr, font);
     189           1 :                         if (font->name) gf_free(font->name);
     190           1 :                         gf_free(font);
     191             :                 }
     192             :         }
     193           1 : }
     194             : 
     195           1 : static void svg_font_on_load(GF_Node *handler, GF_DOM_Event *event, GF_Node *observer)
     196             : {
     197             :         GF_Font *font;
     198             :         assert(event->currentTarget->ptr_type==GF_DOM_EVENT_TARGET_NODE);
     199             :         assert(gf_node_get_tag((GF_Node*)event->currentTarget->ptr)==TAG_SVG_font);
     200           1 :         font = gf_node_get_private((GF_Node*)event->currentTarget->ptr);
     201           1 :         font->not_loaded = 0;
     202             : 
     203             :         /*brute-force signaling that all fonts have changed and texts must be recomputed*/
     204           1 :         font->compositor->reset_fonts = 1;
     205           1 :         gf_sc_next_frame_state(font->compositor, GF_SC_DRAW_FRAME);
     206           1 :         font->compositor->fonts_pending--;
     207           1 : }
     208             : 
     209           2 : void compositor_init_svg_font(GF_Compositor *compositor, GF_Node *node)
     210             : {
     211             :         SVG_handlerElement *handler;
     212             :         GF_Err e;
     213             :         SVGAllAttributes atts;
     214             :         GF_Font *font;
     215           2 :         GF_Node *node_font = gf_node_get_parent(node, 0);
     216           3 :         if (!node_font) return;
     217             : 
     218           2 :         if (gf_node_get_tag(node_font)!=TAG_SVG_font) return;
     219             : 
     220           1 :         gf_svg_flatten_attributes((SVG_Element*)node, &atts);
     221           1 :         if (!atts.font_family) return;
     222             : 
     223             :         /*register font to font manager*/
     224           1 :         GF_SAFEALLOC(font, GF_Font);
     225           1 :         if (!font) {
     226           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate svg font\n"));
     227             :                 return;
     228             :         }
     229           1 :         e = gf_font_manager_register_font(compositor->font_manager, font);
     230           1 :         if (e) {
     231           0 :                 gf_free(font);
     232           0 :                 return;
     233             :         }
     234           1 :         font->ft_mgr = compositor->font_manager;
     235           1 :         font->compositor = compositor;
     236             : 
     237           1 :         font->get_glyphs = svg_font_get_glyphs;
     238           1 :         font->load_glyph = svg_font_load_glyph;
     239           1 :         font->udta = node_font;
     240           1 :         gf_node_set_private(node_font, font);
     241           1 :         gf_node_set_callback_function(node_font, svg_traverse_font);
     242           1 :         font->name = gf_strdup(atts.font_family->value);
     243             : 
     244           1 :         font->em_size = atts.units_per_em ? FIX2INT( gf_ceil(atts.units_per_em->value) ) : 1000;
     245             :         /*Inconsistency between SVG 1.2 and 1.1
     246             :                 when not specify, ascent and descent are computed based on font.vert-origin-y, WHICH DOES NOT EXIST
     247             :         IN Tiny 1.2 !!! We assume it to be 0.
     248             :         */
     249           1 :         font->ascent = atts.ascent ? FIX2INT( gf_ceil(atts.ascent->value) ) : 0;
     250           1 :         if (!font->ascent) font->ascent = font->em_size;
     251           1 :         font->descent = atts.descent ? FIX2INT( gf_ceil(atts.descent->value) ) : 0;
     252           1 :         font->baseline = atts.alphabetic ? FIX2INT( gf_ceil(atts.alphabetic->value) ) : 0;
     253           1 :         font->line_spacing = font->em_size;
     254           1 :         font->styles = 0;
     255           1 :         if (atts.font_style) {
     256           0 :                 switch (*atts.font_style) {
     257           0 :                 case SVG_FONTSTYLE_ITALIC:
     258           0 :                         font->styles |= GF_FONT_ITALIC;
     259           0 :                         break;
     260           0 :                 case SVG_FONTSTYLE_OBLIQUE:
     261           0 :                         font->styles |= GF_FONT_OBLIQUE;
     262           0 :                         break;
     263             :                 }
     264             :         }
     265           1 :         if (atts.font_variant && (*atts.font_variant ==SVG_FONTVARIANT_SMALLCAPS))
     266           0 :                 font->styles |= GF_FONT_SMALLCAPS;
     267             : 
     268           1 :         if (atts.font_weight) {
     269           0 :                 switch(*atts.font_weight) {
     270           0 :                 case SVG_FONTWEIGHT_100:
     271           0 :                         font->styles |= GF_FONT_WEIGHT_100;
     272           0 :                         break;
     273           0 :                 case SVG_FONTWEIGHT_LIGHTER:
     274           0 :                         font->styles |= GF_FONT_WEIGHT_LIGHTER;
     275           0 :                         break;
     276           0 :                 case SVG_FONTWEIGHT_200:
     277           0 :                         font->styles |= GF_FONT_WEIGHT_200;
     278           0 :                         break;
     279           0 :                 case SVG_FONTWEIGHT_300:
     280           0 :                         font->styles |= GF_FONT_WEIGHT_300;
     281           0 :                         break;
     282           0 :                 case SVG_FONTWEIGHT_400:
     283           0 :                         font->styles |= GF_FONT_WEIGHT_400;
     284           0 :                         break;
     285           0 :                 case SVG_FONTWEIGHT_NORMAL:
     286           0 :                         font->styles |= GF_FONT_WEIGHT_NORMAL;
     287           0 :                         break;
     288           0 :                 case SVG_FONTWEIGHT_500:
     289           0 :                         font->styles |= GF_FONT_WEIGHT_500;
     290           0 :                         break;
     291           0 :                 case SVG_FONTWEIGHT_600:
     292           0 :                         font->styles |= GF_FONT_WEIGHT_600;
     293           0 :                         break;
     294           0 :                 case SVG_FONTWEIGHT_700:
     295           0 :                         font->styles |= GF_FONT_WEIGHT_700;
     296           0 :                         break;
     297           0 :                 case SVG_FONTWEIGHT_BOLD:
     298           0 :                         font->styles |= GF_FONT_WEIGHT_BOLD;
     299           0 :                         break;
     300           0 :                 case SVG_FONTWEIGHT_800:
     301           0 :                         font->styles |= GF_FONT_WEIGHT_800;
     302           0 :                         break;
     303           0 :                 case SVG_FONTWEIGHT_900:
     304           0 :                         font->styles |= GF_FONT_WEIGHT_900;
     305           0 :                         break;
     306           0 :                 case SVG_FONTWEIGHT_BOLDER:
     307           0 :                         font->styles |= GF_FONT_WEIGHT_BOLDER;
     308           0 :                         break;
     309             :                 }
     310             :         }
     311             : 
     312           1 :         gf_svg_flatten_attributes((SVG_Element*)node_font, &atts);
     313           1 :         font->max_advance_h = atts.horiz_adv_x ? FIX2INT( gf_ceil(atts.horiz_adv_x->value) ) : 0;
     314             : 
     315           1 :         font->not_loaded = 1;
     316             : 
     317             :         /*wait for onLoad event before activating the font, otherwise we may not have all the glyphs*/
     318           1 :         handler = gf_dom_listener_build(node_font, GF_EVENT_LOAD, 0);
     319           1 :         handler->handle_event = svg_font_on_load;
     320             : }
     321             : 
     322             : 
     323           6 : static void svg_traverse_glyph(GF_Node *node, void *rs, Bool is_destroy)
     324             : {
     325           6 :         if (is_destroy) {
     326             :                 GF_Font *font;
     327             :                 GF_Glyph *prev_glyph, *a_glyph;
     328           6 :                 SVG_GlyphStack *st = gf_node_get_private(node);
     329           6 :                 if (st->unicode) gf_free(st->unicode);
     330             : 
     331           6 :                 font = st->font;
     332             :                 prev_glyph = NULL;
     333           6 :                 a_glyph = font->glyph;
     334          12 :                 while (a_glyph) {
     335           6 :                         if (a_glyph == &st->glyph) break;
     336             :                         prev_glyph = a_glyph;
     337           0 :                         a_glyph = a_glyph->next;
     338             :                 }
     339           6 :                 if (prev_glyph) {
     340           0 :                         prev_glyph->next = st->glyph.next;
     341             :                 } else {
     342           6 :                         font->glyph = st->glyph.next;
     343             :                 }
     344           6 :                 gf_free(st);
     345             :         }
     346           6 : }
     347             : 
     348           8 : void compositor_init_svg_glyph(GF_Compositor *compositor, GF_Node *node)
     349             : {
     350             :         u16 utf_name[20];
     351             :         u8 *utf8;
     352             :         size_t len;
     353             :         GF_Rect rc;
     354             :         GF_Glyph *glyph;
     355             :         GF_Font *font;
     356             :         SVG_GlyphStack *st;
     357             :         SVGAllAttributes atts;
     358           8 :         GF_Node *node_font = gf_node_get_parent(node, 0);
     359             : 
     360             :         /*locate the font node*/
     361           8 :         if (node_font) node_font = gf_node_get_parent(node, 0);
     362          10 :         if (!node_font || (gf_node_get_tag(node_font)!=TAG_SVG_font) ) return;
     363           6 :         font = gf_node_get_private(node_font);
     364           6 :         if (!font) return;
     365             : 
     366           6 :         gf_svg_flatten_attributes((SVG_Element*)node, &atts);
     367             : 
     368           6 :         if (gf_node_get_tag(node)==TAG_SVG_missing_glyph) {
     369           1 :                 GF_SAFEALLOC(st, SVG_GlyphStack);
     370           1 :                 if (!st) return;
     371             :                 goto reg_common;
     372             :         }
     373             :         /*we must have unicode specified*/
     374           5 :         if (!atts.unicode) return;
     375             : 
     376           5 :         GF_SAFEALLOC(st, SVG_GlyphStack);
     377           5 :         if (!st) return;
     378           5 :         utf8 = (u8 *) *atts.unicode;
     379           5 :         len = gf_utf8_mbstowcs(utf_name, 200, (const char **) &utf8);
     380             :         /*this is a single glyph*/
     381           5 :         if (len==1) {
     382           5 :                 st->glyph.utf_name = utf_name[0];
     383           5 :                 st->uni_len = 1;
     384             :         } else {
     385           0 :                 st->glyph.utf_name = (u32) (PTR_TO_U_CAST st);
     386           0 :                 st->unicode = gf_malloc(sizeof(u16)*len);
     387           0 :                 st->uni_len = (u16) len;
     388             :                 memcpy(st->unicode, utf_name, sizeof(u16)*len);
     389             :         }
     390             : 
     391           6 : reg_common:
     392           6 :         st->glyph.ID = (u32)(PTR_TO_U_CAST st);
     393           6 :         st->font = font;
     394           6 :         st->glyph.horiz_advance = font->max_advance_h;
     395           6 :         if (atts.horiz_adv_x) st->glyph.horiz_advance = FIX2INT( gf_ceil(atts.horiz_adv_x->value) );
     396           6 :         if (atts.d) {
     397           6 :                 st->glyph.path = atts.d;
     398           6 :                 gf_path_get_bounds(atts.d, &rc);
     399           6 :                 st->glyph.width = FIX2INT( gf_ceil(rc.width) );
     400           6 :                 st->glyph.height = FIX2INT( gf_ceil(rc.height) );
     401             :         }
     402           6 :         st->glyph.vert_advance = st->glyph.height;
     403           6 :         if (!st->glyph.vert_advance)
     404           0 :                 st->glyph.vert_advance = font->max_advance_v;
     405             : 
     406             :         /*register glyph*/
     407           6 :         if (!font->glyph) {
     408           1 :                 font->glyph = &st->glyph;
     409             :         } else {
     410             :                 glyph = font->glyph;
     411          15 :                 while (glyph->next) glyph = glyph->next;
     412           5 :                 glyph->next = &st->glyph;
     413             :         }
     414             : 
     415           6 :         gf_node_set_private(node, st);
     416           6 :         gf_node_set_callback_function(node, svg_traverse_glyph);
     417             : }
     418             : 
     419             : 
     420             : typedef struct
     421             : {
     422             :         GF_Font *font;
     423             :         GF_Font *alias;
     424             :         GF_Compositor *compositor;
     425             :         GF_MediaObject *mo;
     426             : } FontURIStack;
     427             : 
     428           0 : static Bool svg_font_uri_check(GF_Node *node, FontURIStack *st)
     429             : {
     430             :         GF_Font *font;
     431             :         GF_Node *font_elt;
     432             :         SVGAllAttributes atts;
     433           0 :         gf_svg_flatten_attributes((SVG_Element*)node, &atts);
     434           0 :         if (!atts.xlink_href) return 0;
     435             : 
     436           0 :         if (atts.xlink_href->type == XMLRI_ELEMENTID) {
     437           0 :                 if (!atts.xlink_href->target) atts.xlink_href->target = gf_sg_find_node_by_name(gf_node_get_graph(node), atts.xlink_href->string+1);
     438             :         } else {
     439             :                 GF_SceneGraph *ext_sg;
     440           0 :                 char *font_name = strchr(atts.xlink_href->string, '#');
     441           0 :                 if (!font_name) return 0;
     442           0 :                 if (!st->mo) {
     443           0 :                         st->mo = gf_mo_load_xlink_resource(node, 0, 0, -1);
     444           0 :                         if (!st->mo) {
     445           0 :                                 st->compositor->fonts_pending--;
     446           0 :                                 return 0;
     447             :                         }
     448             :                 }
     449           0 :                 ext_sg = gf_mo_get_scenegraph(st->mo);
     450           0 :                 if (!ext_sg) {
     451           0 :                         st->compositor->fonts_pending--;
     452           0 :                         return 0;
     453             :                 }
     454           0 :                 atts.xlink_href->target = gf_sg_find_node_by_name(ext_sg, font_name+1);
     455           0 :                 if (!atts.xlink_href->target) {
     456           0 :                         st->compositor->fonts_pending--;
     457           0 :                         return 0;
     458             :                 }
     459             :         }
     460           0 :         font_elt = atts.xlink_href->target;
     461           0 :         if (gf_node_get_tag(font_elt) != TAG_SVG_font) {
     462           0 :                 st->compositor->fonts_pending--;
     463           0 :                 return 0;
     464             :         }
     465           0 :         font = gf_node_get_private(font_elt);
     466           0 :         if (!font) {
     467           0 :                 st->compositor->fonts_pending--;
     468           0 :                 return 0;
     469             :         }
     470             : 
     471           0 :         st->alias = font;
     472             : 
     473           0 :         gf_mo_is_done(st->mo);
     474           0 :         font->not_loaded = 0;
     475           0 :         return 1;
     476             : }
     477             : 
     478           0 : GF_Font *svg_font_uri_get_alias(void *udta)
     479             : {
     480             :         GF_Node *node = (GF_Node *)udta;
     481           0 :         FontURIStack *st = gf_node_get_private(node);
     482           0 :         if (!st->alias && !svg_font_uri_check(node, st)) {
     483             :                 return NULL;
     484             :         }
     485           0 :         return st->alias;
     486             : }
     487             : 
     488           0 : static GF_Err svg_font_uri_get_glyphs(void *udta, const char *utf_string, u32 *glyph_buffer, u32 *io_glyph_buffer_size, const char *lang, Bool *is_rtl)
     489             : {
     490           0 :         return GF_URL_ERROR;
     491             : }
     492             : 
     493           0 : static GF_Glyph *svg_font_uri_load_glyph(void *udta, u32 glyph_name)
     494             : {
     495           0 :         return NULL;
     496             : }
     497             : 
     498           0 : static void svg_traverse_font_face_uri(GF_Node *node, void *rs, Bool is_destroy)
     499             : {
     500           0 :         if (is_destroy) {
     501           0 :                 FontURIStack *st = gf_node_get_private(node);
     502           0 :                 if (st) {
     503           0 :                         gf_font_manager_unregister_font(st->font->ft_mgr, st->font);
     504           0 :                         if (st->font->name) gf_free(st->font->name);
     505           0 :                         gf_free(st->font);
     506           0 :                         if (st->mo) gf_mo_unload_xlink_resource(node, st->mo);
     507           0 :                         gf_free(st);
     508             :                 }
     509             :         }
     510           0 : }
     511             : 
     512           1 : void compositor_init_svg_font_face_uri(GF_Compositor *compositor, GF_Node *node)
     513             : {
     514             :         GF_Node *par;
     515             :         GF_Font *font;
     516             :         FontURIStack *stack;
     517             :         GF_Err e;
     518             :         SVGAllAttributes atts;
     519             : 
     520             :         /*check parent is a font-face-src*/
     521           1 :         par = gf_node_get_parent(node, 0);
     522           2 :         if (!par || (gf_node_get_tag(par)!=TAG_SVG_font_face_src)) return;
     523             :         /*check parent's parent is a font-face*/
     524           0 :         par = gf_node_get_parent(par, 0);
     525           0 :         if (!par || (gf_node_get_tag(par)!=TAG_SVG_font_face)) return;
     526             : 
     527             : 
     528           0 :         gf_svg_flatten_attributes((SVG_Element*)node, &atts);
     529           0 :         if (!atts.xlink_href) return;
     530             : 
     531             :         /*get font familly*/
     532           0 :         gf_svg_flatten_attributes((SVG_Element*)par, &atts);
     533           0 :         if (!atts.font_family) return;
     534             : 
     535             :         /*if font with the same name exists, don't load*/
     536           0 :         if (gf_compositor_svg_set_font(compositor->font_manager, atts.font_family->value, 0, 1) != NULL)
     537             :                 return;
     538             : 
     539             :         /*register font to font manager*/
     540           0 :         GF_SAFEALLOC(font, GF_Font);
     541           0 :         if (!font) {
     542           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate font for svg font face URI\n"));
     543             :                 return;
     544             :         }
     545             :         
     546           0 :         e = gf_font_manager_register_font(compositor->font_manager, font);
     547           0 :         if (e) {
     548           0 :                 gf_free(font);
     549           0 :                 return;
     550             :         }
     551           0 :         GF_SAFEALLOC(stack, FontURIStack);
     552           0 :         if (!stack) {
     553           0 :                 gf_free(font);
     554           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate svg font face URI stack\n"));
     555             :                 return;
     556             :         }
     557           0 :         stack->font = font;
     558           0 :         stack->compositor = compositor;
     559             : 
     560           0 :         font->ft_mgr = compositor->font_manager;
     561             : 
     562           0 :         font->get_glyphs = svg_font_uri_get_glyphs;
     563           0 :         font->load_glyph = svg_font_uri_load_glyph;
     564           0 :         font->get_alias = svg_font_uri_get_alias;
     565           0 :         font->udta = node;
     566           0 :         font->name = gf_strdup(atts.font_family->value);
     567           0 :         gf_node_set_private(node, stack);
     568           0 :         gf_node_set_callback_function(node, svg_traverse_font_face_uri);
     569             : 
     570           0 :         font->not_loaded = 1;
     571           0 :         compositor->fonts_pending++;
     572           0 :         svg_font_uri_check(node, stack);
     573             : }
     574             : 
     575             : 
     576             : #endif /*GPAC_DISABLE_SVG*/
     577             : 

Generated by: LCOV version 1.13