summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorPaul Gardiner <paul@glidos.net>2012-05-07 10:32:23 +0100
committerPaul Gardiner <paul@glidos.net>2012-05-08 15:13:44 +0100
commit0b8667c0c3c85bf497b554bfa64375a13527cd1c (patch)
treeb44abc3b059b7e3c4762d07f924ae396535a664e /pdf
parente86dfd0a75186f7bfaceb3bc4d89434d0f00b360 (diff)
downloadmupdf-0b8667c0c3c85bf497b554bfa64375a13527cd1c.tar.xz
JavaScript: add v8 implementation
Diffstat (limited to 'pdf')
-rw-r--r--pdf/mupdf-internal.h5
-rw-r--r--pdf/pdf_js.c42
-rw-r--r--pdf/pdf_jsimp.c11
-rw-r--r--pdf/pdf_jsimp_v8.cpp253
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