diff options
author | Paul Gardiner <paul@glidos.net> | 2012-05-07 10:32:23 +0100 |
---|---|---|
committer | Paul Gardiner <paul@glidos.net> | 2012-05-08 15:13:44 +0100 |
commit | 0b8667c0c3c85bf497b554bfa64375a13527cd1c (patch) | |
tree | b44abc3b059b7e3c4762d07f924ae396535a664e /pdf | |
parent | e86dfd0a75186f7bfaceb3bc4d89434d0f00b360 (diff) | |
download | mupdf-0b8667c0c3c85bf497b554bfa64375a13527cd1c.tar.xz |
JavaScript: add v8 implementation
Diffstat (limited to 'pdf')
-rw-r--r-- | pdf/mupdf-internal.h | 5 | ||||
-rw-r--r-- | pdf/pdf_js.c | 42 | ||||
-rw-r--r-- | pdf/pdf_jsimp.c | 11 | ||||
-rw-r--r-- | pdf/pdf_jsimp_v8.cpp | 253 |
4 files changed, 304 insertions, 7 deletions
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h index 3c233f34..4217be48 100644 --- a/pdf/mupdf-internal.h +++ b/pdf/mupdf-internal.h @@ -573,6 +573,7 @@ void pdf_remove_item(fz_context *ctx, fz_store_free_fn *free, pdf_obj *key); pdf_js *pdf_new_js(pdf_document *doc); void pdf_drop_js(pdf_js *js); void pdf_js_execute(pdf_js *js, char *code); +void pdf_js_execute_count(pdf_js *js, char *code, int count); /* * Javascript engine interface @@ -593,15 +594,15 @@ pdf_jsimp_type *pdf_jsimp_new_type(pdf_jsimp *imp, pdf_jsimp_dtr *dtr); void pdf_jsimp_drop_type(pdf_jsimp *imp, pdf_jsimp_type *type); void pdf_jsimp_addmethod(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth); void pdf_jsimp_addproperty(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set); +void pdf_jsimp_set_global_type(pdf_jsimp *imp, pdf_jsimp_type *type); pdf_jsimp_obj *pdf_jsimp_new_obj(pdf_jsimp *imp, pdf_jsimp_type *type, void *obj); void pdf_jsimp_drop_obj(pdf_jsimp *imp, pdf_jsimp_obj *obj); -void pdf_jsimp_set_this(pdf_jsimp *imp, pdf_jsimp_obj *obj); - pdf_jsimp_obj *pdf_jsimp_fromString(pdf_jsimp *imp, char *str); char *pdf_jsimp_toString(pdf_jsimp *imp, pdf_jsimp_obj *obj); void pdf_jsimp_execute(pdf_jsimp *imp, char *code); +void pdf_jsimp_execute_count(pdf_jsimp *imp, char *code, int count); #endif diff --git a/pdf/pdf_js.c b/pdf/pdf_js.c index 10e2b66e..49771421 100644 --- a/pdf/pdf_js.c +++ b/pdf/pdf_js.c @@ -66,20 +66,23 @@ static void declare_dom(pdf_js *js) js->fieldtype = pdf_jsimp_new_type(imp, NULL); pdf_jsimp_addproperty(imp, js->fieldtype, "value", field_getValue, field_setValue); - /* Create the document object and tell the engine to use - * it as "this" */ - js->jsdoc = pdf_jsimp_new_obj(imp, js->doctype, NULL); - pdf_jsimp_set_this(js->imp, js->jsdoc); + /* Create the document object and tell the engine to use */ + pdf_jsimp_set_global_type(js->imp, js->doctype); } pdf_js *pdf_new_js(pdf_document *doc) { fz_context *ctx = doc->ctx; pdf_js *js = NULL; + pdf_obj *javascript = NULL; + fz_buffer *fzbuf = NULL; fz_var(js); + fz_var(javascript); + fz_var(fzbuf); fz_try(ctx) { + int len, i; pdf_obj *root, *acroform; js = fz_malloc_struct(ctx, pdf_js); js->doc = doc; @@ -94,6 +97,32 @@ pdf_js *pdf_new_js(pdf_document *doc) * pass our js context, for it to pass back to us. */ js->imp = pdf_new_jsimp(ctx, js); declare_dom(js); + + javascript = pdf_load_name_tree(doc, "JavaScript"); + len = pdf_dict_len(javascript); + + for (i = 0; i < len; i++) + { + pdf_obj *fragment = pdf_dict_get_val(javascript, i); + pdf_obj *code = pdf_dict_gets(fragment, "JS"); + + if (pdf_is_stream(doc, pdf_to_num(code), pdf_to_gen(code))) + { + unsigned char *buf; + int len; + + fzbuf = pdf_load_stream(doc, pdf_to_num(code), pdf_to_gen(code)); + len = fz_buffer_storage(ctx, fzbuf, &buf); + pdf_jsimp_execute_count(js->imp, buf, len); + fz_drop_buffer(ctx, fzbuf); + fzbuf = NULL; + } + } + } + fz_always(ctx) + { + fz_drop_buffer(ctx, fzbuf); + pdf_drop_obj(javascript); } fz_catch(ctx) { @@ -119,4 +148,9 @@ void pdf_drop_js(pdf_js *js) void pdf_js_execute(pdf_js *js, char *code) { pdf_jsimp_execute(js->imp, code); +} + +void pdf_js_execute_count(pdf_js *js, char *code, int count) +{ + pdf_jsimp_execute_count(js->imp, code, count); }
\ No newline at end of file diff --git a/pdf/pdf_jsimp.c b/pdf/pdf_jsimp.c index afaf05dc..e3433ee8 100644 --- a/pdf/pdf_jsimp.c +++ b/pdf/pdf_jsimp.c @@ -260,6 +260,11 @@ void pdf_jsimp_addproperty(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf } } +void pdf_jsimp_set_global_type(pdf_jsimp *imp, pdf_jsimp_type *type) +{ + imp->jsthis = pdf_jsimp_new_obj(imp, type, NULL); +} + pdf_jsimp_obj *pdf_jsimp_new_obj(pdf_jsimp *imp, pdf_jsimp_type *type, void *natobj) { pdf_jsimp_obj *obj = fz_malloc_struct(imp->ctx, pdf_jsimp_obj); @@ -396,4 +401,8 @@ void pdf_jsimp_execute(pdf_jsimp *imp, char *code) update_result(imp); assign_display_value(imp, imp->accum); } -}
\ No newline at end of file +} + +void pdf_jsimp_execute_count(pdf_jsimp *imp, char *code, int count) +{ +} diff --git a/pdf/pdf_jsimp_v8.cpp b/pdf/pdf_jsimp_v8.cpp new file mode 100644 index 00000000..158fe63c --- /dev/null +++ b/pdf/pdf_jsimp_v8.cpp @@ -0,0 +1,253 @@ +/* + * This is a dummy JavaScript engine. It cheats by recognising the specific + * strings in calc.pdf, and hence will work only for that file. It is for + * testing only. + */ + +extern "C" { +#include "fitz-internal.h" +#include "mupdf-internal.h" +} + +#include <v8.h> + +using namespace v8; + + +struct PDFJSImp +{ + fz_context *ctx; + void *jsctx; + Persistent<Context> context; + + PDFJSImp(fz_context *ctx, void *jsctx) : ctx(ctx), jsctx(jsctx) + { + HandleScope scope; + context = Persistent<Context>::New(Context::New()); + } + + ~PDFJSImp() + { + context.Dispose(); + } +}; + +/* We need only a couple of specific methods for calc.pdf */ +struct PDFJSImpType +{ + PDFJSImp *imp; + Persistent<ObjectTemplate> templ; + pdf_jsimp_dtr *dtr; + + PDFJSImpType(PDFJSImp *imp, pdf_jsimp_dtr *dtr): imp(imp), dtr(dtr) + { + HandleScope scope; + templ = Persistent<ObjectTemplate>::New(ObjectTemplate::New()); + templ->SetInternalFieldCount(1); + } + + ~PDFJSImpType() + { + templ.Dispose(); + } +}; + +struct PDFJSImpMethod +{ + void *jsctx; + pdf_jsimp_method *meth; + + PDFJSImpMethod(void *jsctx, pdf_jsimp_method *meth) : jsctx(jsctx), meth(meth) {} +}; + +struct PDFJSImpProperty +{ + void *jsctx; + pdf_jsimp_getter *get; + pdf_jsimp_setter *set; + + PDFJSImpProperty(void *jsctx, pdf_jsimp_getter *get, pdf_jsimp_setter *set) : jsctx(jsctx), get(get), set(set) {} +}; + +class PDFJSImpObject +{ + Persistent<Value> pobj; + String::Utf8Value *utf8; + +public: + PDFJSImpObject(Handle<Value> obj) + { + pobj = Persistent<Value>::New(obj); + utf8 = NULL; + } + + PDFJSImpObject(const char *str) + { + pobj = Persistent<Value>::New(String::New(str)); + utf8 = NULL; + } + + ~PDFJSImpObject() + { + delete utf8; + pobj.Dispose(); + } + + char *toString() + { + delete utf8; + utf8 = new String::Utf8Value(pobj); + return **utf8; + } + + Handle<Value> toValue() + { + return pobj; + } +}; + + +extern "C" pdf_jsimp *pdf_new_jsimp(fz_context *ctx, void *jsctx) +{ + return reinterpret_cast<pdf_jsimp *>(new PDFJSImp(ctx, jsctx)); +} + +extern "C" void pdf_drop_jsimp(pdf_jsimp *imp) +{ + delete reinterpret_cast<PDFJSImp *>(imp); +} + +extern "C" pdf_jsimp_type *pdf_jsimp_new_type(pdf_jsimp *imp, pdf_jsimp_dtr *dtr) +{ + return reinterpret_cast<pdf_jsimp_type *>(new PDFJSImpType((PDFJSImp *)imp, dtr)); +} + +extern "C" void pdf_jsimp_drop_type(pdf_jsimp *imp, pdf_jsimp_type *type) +{ + delete reinterpret_cast<PDFJSImpType *>(type); +} + +static Handle<Value> callMethod(const Arguments &args) +{ + HandleScope scope; + Local<Object> self = args.Holder(); + Local<External> owrap; + void *nself = NULL; + Local<External> mwrap = Local<External>::Cast(args.Data()); + PDFJSImpMethod *m = (PDFJSImpMethod *)mwrap->Value(); + int c = args.Length(); + PDFJSImpObject **native_args = new PDFJSImpObject*[c]; + + if (self->InternalFieldCount() > 0) + { + owrap = Local<External>::Cast(self->GetInternalField(0)); + nself = owrap->Value(); + } + + for (int i = 0; i < c; i++) + native_args[i] = new PDFJSImpObject(args[i]); + + PDFJSImpObject *obj = reinterpret_cast<PDFJSImpObject *>(m->meth(m->jsctx, nself, c, reinterpret_cast<pdf_jsimp_obj **>(native_args))); + Handle<Value> val = obj->toValue(); + delete obj; + + for (int i = 0; i < c; i++) + delete native_args[i]; + + delete native_args; + + return scope.Close(val); +} + +extern "C" void pdf_jsimp_addmethod(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth) +{ + PDFJSImpType *vType = reinterpret_cast<PDFJSImpType *>(type); + HandleScope scope; + + vType->templ->Set(String::New(name), FunctionTemplate::New(callMethod, External::New(new PDFJSImpMethod(vType->imp->jsctx, meth)))); +} + +static Handle<Value> getProp(Local<String> property, const AccessorInfo &info) +{ + HandleScope scope; + Local<Object> self = info.Holder(); + Local<External> owrap = Local<External>::Cast(self->GetInternalField(0)); + Local<External> pwrap = Local<External>::Cast(info.Data()); + PDFJSImpProperty *p = reinterpret_cast<PDFJSImpProperty *>(pwrap->Value()); + + PDFJSImpObject *obj = reinterpret_cast<PDFJSImpObject *>(p->get(p->jsctx, owrap->Value())); + Handle<Value> val = obj->toValue(); + delete obj; + return scope.Close(val); +} + +static void setProp(Local<String> property, Local<Value> value, const AccessorInfo &info) +{ + HandleScope scope; + Local<Object> self = info.Holder(); + Local<External> owrap = Local<External>::Cast(self->GetInternalField(0)); + Local<External> wrap = Local<External>::Cast(info.Data()); + PDFJSImpProperty *p = reinterpret_cast<PDFJSImpProperty *>(wrap->Value()); + PDFJSImpObject *obj = new PDFJSImpObject(value); + + p->set(p->jsctx, owrap->Value(), reinterpret_cast<pdf_jsimp_obj *>(obj)); + delete obj; +} + +extern "C" void pdf_jsimp_addproperty(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set) +{ + PDFJSImpType *vType = reinterpret_cast<PDFJSImpType *>(type); + HandleScope scope; + + vType->templ->SetAccessor(String::New(name), getProp, setProp, External::New(new PDFJSImpProperty(vType->imp->jsctx, get, set))); +} + +extern "C" void pdf_jsimp_set_global_type(pdf_jsimp *imp, pdf_jsimp_type *type) +{ + PDFJSImp *vImp = reinterpret_cast<PDFJSImp *>(imp); + PDFJSImpType *vType = reinterpret_cast<PDFJSImpType *>(type); + HandleScope scope; + + vImp->context = Persistent<Context>::New(Context::New(NULL, vType->templ)); +} + +extern "C" pdf_jsimp_obj *pdf_jsimp_new_obj(pdf_jsimp *imp, pdf_jsimp_type *type, void *natobj) +{ + PDFJSImpType *vType = reinterpret_cast<PDFJSImpType *>(type); + HandleScope scope; + Local<Object> obj = vType->templ->NewInstance(); + obj->SetInternalField(0, External::New(natobj)); + + return reinterpret_cast<pdf_jsimp_obj *>(new PDFJSImpObject(obj)); +} + +extern "C" void pdf_jsimp_drop_obj(pdf_jsimp *imp, pdf_jsimp_obj *obj) +{ + delete reinterpret_cast<PDFJSImpObject *>(obj); +} + +extern "C" pdf_jsimp_obj *pdf_jsimp_fromString(pdf_jsimp *imp, char *str) +{ + return reinterpret_cast<pdf_jsimp_obj *>(new PDFJSImpObject(str)); +} + +extern "C" char *pdf_jsimp_toString(pdf_jsimp *imp, pdf_jsimp_obj *obj) +{ + return reinterpret_cast<PDFJSImpObject *>(obj)->toString(); +} + +extern "C" void pdf_jsimp_execute(pdf_jsimp *imp, char *code) +{ + PDFJSImp *vImp = reinterpret_cast<PDFJSImp *>(imp); + HandleScope scope; + Context::Scope context_scope(vImp->context); + Script::Compile(String::New(code))->Run(); +} + +extern "C" void pdf_jsimp_execute_count(pdf_jsimp *imp, char *code, int count) +{ + PDFJSImp *vImp = reinterpret_cast<PDFJSImp *>(imp); + HandleScope scope; + Context::Scope context_scope(vImp->context); + Script::Compile(String::New(code, count))->Run(); +}
\ No newline at end of file |