📄 svg_smjs.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Authors: Jean le Feuvre * Copyright (c) 2005-200X ENST * All rights reserved * * This file is part of GPAC / Scene Graph 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 <gpac/internal/scenegraph_dev.h>#ifndef GPAC_DISABLE_SVG#include <gpac/events.h>#include <gpac/nodes_svg_da.h>#ifdef GPAC_HAS_SPIDERMONKEY#define uDOM_SETUP_CLASS(the_class, cname, flag, getp, setp, fin) \ memset(&the_class, 0, sizeof(the_class)); \ the_class.name = cname; \ the_class.flags = flag; \ the_class.addProperty = JS_PropertyStub; \ the_class.delProperty = JS_PropertyStub; \ the_class.getProperty = getp; \ the_class.setProperty = setp; \ the_class.enumerate = JS_EnumerateStub; \ the_class.resolve = JS_ResolveStub; \ the_class.convert = JS_ConvertStub; \ the_class.finalize = fin; #define _ScriptMessage(_sg, _e, _msg) {\ GF_JSAPIParam par; \ par.info.e = _e; \ par.info.msg = _msg; \ _sg->script_action(_sg->script_action_cbck, GF_JSAPI_OP_MESSAGE, NULL, &par);\ }static GFINLINE Bool ScriptAction(GF_SceneGraph *scene, u32 type, GF_Node *node, GF_JSAPIParam *param){ if (scene->script_action) return scene->script_action(scene->script_action_cbck, type, node, param); return 0;}typedef struct{ u32 nb_inst; /*SVG uDOM classes*/ JSClass globalClass; JSClass connectionClass; JSClass rgbClass; JSClass rectClass; JSClass pointClass; JSClass pathClass; JSClass matrixClass;} GF_SVGuDOM;static GF_SVGuDOM *svg_rt = NULL;static JSObject *svg_new_path_object(JSContext *c, SVG_PathData *d);static void svg_node_changed(GF_Node *n, GF_FieldInfo *info){ if (!info) { gf_node_changed(n, NULL); } else { u32 flag = gf_svg_get_rendering_flag_if_modified((SVG_Element *)n, info); gf_node_dirty_set(n, flag, 0); } /*trigger rendering*/ if (n->sgprivate->scenegraph->NodeCallback) n->sgprivate->scenegraph->NodeCallback(n->sgprivate->scenegraph->userpriv, GF_SG_CALLBACK_MODIFIED, n, info);}/*note we are using float to avoid conversions fixed to/from JS native */typedef struct{ u32 r, g, b;} rgbCI;typedef struct{ Float x, y, w, h; /*if set, this is the svg.viewport uDOM object, its values are updated upon query*/ GF_SceneGraph *sg;} rectCI;typedef struct{ Float x, y; /*if set, this is the svg.currentTranslate uDOM object, its values are updated upon query*/ GF_SceneGraph *sg;} pointCI;typedef struct{ Float x, y;} ptCI;typedef struct{ u32 nb_coms; u8 *tags; ptCI *pts;} pathCI;static JSBool svg_connection_create(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval);static JSBool svg_nav_to_location(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ GF_JSAPIParam par; GF_SceneGraph *sg; if ((argc!=1) || !JS_InstanceOf(c, obj, &svg_rt->globalClass, NULL)) return JS_FALSE; sg = JS_GetContextPrivate(c); par.uri.url = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); par.uri.nb_params = 0; ScriptAction(sg, GF_JSAPI_OP_LOAD_URL, sg->RootNode, &par); return JS_FALSE;}static void svg_script_error(JSContext *c, const char *msg, JSErrorReport *jserr){ GF_SceneGraph *sg = JS_GetContextPrivate(c); _ScriptMessage(sg, GF_SCRIPT_ERROR, msg);}static JSBool svg_echo(JSContext *c, JSObject *p, uintN argc, jsval *argv, jsval *rval){ u32 i; char buf[5000]; GF_SceneGraph *sg = JS_GetContextPrivate(c); if (!sg) return JS_FALSE; strcpy(buf, ""); for (i = 0; i < argc; i++) { JSString *str = JS_ValueToString(c, argv[i]); if (!str) return JS_FALSE; if (i) strcat(buf, " "); strcat(buf, JS_GetStringBytes(str)); } _ScriptMessage(sg, GF_SCRIPT_INFO, buf); return JS_TRUE;}static JSBool global_getProperty(JSContext *c, JSObject *obj, jsval id, jsval *vp){ GF_SceneGraph *sg; if (!JS_InstanceOf(c, obj, &svg_rt->globalClass, NULL) ) return JS_FALSE; sg = JS_GetContextPrivate(c); if (JSVAL_IS_INT(id)) { switch (JSVAL_TO_INT(id)) { /*namespaceURI*/ case 0: return JS_TRUE; /*parent*/ case 1: *vp = JSVAL_VOID; if (sg->parent_scene && sg->parent_scene->svg_js) *vp = OBJECT_TO_JSVAL(sg->parent_scene->svg_js->global); return JS_TRUE; default: return JS_FALSE; } } return JS_TRUE;}/*TODO - try to be more precise...*/static JSBool dom_imp_has_feature(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ *rval = BOOLEAN_TO_JSVAL(0); if (argc) { u32 len; char sep; char *fname = JS_GetStringBytes(JS_ValueToString(c, argv[0])); if (!fname) return JS_FALSE; while (strchr(" \t\n\r", fname[0])) fname++; len = strlen(fname); while (len && strchr(" \t\n\r", fname[len-1])) len--; sep = fname[len]; fname[len] = 0; if (!stricmp(fname, "xml")) *rval = BOOLEAN_TO_JSVAL(1); else if (!stricmp(fname, "core")) *rval = BOOLEAN_TO_JSVAL(1); else if (!stricmp(fname, "traversal")) *rval = BOOLEAN_TO_JSVAL(1); else if (!stricmp(fname, "uievents")) *rval = BOOLEAN_TO_JSVAL(1); else if (!stricmp(fname, "mouseevents")) *rval = BOOLEAN_TO_JSVAL(1); else if (!stricmp(fname, "mutationevents")) *rval = BOOLEAN_TO_JSVAL(1); else if (!stricmp(fname, "events")) *rval = BOOLEAN_TO_JSVAL(1); fname[len] = sep; } return JS_TRUE;}static Bool svg_udom_smil_check_instance(JSContext *c, JSObject *obj){ GF_Node *n = dom_get_node(c, obj, NULL); if (!n) return 0; switch (n->sgprivate->tag) { case TAG_SVG_animate: case TAG_SVG_animateColor: case TAG_SVG_animateMotion: case TAG_SVG_animateTransform: case TAG_SVG_animation: case TAG_SVG_audio: case TAG_SVG_video: case TAG_SVG_set: /*not sure about this one...*/ case TAG_SVG_discard: return 1; } return 0;}/*TODO*/JSBool svg_udom_smil_begin(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ if (!svg_udom_smil_check_instance(c, obj) ) return JS_FALSE; return JS_FALSE;}/*TODO*/JSBool svg_udom_smil_end(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ if (!svg_udom_smil_check_instance(c, obj) ) return JS_FALSE; return JS_FALSE;}/*TODO*/JSBool svg_udom_smil_pause(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ if (!svg_udom_smil_check_instance(c, obj) ) return JS_FALSE; return JS_FALSE;}/*TODO*/JSBool svg_udom_smil_resume(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ if (!svg_udom_smil_check_instance(c, obj) ) return JS_FALSE; return JS_FALSE;}JSBool svg_udom_get_trait(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ char attValue[1024]; GF_Err e; GF_FieldInfo info; GF_Node *n = dom_get_node(c, obj, NULL); if (!n) return JS_FALSE; if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; if (argc==2) { char fullName[1024]; if (!JSVAL_IS_STRING(argv[1])) return JS_FALSE; strcpy(fullName, JS_GetStringBytes(JSVAL_TO_STRING(argv[0])) ); strcat(fullName, ":"); strcat(fullName, JS_GetStringBytes(JSVAL_TO_STRING(argv[1])) ); e = gf_node_get_field_by_name(n, fullName, &info); } else if (argc==2) { e = gf_node_get_field_by_name(n, JS_GetStringBytes(JSVAL_TO_STRING(argv[0])), &info); } else return JS_FALSE; if (e!=GF_OK) return JS_FALSE; *rval = JSVAL_VOID; switch (info.fieldType) { /* inheritable floats */ case SVG_FontSize_datatype: case SVG_Color_datatype: case SVG_Paint_datatype: /* inheritable float and unit */ case SVG_Length_datatype: case SVG_Coordinate_datatype: /*Number*/ case SVG_Number_datatype:/*all string traits*/ case SVG_Boolean_datatype: case SVG_FillRule_datatype: case SVG_StrokeLineJoin_datatype: case SVG_StrokeLineCap_datatype: case SVG_FontStyle_datatype: case SVG_FontWeight_datatype: case SVG_FontVariant_datatype: case SVG_TextAnchor_datatype: case SVG_Display_datatype: case SVG_Visibility_datatype: case SVG_GradientUnit_datatype: case SVG_PreserveAspectRatio_datatype: case XML_Space_datatype: case XMLEV_Propagate_datatype: case XMLEV_DefaultAction_datatype: case XMLEV_Phase_datatype: case SMIL_SyncBehavior_datatype: case SMIL_SyncTolerance_datatype: case SMIL_AttributeType_datatype: case SMIL_CalcMode_datatype: case SMIL_Additive_datatype: case SMIL_Accumulate_datatype: case SMIL_Restart_datatype: case SMIL_Fill_datatype: case SVG_Overflow_datatype: case SVG_ZoomAndPan_datatype: case SVG_DisplayAlign_datatype: case SVG_TextAlign_datatype: case SVG_PointerEvents_datatype: case SVG_RenderingHint_datatype: case SVG_VectorEffect_datatype: case SVG_PlaybackOrder_datatype: case SVG_TimelineBegin_datatype:/*end of string traits*//*DOM string traits*/ case SVG_FontFamily_datatype: case XMLRI_datatype: case SVG_String_datatype: case SVG_ContentType_datatype: case SVG_LanguageID_datatype: case SVG_Focus_datatype: case SVG_ID_datatype: case SVG_GradientOffset_datatype:/*end of DOM string traits*/ gf_svg_dump_attribute(n, &info, attValue); *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, attValue) ); return JS_TRUE; /*dump to trait*/ break;#if 0/*SVGT 1.2 default traits*/ case SMIL_KeyTimes_datatype: case SMIL_KeyPoints_datatype: case SMIL_KeySplines_datatype: case SVG_Coordinates_datatype: case SVG_StrokeDashArray_datatype: case SVG_Points_datatype: case SVG_Motion_datatype:/*end SVGT 1.2 default traits*//*unimplemented/unnkown/FIXME traits*/ case SMIL_SyncTolerance_datatype: case SVG_TransformType_datatype: case SVG_TransformList_datatype: case SMIL_AnimateValue_datatype: case SMIL_AnimateValues_datatype: case SMIL_AttributeName_datatype: case SMIL_Times_datatype: case SMIL_Duration_datatype: case SMIL_RepeatCount_datatype: default:/*end unimplemented/unnkown/FIXME traits*/ return JS_FALSE;#endif } return JS_FALSE;}JSBool svg_udom_get_float_trait(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ char *szName; GF_FieldInfo info; GF_Node *n = dom_get_node(c, obj, NULL); if (!n) return JS_FALSE; if (argc!=1) return JS_FALSE; if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; szName = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); *rval = JSVAL_VOID; if (gf_node_get_field_by_name(n, szName, &info) != GF_OK) return JS_FALSE; switch (info.fieldType) { /* inheritable floats */ case SVG_Number_datatype: case SVG_FontSize_datatype: case SVG_Length_datatype: case SVG_Coordinate_datatype: { SVG_Number *l = (SVG_Number *)info.far_ptr; if (l->type==SVG_NUMBER_AUTO || l->type==SVG_NUMBER_INHERIT) return JS_FALSE; *rval = DOUBLE_TO_JSVAL( JS_NewDouble(c, FIX2FLT(l->value) ) ); return JS_TRUE; } default: return JS_FALSE; } return JS_FALSE;}JSBool svg_udom_get_matrix_trait(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ char *szName; JSObject *mO; GF_FieldInfo info; GF_Node *n = dom_get_node(c, obj, NULL); if (!n) return JS_FALSE; if (argc!=1) return JS_FALSE; if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; szName = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); *rval = JSVAL_VOID; if (gf_node_get_field_by_name(n, szName, &info) != GF_OK) return JS_FALSE; if (info.fieldType==SVG_Transform_datatype) { GF_Matrix2D *mx = malloc(sizeof(GF_Matrix2D)); mO = JS_NewObject(c, &svg_rt->matrixClass, 0, 0); gf_mx2d_init(*mx); gf_mx2d_copy(*mx, ((SVG_Transform*)info.far_ptr)->mat); JS_SetPrivate(c, mO, mx); *rval = OBJECT_TO_JSVAL(mO); return JS_TRUE; } return JS_FALSE;}JSBool svg_udom_get_rect_trait(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSObject *newObj; char *szName; GF_FieldInfo info; GF_Node *n = dom_get_node(c, obj, NULL); if (!n) return JS_FALSE; if (argc!=1) return JS_FALSE; if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; szName = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); *rval = JSVAL_VOID; if (gf_node_get_field_by_name(n, szName, &info) != GF_OK) return JS_FALSE; if (info.fieldType==SVG_ViewBox_datatype) { rectCI *rc; SVG_ViewBox *v = (SVG_ViewBox *)info.far_ptr; newObj = JS_NewObject(c, &svg_rt->rectClass, 0, 0); GF_SAFEALLOC(rc, rectCI); rc->x = FIX2FLT(v->x); rc->y = FIX2FLT(v->y); rc->w = FIX2FLT(v->width); rc->h = FIX2FLT(v->height); JS_SetPrivate(c, newObj, rc); *rval = OBJECT_TO_JSVAL(newObj); return JS_TRUE; } return JS_FALSE;}JSBool svg_udom_get_path_trait(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ char *szName; GF_FieldInfo info; GF_Node *n = dom_get_node(c, obj, NULL); if (!n) return JS_FALSE; if (argc!=1) return JS_FALSE; if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; szName = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); *rval = JSVAL_VOID; if (gf_node_get_field_by_name(n, szName, &info) != GF_OK) return JS_FALSE; if (info.fieldType==SVG_PathData_datatype) { *rval = OBJECT_TO_JSVAL( svg_new_path_object(c, info.far_ptr) ); return JS_TRUE; } return JS_FALSE;}JSBool svg_udom_get_rgb_color_trait(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ char *szName; GF_FieldInfo info; rgbCI *rgb; JSObject *newObj; GF_Node *n = dom_get_node(c, obj, NULL); if (!n) return JS_FALSE; if (argc!=1) return JS_FALSE; if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; szName = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); *rval = JSVAL_VOID; if (gf_node_get_field_by_name(n, szName, &info) != GF_OK) return JS_FALSE; switch (info.fieldType) { case SVG_Color_datatype: { SVG_Color *col = (SVG_Color *)info.far_ptr; if (col->type == SVG_COLOR_CURRENTCOLOR) return JS_FALSE; if (col->type == SVG_COLOR_INHERIT) return JS_FALSE; newObj = JS_NewObject(c, &svg_rt->rgbClass, 0, 0); GF_SAFEALLOC(rgb, rgbCI); rgb->r = (u8) (255*FIX2FLT(col->red)) ; rgb->g = (u8) (255*FIX2FLT(col->green)) ; rgb->b = (u8) (255*FIX2FLT(col->blue)) ; JS_SetPrivate(c, newObj, rgb); *rval = OBJECT_TO_JSVAL(newObj); return JS_TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -