Bool osd_load_scene(GF_OSD *osd) { GF_Node *n; GF_List *nodes; const char *opt; GF_DOMHandler *hdl; /*BT/VRML from string*/ GF_List *gf_sm_load_bt_from_string(GF_SceneGraph *in_scene, const char *node_str, Bool force_wrl); /*create a new scene*/ osd->odm = gf_odm_new(); osd->odm->term = osd->term; osd->odm->subscene = gf_scene_new(NULL); osd->odm->subscene->root_od = osd->odm; gf_sg_set_scene_size_info(osd->odm->subscene->graph, 0, 0, 1); /*create a scene graph*/ nodes = gf_sm_load_bt_from_string(osd->odm->subscene->graph, osd_scene_graph, 0); n = gf_list_get(nodes, 0); gf_list_del(nodes); if (!n) return 0; gf_sg_set_root_node(osd->odm->subscene->graph, n); gf_sg_set_scene_size_info(osd->odm->subscene->graph, 0, 0, 1); hdl = gf_dom_listener_build(n, GF_EVENT_RESIZE, 0); hdl->handle_event = osd_on_resize; hdl->evt_listen_obj = osd; osd->visible = (M_Switch *)gf_sg_find_node_by_name(osd->odm->subscene->graph, "N1"); osd->transform = (M_Transform2D *)gf_sg_find_node_by_name(osd->odm->subscene->graph, "N2"); osd->ct2d = (M_CompositeTexture2D *)gf_sg_find_node_by_name(osd->odm->subscene->graph, "N3"); osd->text = (M_Text *)gf_sg_find_node_by_name(osd->odm->subscene->graph, "N4"); if (osd->text->string.vals[0]) { gf_free(osd->text->string.vals[0]); osd->text->string.vals[0] = NULL; } strcpy(osd->statBuffer, "Hello World !"); osd->text->string.vals[0] = osd->statBuffer; opt = gf_cfg_get_key(osd->term->user->config, "OSD", "Visible"); if (!opt || strcmp(opt, "yes")) osd->visible->whichChoice = -1; return 1; }
static void OnAnchor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info) { GF_Event evt; MFURL *url; AnchorStack *st = (AnchorStack *) gf_node_get_private(sh->owner); if ((ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) st->active = 1; else if (st->active && (ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT) ) { u32 i; if (gf_node_get_tag(sh->owner)==TAG_MPEG4_Anchor) { url = & ((M_Anchor *)sh->owner)->url; evt.navigate.param_count = ((M_Anchor *)sh->owner)->parameter.count; evt.navigate.parameters = (const char **) ((M_Anchor *)sh->owner)->parameter.vals; } else { url = & ((X_Anchor *)sh->owner)->url; evt.navigate.param_count = ((X_Anchor *)sh->owner)->parameter.count; evt.navigate.parameters = (const char **) ((X_Anchor *)sh->owner)->parameter.vals; } evt.type = GF_EVENT_NAVIGATE; i=0; while (i<url->count) { evt.navigate.to_url = url->vals[i].url; if (!evt.navigate.to_url) break; /*current scene navigation*/ if (evt.navigate.to_url[0] == '#') { GF_Node *bindable; evt.navigate.to_url++; bindable = gf_sg_find_node_by_name(gf_node_get_graph(sh->owner), (char *) evt.navigate.to_url); if (bindable) { Bindable_SetSetBind(bindable, 1); break; } } else if (st->compositor->term) { if (gf_is_process_anchor(sh->owner, &evt)) break; } else if (st->compositor->user->EventProc) { if (st->compositor->user->EventProc(st->compositor->user->opaque, &evt)) break; } i++; } } else if (ev->type==GF_EVENT_MOUSEMOVE) { if (st->compositor->user->EventProc) { evt.type = GF_EVENT_NAVIGATE_INFO; if (gf_node_get_tag(sh->owner)==TAG_MPEG4_Anchor) { evt.navigate.to_url = ((M_Anchor *)sh->owner)->description.buffer; url = & ((M_Anchor *)sh->owner)->url; } else { evt.navigate.to_url = ((X_Anchor *)sh->owner)->description.buffer; url = & ((X_Anchor *)sh->owner)->url; } if (!evt.navigate.to_url || !strlen(evt.navigate.to_url)) evt.navigate.to_url = url->vals[0].url; st->compositor->user->EventProc(st->compositor->user->opaque, &evt); } } }
GF_Node *compositor_svg_get_xlink_resource_node(GF_Node *node, XMLRI *xlink) { SVGlinkStack *stack; switch (gf_node_get_tag(node)) { case TAG_SVG_animation: stack = gf_node_get_private(node); return gf_sg_get_root_node(stack->inline_sg); case TAG_SVG_use: stack = gf_node_get_private(node); if (stack && stack->fragment_id) return gf_sg_find_node_by_name(stack->inline_sg, (char *) stack->fragment_id+1); return xlink ? xlink->target : NULL; } return NULL; }
/* Tries to resolve event-based or sync-based time values Used in parsing, to determine if a timed element can be initialized */ Bool gf_svg_resolve_smil_times(GF_Node *anim, void *event_base_element, GF_List *smil_times, Bool is_end, const char *node_name) { u32 i, done, count; done = 0; count = gf_list_count(smil_times); for (i=0; i<count; i++) { SMIL_Time *t = (SMIL_Time *)gf_list_get(smil_times, i); if (t->type != GF_SMIL_TIME_EVENT) { done++; continue; } if (!t->element_id) { if (!t->element) t->element = (GF_Node *)event_base_element; done++; continue; } /*commented out because it breaks regular anims (cf interact-pevents-07-t.svg)*/ // if (node_name && strcmp(node_name, t->element_id)) continue; t->element = gf_sg_find_node_by_name(anim->sgprivate->scenegraph, t->element_id); if (t->element) { gf_free(t->element_id); t->element_id = NULL; done++; } } /*lacuna value of discard is 0*/ if (!count && !is_end && (anim->sgprivate->tag==TAG_SVG_discard) ) { SMIL_Time *t; GF_SAFEALLOC(t, SMIL_Time); t->clock = 0; t->type = GF_SMIL_TIME_CLOCK; gf_list_add(smil_times, t); return 1; } if (done!=count) return 0; return 1; }
GF_EXPORT GF_Err gf_bifs_encoder_new_stream(GF_BifsEncoder *codec, u16 ESID, GF_BIFSConfig *cfg, Bool encodeNames, Bool has_predictive) { u32 i, count; BIFSStreamInfo *pInfo; // gf_mx_p(codec->mx); if (BE_GetStream(codec, ESID) != NULL) { // gf_mx_v(codec->mx); return GF_BAD_PARAM; } GF_SAFEALLOC(pInfo, BIFSStreamInfo); pInfo->ESID = ESID; codec->UseName = encodeNames; pInfo->config.Height = cfg->pixelHeight; pInfo->config.Width = cfg->pixelWidth; pInfo->config.NodeIDBits = cfg->nodeIDbits; pInfo->config.RouteIDBits = cfg->routeIDbits; pInfo->config.ProtoIDBits = cfg->protoIDbits; pInfo->config.PixelMetrics = cfg->pixelMetrics; pInfo->config.version = (has_predictive || cfg->protoIDbits) ? 2 : 1; pInfo->config.UsePredictiveMFField = has_predictive; if (cfg->elementaryMasks) { pInfo->config.elementaryMasks = gf_list_new(); count = gf_list_count(cfg->elementaryMasks); for (i=0; i<count; i++) { BIFSElementaryMask *bem; GF_ElementaryMask *em = (GF_ElementaryMask *)gf_list_get(cfg->elementaryMasks, i); GF_SAFEALLOC(bem, BIFSElementaryMask); if (em->node_id) bem->node = gf_sg_find_node(codec->scene_graph, em->node_id); else if (em->node_name) bem->node = gf_sg_find_node_by_name(codec->scene_graph, em->node_name); bem->node_id = em->node_id; gf_list_add(pInfo->config.elementaryMasks, bem); } } gf_list_add(codec->streamInfo, pInfo); // gf_mx_v(codec->mx); return GF_OK; }
static void anchor_activation(GF_Node *node, AnchorStack *st, GF_Compositor *compositor) { GF_Event evt; u32 i; MFURL *url = NULL; switch (gf_node_get_tag(node)) { case TAG_MPEG4_Anchor: url = & ((M_Anchor *)node)->url; evt.navigate.param_count = ((M_Anchor *)node)->parameter.count; evt.navigate.parameters = (const char **) ((M_Anchor *)node)->parameter.vals; break; #ifndef GPAC_DISABLE_X3D case TAG_X3D_Anchor: url = & ((X_Anchor *)node)->url; evt.navigate.param_count = ((X_Anchor *)node)->parameter.count; evt.navigate.parameters = (const char **) ((X_Anchor *)node)->parameter.vals; break; #endif } evt.type = GF_EVENT_NAVIGATE; i=0; while (url && i<url->count) { evt.navigate.to_url = url->vals[i].url; if (!evt.navigate.to_url) break; /*current scene navigation*/ if (evt.navigate.to_url[0] == '#') { GF_Node *bindable; evt.navigate.to_url++; bindable = gf_sg_find_node_by_name(gf_node_get_graph(node), (char *) evt.navigate.to_url); if (bindable) { Bindable_SetSetBind(bindable, 1); break; } } else if (compositor->term) { if (gf_scene_process_anchor(node, &evt)) break; } else if (gf_term_send_event(compositor->term, &evt)) { break; } i++; } }
GF_EXPORT Bool gf_mo_get_visual_info(GF_MediaObject *mo, u32 *width, u32 *height, u32 *stride, u32 *pixel_ar, u32 *pixelFormat, Bool *is_flipped) { GF_CodecCapability cap; if ((mo->type != GF_MEDIA_OBJECT_VIDEO) && (mo->type!=GF_MEDIA_OBJECT_TEXT)) return GF_FALSE; if (width) { cap.CapCode = GF_CODEC_WIDTH; gf_codec_get_capability(mo->odm->codec, &cap); *width = cap.cap.valueInt; } if (height) { cap.CapCode = GF_CODEC_HEIGHT; gf_codec_get_capability(mo->odm->codec, &cap); *height = cap.cap.valueInt; } if (mo->type==GF_MEDIA_OBJECT_TEXT) return GF_TRUE; if (is_flipped) { cap.CapCode = GF_CODEC_FLIP; cap.cap.valueInt = 0; gf_codec_get_capability(mo->odm->codec, &cap); *is_flipped = cap.cap.valueInt ? GF_TRUE : GF_FALSE; } if (stride) { cap.CapCode = GF_CODEC_STRIDE; gf_codec_get_capability(mo->odm->codec, &cap); *stride = cap.cap.valueInt; } if (pixelFormat) { cap.CapCode = GF_CODEC_PIXEL_FORMAT; gf_codec_get_capability(mo->odm->codec, &cap); *pixelFormat = cap.cap.valueInt; if (mo->odm && mo->odm->parentscene->is_dynamic_scene) { #ifndef GPAC_DISABLE_VRML const char *name = gf_node_get_name(gf_event_target_get_node(gf_mo_event_target_get(mo, 0))); if (name && !strcmp(name, "DYN_VIDEO")) { const char *opt; u32 r, g, b, a; M_Background2D *back = (M_Background2D *) gf_sg_find_node_by_name(mo->odm->parentscene->graph, "DYN_BACK"); if (back) { switch (cap.cap.valueInt) { case GF_PIXEL_ARGB: case GF_PIXEL_RGBA: case GF_PIXEL_YUVA: opt = gf_cfg_get_key(mo->odm->term->user->config, "Compositor", "BackColor"); if (!opt) { gf_cfg_set_key(mo->odm->term->user->config, "Compositor", "BackColor", "FF999999"); opt = "FF999999"; } sscanf(opt, "%02X%02X%02X%02X", &a, &r, &g, &b); back->backColor.red = INT2FIX(r)/255; back->backColor.green = INT2FIX(g)/255; back->backColor.blue = INT2FIX(b)/255; break; default: back->backColor.red = back->backColor.green = back->backColor.blue = 0; break; } gf_node_dirty_set((GF_Node *)back, 0, GF_TRUE); } } #endif } } /*get PAR settings*/ if (pixel_ar) { cap.CapCode = GF_CODEC_PAR; gf_codec_get_capability(mo->odm->codec, &cap); *pixel_ar = cap.cap.valueInt; if (! (*pixel_ar & 0x0000FFFF)) *pixel_ar = 0; if (! (*pixel_ar & 0xFFFF0000)) *pixel_ar = 0; /**/ if (! *pixel_ar) { GF_Channel *ch; GF_NetworkCommand com; com.base.command_type = GF_NET_CHAN_GET_PIXEL_AR; ch = (GF_Channel *)gf_list_get(mo->odm->channels, 0); if (!ch) return GF_FALSE; com.base.on_channel = ch; com.par.hSpacing = com.par.vSpacing = 0; if (gf_term_service_command(ch->service, &com) == GF_OK) { if ((com.par.hSpacing>65535) || (com.par.vSpacing>65535)) { com.par.hSpacing>>=16; com.par.vSpacing>>=16; } if (com.par.hSpacing|| com.par.vSpacing) *pixel_ar = (com.par.hSpacing<<16) | com.par.vSpacing; } }
static Bool OnAnchor(SensorHandler *sh, GF_Event *evt, DrawableContext *ctx, GF_Matrix2D *sensor_matrix) { u32 i; GF_Event event; AnchorStack *st = (AnchorStack *) gf_node_get_private(sh->owner); M_Anchor *an = (M_Anchor *) sh->owner; if (ctx==NULL) { event.type = GF_EVENT_NAVIGATE_INFO; event.navigate.to_url = ""; st->compositor->user->EventProc(st->compositor->user->opaque, &event); st->is_over = 0; return 0; } if (evt->type == GF_EVENT_MOUSEMOVE) { if (!st->is_over && st->compositor->user->EventProc) { event.type = GF_EVENT_NAVIGATE_INFO; event.navigate.to_url = an->description.buffer; if (!event.navigate.to_url || !strlen(event.navigate.to_url)) event.navigate.to_url = an->url.vals[0].url; st->compositor->user->EventProc(st->compositor->user->opaque, &event); } st->is_over = 1; return 0; } if ((evt->type != GF_EVENT_MOUSEUP) || (evt->mouse.button != GF_MOUSE_LEFT)) return 0; event.type = GF_EVENT_NAVIGATE; event.navigate.param_count = an->parameter.count; event.navigate.parameters = (const char **) an->parameter.vals; i=0; while (i<an->url.count) { event.navigate.to_url = an->url.vals[i].url; if (!event.navigate.to_url) break; /*current scene navigation*/ if (event.navigate.to_url[0] == '#') { GF_Node *n; event.navigate.to_url++; n = gf_sg_find_node_by_name(gf_node_get_graph(sh->owner), (char *) event.navigate.to_url); if (n) { switch (gf_node_get_tag(n)) { case TAG_MPEG4_Viewport: ((M_Viewport *)n)->set_bind = 1; ((M_Viewport *)n)->on_set_bind(n); break; } break; } } else if (st->compositor->term) { if (gf_is_process_anchor(sh->owner, &event)) break; } else if (st->compositor->user->EventProc) { if (st->compositor->user->EventProc(st->compositor->user->opaque, &event)) break; } i++; } return 0; }
static void svg_parse_animation(GF_SceneGraph *sg, SVG_DeferedAnimation *anim) { GF_FieldInfo info; u32 tag; u8 anim_value_type = 0; if (anim->resolve_stage==0) { /* Stage 0: parsing the animation attribute values for that we need to resolve the target first */ if (!anim->target) anim->target = (SVG_Element *) gf_sg_find_node_by_name(sg, anim->target_id + 1); if (!anim->target) { /* the target is still not known stay in stage 0 */ return; } else { XMLRI *iri; gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_XLINK_ATT_href, 1, 0, &info); iri = (XMLRI *)info.far_ptr; iri->type = XMLRI_ELEMENTID; iri->target = anim->target; gf_node_register_iri(sg, iri); } tag = gf_node_get_tag((GF_Node *)anim->animation_elt); /* get the attribute name attribute if specified */ if (anim->type && (tag== TAG_SVG_animateTransform) ) { gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_transform_type, 1, 0, &info); gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->type, 0); switch(*(SVG_TransformType *) info.far_ptr) { case SVG_TRANSFORM_TRANSLATE: anim_value_type = SVG_Transform_Translate_datatype; break; case SVG_TRANSFORM_SCALE: anim_value_type = SVG_Transform_Scale_datatype; break; case SVG_TRANSFORM_ROTATE: anim_value_type = SVG_Transform_Rotate_datatype; break; case SVG_TRANSFORM_SKEWX: anim_value_type = SVG_Transform_SkewX_datatype; break; case SVG_TRANSFORM_SKEWY: anim_value_type = SVG_Transform_SkewY_datatype; break; case SVG_TRANSFORM_MATRIX: anim_value_type = SVG_Transform_datatype; break; default: fprintf(stdout, "unknown datatype for animate transform"); return; } } else if (gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_attributeName, 0, 0, &info) == GF_OK) { gf_node_get_attribute_by_name((GF_Node *)anim->target, ((SMIL_AttributeName *)info.far_ptr)->name, 0, 1, 1, &info); anim_value_type = info.fieldType; } else { if (tag == TAG_SVG_animateMotion) { anim_value_type = SVG_Motion_datatype; } else if (tag == TAG_SVG_discard) { /* there is no value to parse in discard, we can jump to the next stage */ anim->resolve_stage = 1; svg_parse_animation(sg, anim); return; } else { fprintf(stdout, "Missing attributeName attribute on %s", gf_node_get_name((GF_Node *)anim->animation_elt)); return; } } if (anim->to) { gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_to, 1, 0, &info); gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->to, anim_value_type); } if (anim->from) { gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_from, 1, 0, &info); gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->from, anim_value_type); } if (anim->by) { gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_by, 1, 0, &info); gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->by, anim_value_type); } if (anim->values) { gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_values, 1, 0, &info); gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->values, anim_value_type); } anim->resolve_stage = 1; } }
static GF_Err gf_text_import_srt_bifs(GF_SceneManager *ctx, GF_ESD *src, GF_MuxInfo *mux) { GF_Err e; GF_Node *text, *font; GF_StreamContext *srt; FILE *srt_in; GF_FieldInfo string, style; u32 sh, sm, ss, sms, eh, em, es, ems, start, end; GF_AUContext *au; GF_Command *com; SFString *sfstr; GF_CommandField *inf; Bool italic, underlined, bold; u32 state, curLine, line, i, len; char szLine[2048], szText[2048], *ptr; GF_StreamContext *sc = NULL; if (!ctx->scene_graph) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] base scene not assigned\n")); return GF_BAD_PARAM; } i=0; while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) { if (sc->streamType==GF_STREAM_SCENE) break; sc = NULL; } if (!sc) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot locate base scene\n")); return GF_BAD_PARAM; } if (!mux->textNode) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] Target text node unspecified\n")); return GF_BAD_PARAM; } text = gf_sg_find_node_by_name(ctx->scene_graph, mux->textNode); if (!text) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot find target text node %s\n", mux->textNode)); return GF_BAD_PARAM; } if (gf_node_get_field_by_name(text, "string", &string) != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] Target text node %s doesn't look like text\n", mux->textNode)); return GF_BAD_PARAM; } font = NULL; if (mux->fontNode) { font = gf_sg_find_node_by_name(ctx->scene_graph, mux->fontNode); if (!font) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot find target font node %s\n", mux->fontNode)); return GF_BAD_PARAM; } if (gf_node_get_field_by_name(font, "style", &style) != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] Target font node %s doesn't look like font\n", mux->fontNode)); return GF_BAD_PARAM; } } srt_in = gf_f64_open(mux->file_name, "rt"); if (!srt_in) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot open input file %s\n", mux->file_name)); return GF_URL_ERROR; } srt = gf_sm_stream_new(ctx, src->ESID, GF_STREAM_SCENE, 1); if (!srt) return GF_OUT_OF_MEM; if (!src->slConfig) src->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); src->slConfig->timestampResolution = 1000; if (!src->decoderConfig) src->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG); src->decoderConfig->streamType = GF_STREAM_SCENE; src->decoderConfig->objectTypeIndication = 1; e = GF_OK; state = end = 0; curLine = 0; au = NULL; com = NULL; italic = underlined = bold = 0; inf = NULL; while (1) { char *sOK = fgets(szLine, 2048, srt_in); if (sOK) REM_TRAIL_MARKS(szLine, "\r\n\t ") if (!sOK || !strlen(szLine)) { state = 0; if (au) { /*if italic or underscore do it*/ if (font && (italic || underlined || bold)) { com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = font; gf_node_register(font, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = style.fieldIndex; inf->fieldType = style.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(style.fieldType); sfstr = (SFString *)inf->field_ptr; if (bold && italic && underlined) sfstr->buffer = gf_strdup("BOLDITALIC UNDERLINED"); else if (italic && underlined) sfstr->buffer = gf_strdup("ITALIC UNDERLINED"); else if (bold && underlined) sfstr->buffer = gf_strdup("BOLD UNDERLINED"); else if (underlined) sfstr->buffer = gf_strdup("UNDERLINED"); else if (bold && italic) sfstr->buffer = gf_strdup("BOLDITALIC"); else if (bold) sfstr->buffer = gf_strdup("BOLD"); else sfstr->buffer = gf_strdup("ITALIC"); gf_list_add(au->commands, com); } au = gf_sm_stream_au_new(srt, end, 0, 1); com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = text; gf_node_register(text, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = string.fieldIndex; inf->fieldType = string.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType); gf_list_add(au->commands, com); /*reset font styles so that all AUs are true random access*/ if (font) { com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = font; gf_node_register(font, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = style.fieldIndex; inf->fieldType = style.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(style.fieldType); gf_list_add(au->commands, com); } au = NULL; } inf = NULL; if (!sOK) break; continue; } switch (state) { case 0: if (sscanf(szLine, "%u", &line) != 1) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] bad frame format (src: %s)\n", szLine)); e = GF_CORRUPTED_DATA; goto exit; } if (line != curLine + 1) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] bad frame: previous %d - current %d (src: %s)\n", curLine, line, szLine)); e = GF_CORRUPTED_DATA; goto exit; } curLine = line; state = 1; break; case 1: if (sscanf(szLine, "%u:%u:%u,%u --> %u:%u:%u,%u", &sh, &sm, &ss, &sms, &eh, &em, &es, &ems) != 8) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] bad frame %u (src: %s)\n", curLine, szLine)); e = GF_CORRUPTED_DATA; goto exit; } start = (3600*sh + 60*sm + ss)*1000 + sms; if (start<end) { GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[srt->bifs] corrupted frame starts before end of previous one (SRT Frame %d) - adjusting time stamps\n", curLine)); start = end; } end = (3600*eh + 60*em + es)*1000 + ems; /*make stream start at 0 by inserting a fake AU*/ if ((curLine==1) && start>0) { au = gf_sm_stream_au_new(srt, 0, 0, 1); com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = text; gf_node_register(text, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = string.fieldIndex; inf->fieldType = string.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType); gf_list_add(au->commands, com); } au = gf_sm_stream_au_new(srt, start, 0, 1); com = NULL; state = 2; italic = underlined = bold = 0; break; default: ptr = szLine; /*FIXME - other styles posssibles ??*/ while (1) { if (!strnicmp(ptr, "<i>", 3)) { italic = 1; ptr += 3; } else if (!strnicmp(ptr, "<u>", 3)) { underlined = 1; ptr += 3; } else if (!strnicmp(ptr, "<b>", 3)) { bold = 1; ptr += 3; } else break; } /*if style remove end markers*/ while ((strlen(ptr)>4) && (ptr[strlen(ptr) - 4] == '<') && (ptr[strlen(ptr) - 1] == '>')) { ptr[strlen(ptr) - 4] = 0; } if (!com) { com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = text; gf_node_register(text, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = string.fieldIndex; inf->fieldType = string.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType); gf_list_add(au->commands, com); } assert(inf); gf_sg_vrml_mf_append(inf->field_ptr, GF_SG_VRML_MFSTRING, (void **) &sfstr); len = 0; for (i=0; i<strlen(ptr); i++) { /*FIXME - UTF16 support !!*/ if (ptr[i] & 0x80) { /*non UTF8 (likely some win-CP)*/ if ((ptr[i+1] & 0xc0) != 0x80) { szText[len] = 0xc0 | ( (ptr[i] >> 6) & 0x3 ); len++; ptr[i] &= 0xbf; } /*we only handle UTF8 chars on 2 bytes (eg first byte is 0b110xxxxx)*/ else if ((ptr[i] & 0xe0) == 0xc0) { szText[len] = ptr[i]; len++; i++; } } szText[len] = ptr[i]; len++; } szText[len] = 0; sfstr->buffer = gf_strdup(szText); break; }
static void svg_traverse_resource(GF_Node *node, void *rs, Bool is_destroy, Bool is_foreign_object) { GF_Matrix2D backup_matrix; GF_Matrix mx_3d; GF_Matrix2D translate; SVGPropertiesPointers backup_props; u32 backup_flags, dirty; Bool is_fragment; GF_Node *used_node; GF_TraverseState *tr_state = (GF_TraverseState *)rs; SVGAllAttributes all_atts; SVGlinkStack *stack = gf_node_get_private(node); SFVec2f prev_vp; SVG_Number *prev_opacity; if (is_destroy) { if (stack->resource) gf_mo_unload_xlink_resource(node, stack->resource); gf_free(stack); return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); if (!all_atts.xlink_href) return; if (!compositor_svg_traverse_base(node, &all_atts, tr_state, &backup_props, &backup_flags)) return; dirty = gf_node_dirty_get(node); if (dirty & GF_SG_CHILD_DIRTY) drawable_reset_group_highlight(tr_state, node); if (dirty & GF_SG_SVG_XLINK_HREF_DIRTY) { stack->fragment_id = NULL; stack->inline_sg = NULL; if (all_atts.xlink_href->string && (all_atts.xlink_href->string[0]=='#')) { stack->fragment_id = all_atts.xlink_href->string; stack->inline_sg = gf_node_get_graph(node); } else { GF_MediaObject *new_res = gf_mo_load_xlink_resource(node, is_foreign_object, 0, -1); if (new_res != stack->resource) { if (stack->resource) gf_mo_unload_xlink_resource(node, stack->resource); stack->resource = new_res; } } } gf_node_dirty_clear(node, 0); /*locate the used node - this is done at each step to handle progressive loading*/ is_fragment = 0; used_node = NULL; if (!stack->inline_sg && !stack->fragment_id && all_atts.xlink_href) { if (all_atts.xlink_href->type == XMLRI_ELEMENTID) { used_node = all_atts.xlink_href->target; is_fragment = 1; } else if (stack->resource) { stack->inline_sg = gf_mo_get_scenegraph(stack->resource); if (!is_foreign_object) { stack->fragment_id = strchr(all_atts.xlink_href->string, '#'); } } } if (!used_node && stack->inline_sg) { if (stack->fragment_id) { used_node = gf_sg_find_node_by_name(stack->inline_sg, (char *) stack->fragment_id+1); is_fragment = 1; } else if (is_foreign_object) { used_node = gf_sg_get_root_node(stack->inline_sg); } } if (!used_node) goto end; /*stack use nodes for picking*/ gf_list_add(tr_state->use_stack, used_node); gf_list_add(tr_state->use_stack, node); gf_mx2d_init(translate); translate.m[2] = (all_atts.x ? all_atts.x->value : 0); translate.m[5] = (all_atts.y ? all_atts.y->value : 0); /*update VP size (SVG 1.1)*/ prev_vp = tr_state->vp_size; if (all_atts.width && all_atts.height) { tr_state->vp_size.x = gf_sc_svg_convert_length_to_display(tr_state->visual->compositor, all_atts.width); tr_state->vp_size.y = gf_sc_svg_convert_length_to_display(tr_state->visual->compositor, all_atts.height); } prev_opacity = tr_state->parent_use_opacity; tr_state->parent_use_opacity = all_atts.opacity; if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) { compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d); if (!compositor_svg_is_display_off(tr_state->svg_props)) { gf_node_traverse(used_node, tr_state); gf_mx2d_apply_rect(&translate, &tr_state->bounds); } compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d); } /*SORT mode and visible, traverse*/ else if (!compositor_svg_is_display_off(tr_state->svg_props) && (*(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN)) { compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d); #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) { gf_mx_add_matrix_2d(&tr_state->model_matrix, &translate); if (tr_state->traversing_mode==TRAVERSE_SORT) { GF_Matrix tmp; gf_mx_from_mx2d(&tmp, &translate); visual_3d_matrix_add(tr_state->visual, tmp.m); } } else #endif gf_mx2d_pre_multiply(&tr_state->transform, &translate); drawable_check_focus_highlight(node, tr_state, NULL); if (is_fragment) { gf_node_traverse(used_node, tr_state); } else { gf_sc_traverse_subscene(tr_state->visual->compositor, node, stack->inline_sg, tr_state); } compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d); } gf_list_rem_last(tr_state->use_stack); gf_list_rem_last(tr_state->use_stack); tr_state->vp_size = prev_vp; tr_state->parent_use_opacity = prev_opacity; end: memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); tr_state->svg_flags = backup_flags; }
static void svg_a_handle_event(GF_Node *handler, GF_DOM_Event *event, GF_Node *observer) { GF_Compositor *compositor; GF_Event evt; SVG_Element *a; SVGAllAttributes all_atts; if (event->event_phase & GF_DOM_EVENT_PHASE_PREVENT) return; assert(gf_node_get_tag((GF_Node*)event->currentTarget->ptr)==TAG_SVG_a); a = (SVG_Element *) event->currentTarget->ptr; gf_svg_flatten_attributes(a, &all_atts); compositor = (GF_Compositor *)gf_node_get_private((GF_Node *)handler); if (!compositor->user->EventProc) return; if (!all_atts.xlink_href) return; if (event->type==GF_EVENT_MOUSEOVER) { evt.type = GF_EVENT_NAVIGATE_INFO; if (all_atts.xlink_title) evt.navigate.to_url = *all_atts.xlink_title; else if (all_atts.xlink_href->string) evt.navigate.to_url = all_atts.xlink_href->string; else { evt.navigate.to_url = gf_node_get_name(all_atts.xlink_href->target); if (!evt.navigate.to_url) evt.navigate.to_url = "document internal link"; } gf_term_send_event(compositor->term, &evt); return; } evt.type = GF_EVENT_NAVIGATE; if (all_atts.xlink_href->type == XMLRI_STRING) { evt.navigate.to_url = gf_term_resolve_xlink(handler, all_atts.xlink_href->string); if (evt.navigate.to_url) { if (all_atts.target) { evt.navigate.parameters = (const char **) &all_atts.target; evt.navigate.param_count = 1; } else { evt.navigate.parameters = NULL; evt.navigate.param_count = 0; } if (evt.navigate.to_url[0] != '#') { if (compositor->term) { gf_scene_process_anchor(handler, &evt); } else { gf_term_send_event(compositor->term, &evt); } gf_free((char *)evt.navigate.to_url); return; } all_atts.xlink_href->target = gf_sg_find_node_by_name(gf_node_get_graph(handler), (char *) evt.navigate.to_url+1); if (all_atts.xlink_href->target) { all_atts.xlink_href->type = XMLRI_ELEMENTID; gf_free((char *)evt.navigate.to_url); } else { svg_a_set_view(handler, compositor, evt.navigate.to_url + 1); gf_free((char *)evt.navigate.to_url); return; } } } if (!all_atts.xlink_href->target) { return; } /*this is a time event*/ if (is_timing_target(all_atts.xlink_href->target)) { gf_smil_timing_insert_clock(all_atts.xlink_href->target, 0, gf_node_get_scene_time((GF_Node *)handler) ); } /*this is an implicit SVGView event*/ else { svg_a_set_view(handler, compositor, gf_node_get_name(all_atts.xlink_href->target)); } }
static void svg_recompute_viewport_transformation(GF_Node *node, SVGsvgStack *stack, GF_TraverseState *tr_state, SVGAllAttributes *atts) { GF_Matrix2D mx; SVG_ViewBox ext_vb, *vb; SVG_PreserveAspectRatio par; Fixed scale, vp_w, vp_h; Fixed parent_width, parent_height, doc_width, doc_height; /*canvas size negociation has already been done when attaching the scene to the compositor*/ if (atts->width && (atts->width->type==SVG_NUMBER_PERCENTAGE) ) { parent_width = gf_mulfix(tr_state->vp_size.x, atts->width->value/100); doc_width = 0; } else if (!stack->root_svg) { doc_width = parent_width = atts->width ? atts->width->value : 0; } else { parent_width = tr_state->vp_size.x; doc_width = atts->width ? atts->width->value : 0; } if (atts->height && (atts->height->type==SVG_NUMBER_PERCENTAGE) ) { parent_height = gf_mulfix(tr_state->vp_size.y, atts->height->value/100); doc_height = 0; } else if (!stack->root_svg) { doc_height = parent_height = atts->height ? atts->height->value : 0; } else { parent_height = tr_state->vp_size.y; doc_height = atts->height ? atts->height->value : 0; } stack->vp = stack->parent_vp = tr_state->vp_size; vb = atts->viewBox; gf_mx2d_init(mx); if (stack->root_svg) { const char *frag_uri = gf_scene_get_fragment_uri(node); if (frag_uri) { /*SVGView*/ if (!strncmp(frag_uri, "svgView", 7)) { if (!strncmp(frag_uri, "svgView(viewBox(", 16)) { Float x, y, w, h; sscanf(frag_uri, "svgView(viewBox(%f,%f,%f,%f))", &x, &y, &w, &h); ext_vb.x = FLT2FIX(x); ext_vb.y = FLT2FIX(y); ext_vb.width = FLT2FIX(w); ext_vb.height = FLT2FIX(h); ext_vb.is_set = 1; vb = &ext_vb; } else if (!strncmp(frag_uri, "svgView(transform(", 18)) { Bool ret = gf_svg_parse_transformlist(&mx, (char *) frag_uri+18); if (!ret) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] Error parsing SVG View transform component: %s\n", frag_uri+18)); } } } /*fragID*/ else { GF_Node *target = gf_sg_find_node_by_name(gf_node_get_graph(node), (char *) frag_uri); if (target) { GF_Matrix2D mx; GF_TraverseState bounds_state; memset(&bounds_state, 0, sizeof(bounds_state)); bounds_state.traversing_mode = TRAVERSE_GET_BOUNDS; bounds_state.visual = tr_state->visual; bounds_state.for_node = target; bounds_state.svg_props = tr_state->svg_props; gf_mx2d_init(bounds_state.transform); gf_mx2d_init(bounds_state.mx_at_node); gf_mx_init(tr_state->visual->compositor->hit_world_to_local); gf_sc_get_nodes_bounds(node, ((GF_ParentNode *)node)->children, &bounds_state, NULL); gf_mx2d_from_mx(&mx, &tr_state->visual->compositor->hit_world_to_local); gf_mx2d_apply_rect(&mx, &bounds_state.bounds); ext_vb.x = bounds_state.bounds.x; ext_vb.y = bounds_state.bounds.y-bounds_state.bounds.height; ext_vb.width = bounds_state.bounds.width; ext_vb.height = bounds_state.bounds.height; ext_vb.is_set = 1; vb = &ext_vb; } } } } gf_mx2d_init(stack->viewbox_mx); if (!vb) { if (!doc_width || !doc_height) { gf_mx2d_copy(stack->viewbox_mx, mx); return; } /*width/height were specified in the doc, use them to compute a dummy viewbox*/ ext_vb.x = 0; ext_vb.y = 0; ext_vb.width = doc_width; ext_vb.height = doc_height; ext_vb.is_set = 1; vb = &ext_vb; } if ((vb->width<=0) || (vb->height<=0) ) { gf_mx2d_copy(stack->viewbox_mx, mx); return; } stack->vp.x = vb->width; stack->vp.y = vb->height; /*setup default*/ par.defer = 0; par.meetOrSlice = SVG_MEETORSLICE_MEET; par.align = SVG_PRESERVEASPECTRATIO_XMIDYMID; /*use parent (animation, image) viewport settings*/ if (tr_state->parent_anim_atts) { if (tr_state->parent_anim_atts->preserveAspectRatio) { if (tr_state->parent_anim_atts->preserveAspectRatio->defer) { if (atts->preserveAspectRatio) par = *atts->preserveAspectRatio; } else { par = *tr_state->parent_anim_atts->preserveAspectRatio; } } } /*use current viewport settings*/ else if (atts->preserveAspectRatio) { par = *atts->preserveAspectRatio; } if (par.meetOrSlice==SVG_MEETORSLICE_MEET) { if (gf_divfix(parent_width, vb->width) > gf_divfix(parent_height, vb->height)) { scale = gf_divfix(parent_height, vb->height); vp_w = gf_mulfix(vb->width, scale); vp_h = parent_height; } else { scale = gf_divfix(parent_width, vb->width); vp_w = parent_width; vp_h = gf_mulfix(vb->height, scale); } } else { if (gf_divfix(parent_width, vb->width) < gf_divfix(parent_height, vb->height)) { scale = gf_divfix(parent_height, vb->height); vp_w = gf_mulfix(vb->width, scale); vp_h = parent_height; } else { scale = gf_divfix(parent_width, vb->width); vp_w = parent_width; vp_h = gf_mulfix(vb->height, scale); } } if (par.align==SVG_PRESERVEASPECTRATIO_NONE) { stack->viewbox_mx.m[0] = gf_divfix(parent_width, vb->width); stack->viewbox_mx.m[4] = gf_divfix(parent_height, vb->height); stack->viewbox_mx.m[2] = - gf_muldiv(vb->x, parent_width, vb->width); stack->viewbox_mx.m[5] = - gf_muldiv(vb->y, parent_height, vb->height); } else { Fixed dx, dy; stack->viewbox_mx.m[0] = stack->viewbox_mx.m[4] = scale; stack->viewbox_mx.m[2] = - gf_mulfix(vb->x, scale); stack->viewbox_mx.m[5] = - gf_mulfix(vb->y, scale); dx = dy = 0; switch (par.align) { case SVG_PRESERVEASPECTRATIO_XMINYMIN: break; case SVG_PRESERVEASPECTRATIO_XMIDYMIN: dx = ( parent_width - vp_w) / 2; break; case SVG_PRESERVEASPECTRATIO_XMAXYMIN: dx = parent_width - vp_w; break; case SVG_PRESERVEASPECTRATIO_XMINYMID: dy = ( parent_height - vp_h) / 2; break; case SVG_PRESERVEASPECTRATIO_XMIDYMID: dx = ( parent_width - vp_w) / 2; dy = ( parent_height - vp_h) / 2; break; case SVG_PRESERVEASPECTRATIO_XMAXYMID: dx = parent_width - vp_w; dy = ( parent_height - vp_h) / 2; break; case SVG_PRESERVEASPECTRATIO_XMINYMAX: dy = parent_height - vp_h; break; case SVG_PRESERVEASPECTRATIO_XMIDYMAX: dx = (parent_width - vp_w) / 2; dy = parent_height - vp_h; break; case SVG_PRESERVEASPECTRATIO_XMAXYMAX: dx = parent_width - vp_w; dy = parent_height - vp_h; break; } gf_mx2d_add_translation(&stack->viewbox_mx, dx, dy); stack->dx = dx; stack->dy = dy; stack->vpw = vp_w; stack->vph = vp_h; /*we need a clipper*/ if (stack->root_svg && !tr_state->parent_anim_atts && (par.meetOrSlice==SVG_MEETORSLICE_SLICE)) { GF_Rect rc; rc.width = parent_width; rc.height = parent_height; if (!stack->root_svg) { rc.x = 0; rc.y = parent_height; gf_mx2d_apply_rect(&stack->viewbox_mx, &rc); } else { rc.x = dx; rc.y = dy + parent_height; } // tr_state->visual->top_clipper = gf_rect_pixelize(&rc); } } gf_mx2d_add_matrix(&stack->viewbox_mx, &mx); }