📄 svg_media.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean le Feuvre * Copyright (c) 2005-200X ENST * All rights reserved * * This file is part of GPAC / SVG Rendering sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "visualsurface2d.h"#ifndef GPAC_DISABLE_SVG#include "svg_stacks.h"#include <gpac/internal/scenegraph_dev.h>static void SVG_Draw_bitmap(RenderEffect2D *eff){ u8 alpha; Render2D *sr; Bool use_blit; DrawableContext *ctx = eff->ctx; sr = eff->surface->render; use_blit = 1; alpha = GF_COL_A(ctx->aspect.fill_color); /*this is not a native texture, use graphics*/ if (!ctx->h_texture->data || ctx->transform.m[1] || ctx->transform.m[3]) { use_blit = 0; } else { if (!eff->surface->SupportsFormat || !eff->surface->DrawBitmap ) use_blit = 0; /*format not supported directly, try with brush*/ else if (!eff->surface->SupportsFormat(eff->surface, ctx->h_texture->pixelformat) ) use_blit = 0; } /*no HW, fall back to the graphics driver*/ if (!use_blit) { VS2D_TexturePath(eff->surface, ctx->drawable->path, ctx); return; } /*direct rendering, render without clippers */ if (eff->surface->render->top_effect->trav_flags & TF_RENDER_DIRECT) { eff->surface->DrawBitmap(eff->surface, ctx->h_texture, &ctx->bi->clip, &ctx->bi->unclip, alpha, NULL, ctx->col_mat); } /*render bitmap for all dirty rects*/ else { u32 i; GF_IRect clip; for (i=0; i<eff->surface->to_redraw.count; i++) { /*there's an opaque region above, don't draw*/#ifdef TRACK_OPAQUE_REGIONS if (eff->surface->draw_node_index < eff->surface->to_redraw.opaque_node_index[i]) continue;#endif clip = ctx->bi->clip; gf_irect_intersect(&clip, &eff->surface->to_redraw.list[i]); if (clip.width && clip.height) { eff->surface->DrawBitmap(eff->surface, ctx->h_texture, &clip, &ctx->bi->unclip, alpha, NULL, ctx->col_mat); } } }}static void SVG_Build_Bitmap_Graph(SVG_image_stack *st){ GF_Rect rc, new_rc; Fixed x, y, width, height; u32 tag = gf_node_get_tag(st->graph->node); switch (tag) {#ifdef GPAC_ENABLE_SVG_SA case TAG_SVG_SA_image: { SVG_SA_imageElement *img = (SVG_SA_imageElement *)st->graph->node; x = img->x.value; y = img->y.value; width = img->width.value; height = img->height.value; } break; case TAG_SVG_SA_video: { SVG_SA_videoElement *video = (SVG_SA_videoElement *)st->graph->node; x = video->x.value; y = video->y.value; width = video->width.value; height = video->height.value; } break;#endif#ifdef GPAC_ENABLE_SVG_SANI case TAG_SVG_SANI_image: { SVG_SANI_imageElement *img = (SVG_SANI_imageElement *)st->graph->node; x = img->x.value; y = img->y.value; width = img->width.value; height = img->height.value; } break; case TAG_SVG_SANI_video: { SVG_SANI_videoElement *video = (SVG_SANI_videoElement *)st->graph->node; x = video->x.value; y = video->y.value; width = video->width.value; height = video->height.value; } break;#endif case TAG_SVG_image: case TAG_SVG_video: { SVG_Element *e = (SVG_Element *)st->graph->node; SVGAllAttributes atts; gf_svg_flatten_attributes(e, &atts); x = (atts.x ? atts.x->value : 0); y = (atts.y ? atts.y->value : 0); width = (atts.width ? atts.width->value : 0); height = (atts.height ? atts.height->value : 0); } break; default: return; } if (!width) width = INT2FIX(st->txh.width); if (!height) height = INT2FIX(st->txh.height); gf_path_get_bounds(st->graph->path, &rc); drawable_reset_path(st->graph); gf_path_add_rect_center(st->graph->path, x+width/2, y+height/2, width, height); gf_path_get_bounds(st->graph->path, &new_rc); if (!gf_rect_equal(rc, new_rc)) st->graph->flags |= DRAWABLE_HAS_CHANGED; gf_node_dirty_clear(st->graph->node, GF_SG_SVG_GEOMETRY_DIRTY);}#ifdef GPAC_ENABLE_SVG_SAstatic void svg_sa_render_bitmap(GF_Node *node, void *rs){ /*video stack is just an extension of image stack, type-casting is OK*/ SVG_image_stack *st = (SVG_image_stack*)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; SVGPropertiesPointers backup_props; u32 backup_flags; GF_Matrix2D backup_matrix; GF_Matrix2D *m; DrawableContext *ctx; if (eff->traversing_mode==TRAVERSE_DRAW) { SVG_Draw_bitmap(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { eff->is_over = 1; return; } svg_sa_render_base(node, eff, &backup_props, &backup_flags); if (gf_node_dirty_get(node)) { SVG_Build_Bitmap_Graph((SVG_image_stack*)gf_node_get_private(node)); /*if open and changed, stop and play*/ if (gf_term_check_iri_change(st->txh.compositor->term, &st->txurl, & ((SVG_SA_Element *)node)->xlink->href)) { const char *cache_dir = gf_cfg_get_key(st->txh.compositor->user->config, "General", "CacheDirectory"); gf_svg_store_embedded_data(& ((SVG_SA_Element *)node)->xlink->href, cache_dir, "embedded_"); if (gf_term_check_iri_change(st->txh.compositor->term, &st->txurl, & ((SVG_SA_Element *)node)->xlink->href)) { gf_term_set_mfurl_from_uri(st->txh.compositor->term, &(st->txurl), & ((SVG_SA_Element*)node)->xlink->href); if (st->txh.is_open) gf_sr_texture_stop(&st->txh); gf_sr_texture_play_from_to(&st->txh, &st->txurl, 0, -1, 0, 0); } } gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); } switch (gf_node_get_tag(node)) {#ifdef GPAC_ENABLE_SVG_SA case TAG_SVG_SA_image: m = &((SVG_SA_imageElement *)node)->transform.mat; break; case TAG_SVG_SA_video: m = &((SVG_SA_videoElement *)node)->transform.mat; break;#endif#ifdef GPAC_ENABLE_SVG_SANI case TAG_SVG_SANI_image: m = &((SVG_SA_imageElement *)node)->transform.mat; break; case TAG_SVG_SANI_video: m = &((SVG_SA_videoElement *)node)->transform.mat; break;#endif default: /*SVG FIXME*/ m = NULL; } /*FIXME: setup aspect ratio*/ if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) { svg_sa_apply_local_transformation(eff, node, &backup_matrix); if (!svg_is_display_off(eff->svg_props)) { gf_path_get_bounds(st->graph->path, &eff->bounds); } memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); svg_sa_restore_parent_transformation(eff, &backup_matrix); eff->svg_flags = backup_flags; return; } if (svg_is_display_off(eff->svg_props) || *(eff->svg_props->visibility) == SVG_VISIBILITY_HIDDEN) { memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); eff->svg_flags = backup_flags; return; } svg_sa_apply_local_transformation(eff, node, &backup_matrix); ctx = SVG_drawable_init_context(st->graph, eff); if (!ctx || !ctx->h_texture ) return; /*even if set this is not true*/ ctx->aspect.pen_props.width = 0; ctx->flags |= CTX_NO_ANTIALIAS; /*if rotation, transparent*/ ctx->flags &= ~CTX_IS_TRANSPARENT; if (ctx->transform.m[1] || ctx->transform.m[3]) { ctx->flags |= CTX_IS_TRANSPARENT; ctx->flags &= ~CTX_NO_ANTIALIAS; } else if (ctx->h_texture->transparent) ctx->flags |= CTX_IS_TRANSPARENT; else if (eff->svg_props->opacity && (eff->svg_props->opacity->type==SVG_NUMBER_VALUE) && (eff->svg_props->opacity->value!=FIX_ONE)) { ctx->flags = CTX_IS_TRANSPARENT; ctx->aspect.fill_color = GF_COL_ARGB(FIX2INT(0xFF * eff->svg_props->opacity->value), 0, 0, 0); } /*bounds are stored when building graph*/ drawable_finalize_render(ctx, eff, NULL); svg_sa_restore_parent_transformation(eff, &backup_matrix); memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); eff->svg_flags = backup_flags;}#endifstatic void svg_play_texture(SVG_image_stack *st, SVGAllAttributes *atts){ SVGAllAttributes all_atts; Bool lock_scene = 0; if (st->txh.is_open) gf_sr_texture_stop(&st->txh); if (!atts) { gf_svg_flatten_attributes((SVG_Element*)st->txh.owner, &all_atts); atts = &all_atts; } if (atts->syncBehavior) lock_scene = (*atts->syncBehavior == SMIL_SYNCBEHAVIOR_LOCKED) ? 1 : 0; gf_sr_texture_play_from_to(&st->txh, &st->txurl, atts->clipBegin ? (*atts->clipBegin) : 0.0, atts->clipEnd ? (*atts->clipEnd) : -1.0, 0, lock_scene);}static void svg_render_bitmap(GF_Node *node, void *rs){ /*video stack is just an extension of image stack, type-casting is OK*/ SVG_image_stack *st = (SVG_image_stack*)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; SVGPropertiesPointers backup_props; u32 backup_flags; GF_Matrix2D backup_matrix; DrawableContext *ctx; SVGAllAttributes all_atts; if (eff->traversing_mode==TRAVERSE_DRAW) { SVG_Draw_bitmap(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); svg_render_base(node, &all_atts, (RenderEffect2D *)rs, &backup_props, &backup_flags); if (gf_node_dirty_get(node)) { GF_FieldInfo href_info; SVG_Build_Bitmap_Graph((SVG_image_stack*)gf_node_get_private(node)); /*if open and changed, stop and play*/ if (gf_svg_get_attribute_by_tag(node, TAG_SVG_ATT_xlink_href, 0, 0, &href_info) == GF_OK) { if (gf_term_check_iri_change(st->txh.compositor->term, &st->txurl, href_info.far_ptr)) { const char *cache_dir = gf_cfg_get_key(st->txh.compositor->user->config, "General", "CacheDirectory"); gf_svg_store_embedded_data(href_info.far_ptr, cache_dir, "embedded_"); if (gf_term_check_iri_change(st->txh.compositor->term, &st->txurl, href_info.far_ptr) == GF_OK) { gf_term_set_mfurl_from_uri(st->txh.compositor->term, &(st->txurl), href_info.far_ptr); svg_play_texture(st, &all_atts); } } } gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); } /*FIXME: setup aspect ratio*/ if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) { svg_apply_local_transformation(eff, &all_atts, &backup_matrix); if (!svg_is_display_off(eff->svg_props)) { gf_path_get_bounds(st->graph->path, &eff->bounds); } svg_restore_parent_transformation(eff, &backup_matrix); memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); eff->svg_flags = backup_flags; return; } if (svg_is_display_off(eff->svg_props) || *(eff->svg_props->visibility) == SVG_VISIBILITY_HIDDEN) { memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); eff->svg_flags = backup_flags; return; } svg_apply_local_transformation(eff, &all_atts, &backup_matrix); ctx = SVG_drawable_init_context(st->graph, eff); if (!ctx || !ctx->h_texture ) return; /*even if set this is not true*/ ctx->aspect.pen_props.width = 0; ctx->flags |= CTX_NO_ANTIALIAS; /*if rotation, transparent*/ ctx->flags &= ~CTX_IS_TRANSPARENT; if (ctx->transform.m[1] || ctx->transform.m[3]) { ctx->flags |= CTX_IS_TRANSPARENT; ctx->flags &= ~CTX_NO_ANTIALIAS; } else if (ctx->h_texture->transparent) ctx->flags |= CTX_IS_TRANSPARENT; else if (eff->svg_props->opacity && (eff->svg_props->opacity->type==SVG_NUMBER_VALUE) && (eff->svg_props->opacity->value!=FIX_ONE)) { ctx->flags = CTX_IS_TRANSPARENT; ctx->aspect.fill_color = GF_COL_ARGB(FIX2INT(0xFF * eff->svg_props->opacity->value), 0, 0, 0); } /*bounds are stored when building graph*/ drawable_finalize_render(ctx, eff, NULL); svg_restore_parent_transformation(eff, &backup_matrix); memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); eff->svg_flags = backup_flags;}/*********************//* SVG image element *//*********************/static void SVG_Update_image(GF_TextureHandler *txh){ MFURL *txurl = &(((SVG_image_stack *)gf_node_get_private(txh->owner))->txurl); /*setup texture if needed*/ if (!txh->is_open && txurl->count) { gf_sr_texture_play_from_to(txh, txurl, 0, -1, 0, 0); } gf_sr_texture_update_frame(txh, 0); /*URL is present but not opened - redraw till fetch*/ if (txh->stream && !txh->hwtx) gf_sr_invalidate(txh->compositor, NULL);}static void SVG_Render_image(GF_Node *node, void *rs, Bool is_destroy){ if (is_destroy) { SVG_image_stack *st = (SVG_image_stack *)gf_node_get_private(node); gf_sr_texture_destroy(&st->txh); gf_sg_mfurl_del(st->txurl); drawable_del(st->graph); free(st); } else { switch (gf_node_get_tag(node)) {#ifdef GPAC_ENABLE_SVG_SA case TAG_SVG_SA_image: svg_sa_render_bitmap(node, rs); break;#endif#ifdef GPAC_ENABLE_SVG_SANI case TAG_SVG_SANI_image:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -