📄 svg_smjs.c
字号:
} return JS_FALSE;}static u32 svg_path_realloc_pts(pathCI *p, u32 nb_pts){ u32 i, orig_pts; orig_pts = 0; for (i=0; i<p->nb_coms; i++) { switch (p->tags[i]) { case 0: orig_pts++; break; case 1: orig_pts++; break; case 2: orig_pts+=3; break; case 3: orig_pts+=2; break; case 4: orig_pts+=2; break; case 5: orig_pts+=1; break; } } p->pts = realloc(p->pts, sizeof(ptCI)*(nb_pts+orig_pts)); return orig_pts;}static JSBool svg_path_move_to(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ pathCI *p; jsdouble x, y; u32 nb_pts; if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_FALSE; p = JS_GetPrivate(c, obj); if (!p) return JS_FALSE; if ((argc!=2) || !JSVAL_IS_NUMBER(argv[0]) || !JSVAL_IS_NUMBER(argv[1])) return JS_FALSE; JS_ValueToNumber(c, argv[0], &x); JS_ValueToNumber(c, argv[1], &y); nb_pts = svg_path_realloc_pts(p, 1); p->pts[nb_pts].x = (Float) x; p->pts[nb_pts].y = (Float) y; p->tags = realloc(p->tags, sizeof(u8)*(p->nb_coms+1) ); p->tags[p->nb_coms] = 0; p->nb_coms++; return JS_TRUE;}static JSBool svg_path_line_to(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ pathCI *p; jsdouble x, y; u32 nb_pts; if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_FALSE; p = JS_GetPrivate(c, obj); if (!p) return JS_FALSE; if ((argc!=2) || !JSVAL_IS_NUMBER(argv[0]) || !JSVAL_IS_NUMBER(argv[1])) return JS_FALSE; JS_ValueToNumber(c, argv[0], &x); JS_ValueToNumber(c, argv[1], &y); nb_pts = svg_path_realloc_pts(p, 1); p->pts[nb_pts].x = (Float) x; p->pts[nb_pts].y = (Float) y; p->tags = realloc(p->tags, sizeof(u8)*(p->nb_coms+1) ); p->tags[p->nb_coms] = 1; p->nb_coms++; return JS_TRUE;}static JSBool svg_path_quad_to(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ pathCI *p; jsdouble x1, y1, x2, y2; u32 nb_pts; if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_FALSE; p = JS_GetPrivate(c, obj); if (!p) return JS_FALSE; if ((argc!=4) || !JSVAL_IS_NUMBER(argv[0]) || !JSVAL_IS_NUMBER(argv[1]) || !JSVAL_IS_NUMBER(argv[2]) || !JSVAL_IS_NUMBER(argv[3])) return JS_FALSE; JS_ValueToNumber(c, argv[0], &x1); JS_ValueToNumber(c, argv[1], &y1); JS_ValueToNumber(c, argv[2], &x2); JS_ValueToNumber(c, argv[3], &y2); nb_pts = svg_path_realloc_pts(p, 2); p->pts[nb_pts].x = (Float) x1; p->pts[nb_pts].y = (Float) y1; p->pts[nb_pts+1].x = (Float) x2; p->pts[nb_pts+1].y = (Float) y2; p->tags = realloc(p->tags, sizeof(u8)*(p->nb_coms+1) ); p->tags[p->nb_coms] = 4; p->nb_coms++; return JS_TRUE;}static JSBool svg_path_curve_to(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ pathCI *p; jsdouble x1, y1, x2, y2, x, y; u32 nb_pts; if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_FALSE; p = JS_GetPrivate(c, obj); if (!p) return JS_FALSE; if ((argc!=6) || !JSVAL_IS_NUMBER(argv[0]) || !JSVAL_IS_NUMBER(argv[1]) || !JSVAL_IS_NUMBER(argv[2]) || !JSVAL_IS_NUMBER(argv[3]) || !JSVAL_IS_NUMBER(argv[4]) || !JSVAL_IS_NUMBER(argv[5])) return JS_FALSE; JS_ValueToNumber(c, argv[0], &x1); JS_ValueToNumber(c, argv[1], &y1); JS_ValueToNumber(c, argv[2], &x2); JS_ValueToNumber(c, argv[3], &y2); JS_ValueToNumber(c, argv[4], &x); JS_ValueToNumber(c, argv[5], &y); nb_pts = svg_path_realloc_pts(p, 3); p->pts[nb_pts].x = (Float) x1; p->pts[nb_pts].y = (Float) y1; p->pts[nb_pts+1].x = (Float) x2; p->pts[nb_pts+1].y = (Float) y2; p->pts[nb_pts+2].x = (Float) x; p->pts[nb_pts+2].y = (Float) y; p->tags = realloc(p->tags, sizeof(u8)*(p->nb_coms+1) ); p->tags[p->nb_coms] = 2; p->nb_coms++; return JS_TRUE;}static JSBool svg_path_close(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ pathCI *p; if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_FALSE; p = JS_GetPrivate(c, obj); if (!p) return JS_FALSE; if (argc) return JS_FALSE; p->tags = realloc(p->tags, sizeof(u8)*(p->nb_coms+1) ); p->tags[p->nb_coms] = 6; p->nb_coms++; return JS_TRUE;}static JSBool svg_mx2d_constructor(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ GF_Matrix2D *mx = malloc(sizeof(GF_Matrix2D)); gf_mx2d_init(*mx); JS_SetPrivate(c, obj, mx); *rval = OBJECT_TO_JSVAL(obj); return JS_TRUE;}static JSBool svg_mx2d_get_component(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ jsdouble *d; GF_Matrix2D *mx; if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_FALSE; mx = JS_GetPrivate(c, obj); if (!mx || (argc!=1)) return JS_FALSE; if (!JSVAL_IS_INT(argv[0])) return JS_FALSE; switch (JSVAL_TO_INT(argv[0])) { case 0: d = JS_NewDouble(c, FIX2FLT(mx->m[0])); *vp = DOUBLE_TO_JSVAL(d); return JS_TRUE; case 1: d = JS_NewDouble(c, FIX2FLT(mx->m[3])); *vp = DOUBLE_TO_JSVAL(d); return JS_TRUE; case 2: d = JS_NewDouble(c, FIX2FLT(mx->m[1])); *vp = DOUBLE_TO_JSVAL(d); return JS_TRUE; case 3: d = JS_NewDouble(c, FIX2FLT(mx->m[4])); *vp = DOUBLE_TO_JSVAL(d); return JS_TRUE; case 4: d = JS_NewDouble(c, FIX2FLT(mx->m[2])); *vp = DOUBLE_TO_JSVAL(d); return JS_TRUE; case 5: d = JS_NewDouble(c, FIX2FLT(mx->m[5])); *vp = DOUBLE_TO_JSVAL(d); return JS_TRUE; } return JS_FALSE;}static JSBool svg_mx2d_multiply(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ JSObject *mat; GF_Matrix2D *mx1, *mx2; if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_FALSE; mx1 = JS_GetPrivate(c, obj); if (!mx1 || (argc!=1)) return JS_FALSE; if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE; mat = JSVAL_TO_OBJECT(argv[0]); if (!JS_InstanceOf(c, mat, &svg_rt->matrixClass, NULL) ) return JS_FALSE; mx2 = JS_GetPrivate(c, mat); if (!mx2) return JS_FALSE; gf_mx2d_add_matrix(mx1, mx2); *vp = OBJECT_TO_JSVAL(obj); return JS_TRUE;}static JSBool svg_mx2d_inverse(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ GF_Matrix2D *mx1; if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_FALSE; mx1 = JS_GetPrivate(c, obj); if (!mx1) return JS_FALSE; gf_mx2d_inverse(mx1); *vp = OBJECT_TO_JSVAL(obj); return JS_TRUE;}static JSBool svg_mx2d_translate(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ jsdouble x, y; GF_Matrix2D *mx1; if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_FALSE; mx1 = JS_GetPrivate(c, obj); if (!mx1 || (argc!=2)) return JS_FALSE; JS_ValueToNumber(c, argv[0], &x); JS_ValueToNumber(c, argv[1], &y); gf_mx2d_add_translation(mx1, FLT2FIX(x), FLT2FIX(y)); *vp = OBJECT_TO_JSVAL(obj); return JS_TRUE;}static JSBool svg_mx2d_scale(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ jsdouble scale; GF_Matrix2D *mx1; if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_FALSE; mx1 = JS_GetPrivate(c, obj); if (!mx1 || (argc!=2)) return JS_FALSE; JS_ValueToNumber(c, argv[0], &scale); gf_mx2d_add_scale(mx1, FLT2FIX(scale), FLT2FIX(scale)); *vp = OBJECT_TO_JSVAL(obj); return JS_TRUE;}static JSBool svg_mx2d_rotate(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *vp){ jsdouble angle; GF_Matrix2D *mx1; if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_FALSE; mx1 = JS_GetPrivate(c, obj); if (!mx1 || (argc!=2)) return JS_FALSE; JS_ValueToNumber(c, argv[0], &angle); gf_mx2d_add_rotation(mx1, 0, 0, FLT2FIX(angle)); *vp = OBJECT_TO_JSVAL(obj); return JS_TRUE;}jsval svg_udom_new_rect(JSContext *c, Fixed x, Fixed y, Fixed width, Fixed height){ JSObject *r = JS_NewObject(c, &svg_rt->rectClass, 0, 0); rectCI *rc = malloc(sizeof(rectCI)); rc->x = FIX2FLT(x); rc->y = FIX2FLT(y); rc->w = FIX2FLT(width); rc->h = FIX2FLT(height); rc->sg = NULL; JS_SetPrivate(c, r, rc); return OBJECT_TO_JSVAL(r);}jsval svg_udom_new_point(JSContext *c, Fixed x, Fixed y){ JSObject *p = JS_NewObject(c, &svg_rt->pointClass, 0, 0); pointCI *pt = malloc(sizeof(pointCI)); pt->x = FIX2FLT(x); pt->y = FIX2FLT(y); pt->sg = NULL; JS_SetPrivate(c, p, pt); return OBJECT_TO_JSVAL(p);}static void svg_init_js_api(GF_SceneGraph *scene){ JS_SetContextPrivate(scene->svg_js->js_ctx, scene); JS_SetErrorReporter(scene->svg_js->js_ctx, svg_script_error); /*init global object*/ scene->svg_js->global = JS_NewObject(scene->svg_js->js_ctx, &svg_rt->globalClass, 0, 0 ); JS_InitStandardClasses(scene->svg_js->js_ctx, scene->svg_js->global); /*remember pointer to scene graph!!*/ JS_SetPrivate(scene->svg_js->js_ctx, scene->svg_js->global, scene); { JSPropertySpec globalClassProps[] = { {"connected", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY}, {"parent", 1, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY}, {0} }; JSFunctionSpec globalClassFuncs[] = { {"createConnection", svg_connection_create, 0}, {"gotoLocation", svg_nav_to_location, 1}, {"alert", svg_echo, 0}, /*technically, this is part of Implementation interface, not global, but let's try not to complicate things too much*/ {"hasFeature", dom_imp_has_feature, 2}, {0} }; JS_DefineFunctions(scene->svg_js->js_ctx, scene->svg_js->global, globalClassFuncs); JS_DefineProperties(scene->svg_js->js_ctx, scene->svg_js->global, globalClassProps); } /*initialize DOM core */ dom_js_load(scene->svg_js->js_ctx, scene->svg_js->global); /*create document object, and remember it*/ dom_js_define_document(scene->svg_js->js_ctx, scene->svg_js->global, scene); /*create event object, and remember it*/ scene->svg_js->event = dom_js_define_event(scene->svg_js->js_ctx, scene->svg_js->global); /*RGBColor class*/ { JSPropertySpec rgbClassProps[] = { {"red", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT }, {"green", 1, JSPROP_ENUMERATE | JSPROP_PERMANENT }, {"blue", 2, JSPROP_ENUMERATE | JSPROP_PERMANENT }, {0} }; JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->rgbClass, rgb_constructor, 0, rgbClassProps, 0, 0, 0); } /*SVGRect class*/ { JSPropertySpec rectClassProps[] = { {"x", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT }, {"y", 1, JSPROP_ENUMERATE | JSPROP_PERMANENT }, {"width", 2, JSPROP_ENUMERATE | JSPROP_PERMANENT }, {"height", 3, JSPROP_ENUMERATE | JSPROP_PERMANENT }, {0} }; JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->rectClass, rect_constructor, 0, rectClassProps, 0, 0, 0); } /*SVGPoint class*/ { JSPropertySpec pointClassProps[] = { {"x", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT }, {"y", 1, JSPROP_ENUMERATE | JSPROP_PERMANENT }, {0} }; JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->pointClass, point_constructor, 0, pointClassProps, 0, 0, 0); } /*SVGMatrix class*/ { JSFunctionSpec matrixClassFuncs[] = { {"getComponent", svg_mx2d_get_component, 1}, {"mMultiply", svg_mx2d_multiply, 1}, {"inverse", svg_mx2d_inverse, 0}, {"mTranslate", svg_mx2d_translate, 2}, {"mScale", svg_mx2d_scale, 1}, {"mRotate", svg_mx2d_rotate, 1}, {0} }; JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->matrixClass, svg_mx2d_constructor, 0, 0, matrixClassFuncs, 0, 0); } /*SVGPath class*/ { JSFunctionSpec pathClassFuncs[] = { {"getSegment", svg_path_get_segment, 1}, {"getSegmentParam", svg_path_get_segment_param, 2}, {"moveTo", svg_path_move_to, 2}, {"lineTo", svg_path_line_to, 2}, {"quadTo", svg_path_quad_to, 4}, {"curveTo", svg_path_curve_to, 6}, {"close", svg_path_close, 0}, {0} }; JSPropertySpec pathClassProps[] = { {"numberOfSegments", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY}, {0} }; JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->pathClass, pathCI_constructor, 0, pathClassProps, pathClassFuncs, 0, 0); }}Bool svg_script_execute(GF_SceneGraph *sg, char *utf8_script, GF_DOM_Event *event){ char szFuncName[1024]; JSBool ret; jsval rval; GF_DOM_Event *prev_event = NULL; char *sep = strchr(utf8_script, '('); if (!sep) { strcpy(szFuncName, utf8_script); strcat(szFuncName, "(evt)"); utf8_script = szFuncName; } prev_event = JS_GetPrivate(sg->svg_js->js_ctx, sg->svg_js->event); JS_SetPrivate(sg->svg_js->js_ctx, sg->svg_js->event, event); ret = JS_EvaluateScript(sg->svg_js->js_ctx, sg->svg_js->global, utf8_script, strlen(utf8_script), 0, 0, &rval); JS_SetPrivate(sg->svg_js->js_ctx, sg->svg_js->event, prev_event); /*clean-up*/ JS_GC(sg->svg_js->js_ctx); if (ret==JS_FALSE) { char *sep = strchr(utf8_script, '('); if (!sep) return 0; sep[0] = 0; JS_LookupProperty(sg->svg_js->js_ctx, sg->svg_js->global, utf8_script, &rval); sep[0] = '('; if (JSVAL_IS_VOID(rval)) return 0; } return 1;}static void svg_script_predestroy(GF_Node *n, void *eff, Bool is_destroy){ if (is_destroy) { GF_SVGJS *svg_js = n->sgprivate->scenegraph->svg_js; /*unregister script from parent scene (cf base_scenegraph::sg_reset) */ gf_list_del_item(n->sgprivate->scenegraph->scripts, n); if (svg_js->nb_scripts) { svg_js->nb_scripts--; if (!svg_js->nb_scripts) { gf_sg_ecmascript_del(svg_js->js_ctx); dom_js_unload(svg_js->js_ctx, svg_js->global); free(svg_js); n->sgprivate->scenegraph->svg_js = NULL; assert(svg_rt); svg_rt->nb_inst--; if (!svg_rt->nb_inst) { free(svg_rt); svg_rt = NULL; } } } }}static GF_Err JSScript_CreateSVGContext(GF_SceneGraph *sg){ GF_SVGJS *svg_js; GF_SAFEALLOC(svg_js, GF_SVGJS); /*create new ecmascript context*/ svg_js->js_ctx = gf_sg_ecmascript_new(); if (!svg_js->js_ctx) { free(svg_js); return GF_SCRIPT_ERROR; } if (!svg_rt) { GF_SAFEALLOC(svg_rt, GF_SVGuDOM); uDOM_SETUP_CLASS(svg_rt->globalClass, "global", JSCLASS_HAS_PRIVATE, global_getProperty, JS_PropertyStub, JS_FinalizeStub); uDOM_SETUP_CLASS(svg_rt->rgbClass, "SVGRGBColor", JSCLASS_HAS_PRIVATE, rgb_getProperty, rgb_setProperty, baseCI_finalize); uDOM_SETUP_CLASS(svg_rt->rectClass, "SVGRect", JSCLASS_HAS_PRIVATE, rect_getProperty, rect_setProperty, baseCI_finalize); uDOM_SETUP_CLASS(svg_rt->pointClass, "SVGPoint", JSCLASS_HAS_PRIVATE, point_getProperty, point_setProperty, baseCI_finalize); uDOM_SETUP_CLASS(svg_rt->matrixClass, "SVGMatrix", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, baseCI_finalize); uDOM_SETUP_CLASS(svg_rt->pathClass, "SVGPath", JSCLASS_HAS_PRIVATE, path_getProperty, JS_PropertyStub, pathCI_finalize); } svg_rt->nb_inst++; svg_js->script_execute = svg_script_execute; svg_js->handler_execute = svg_script_execute_handler; sg->svg_js = svg_js; /*load SVG & DOM APIs*/ svg_init_js_api(sg); return GF_OK;}GF_DOMText *svg_get_text_child(GF_Node *node){ GF_ChildNodeItem *child; GF_DOMText *txt; txt = NULL; child = ((SVG_Element*)node)->children; if (! child) return NULL; while (child) { txt = (GF_DOMText*)child->node; if ((txt->sgprivate->tag==TAG_DOMText) && txt->textContent) return txt; txt = NULL; child = child->next; } return NULL;}void JSScript_LoadSVG(GF_Node *node){ GF_DOMText *txt; GF_SVGJS *svg_js; JSBool ret; jsval rval; txt = svg_get_text_child(node); if (!txt) return; if (!node->sgprivate->scenegraph->svg_js) { if (JSScript_CreateSVGContext(node->sgprivate->scenegraph) != GF_OK) return; } /*register script width parent scene (cf base_scenegraph::sg_reset) */ gf_list_add(node->sgprivate->scenegraph->scripts, node); svg_js = node->sgprivate->scenegraph->svg_js; if (!node->sgprivate->UserCallback) { svg_js->nb_scripts++; node->sgprivate->UserCallback = svg_script_predestroy; } if (node->sgprivate->tag == TAG_SVG_handler) return; ret = JS_EvaluateScript(svg_js->js_ctx, svg_js->global, txt->textContent, strlen(txt->textContent), 0, 0, &rval); if (ret==JS_FALSE) { _ScriptMessage(node->sgprivate->scenegraph, GF_SCRIPT_ERROR, "SVG: Invalid script"); return; } return;}Bool svg_script_execute_handler(GF_Node *node, GF_DOM_Event *event){ GF_DOMText *txt; GF_SVGJS *svg_js; JSBool ret = JS_FALSE; GF_DOM_Event *prev_event = NULL; jsval fval, rval; txt = svg_get_text_child(node); if (!txt) return 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[DOM Events] Executing script code from handler\n")); svg_js = node->sgprivate->scenegraph->svg_js; prev_event = JS_GetPrivate(svg_js->js_ctx, svg_js->event); JS_SetPrivate(svg_js->js_ctx, svg_js->event, event); if (JS_LookupProperty(svg_js->js_ctx, svg_js->global, txt->textContent, &fval) && !JSVAL_IS_VOID(fval) ) { if (svg_script_execute(node->sgprivate->scenegraph, txt->textContent, event)) ret = JS_TRUE; } else { ret = JS_EvaluateScript(svg_js->js_ctx, svg_js->global, txt->textContent, strlen(txt->textContent), 0, 0, &rval); } JS_SetPrivate(svg_js->js_ctx, svg_js->event, prev_event); if (ret==JS_FALSE) { _ScriptMessage(node->sgprivate->scenegraph, GF_SCRIPT_ERROR, "SVG: Invalid handler textContent"); return 0; } return 1;}#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -