diff options
author | Paul Gardiner <paul@glidos.net> | 2012-04-19 16:27:53 +0100 |
---|---|---|
committer | Paul Gardiner <paul@glidos.net> | 2012-05-08 15:12:37 +0100 |
commit | 08a925d3ff7e703e1752dbdcd0f1188ec9cee8d0 (patch) | |
tree | 905e2bc90d26fae02ad1aeb1048a0f44bbdc6e29 /pdf | |
parent | 9ebe09595ad8088f518b6397e791aa44c27a374f (diff) | |
download | mupdf-08a925d3ff7e703e1752dbdcd0f1188ec9cee8d0.tar.xz |
Implement dummy JavaScript engine just for the sake of viewing calc.pdf
Diffstat (limited to 'pdf')
-rw-r--r-- | pdf/mupdf-internal.h | 8 | ||||
-rw-r--r-- | pdf/pdf_form.c | 22 | ||||
-rw-r--r-- | pdf/pdf_js.c | 7 | ||||
-rw-r--r-- | pdf/pdf_jsimp.c | 294 | ||||
-rw-r--r-- | pdf/pdf_xref.c | 2 |
5 files changed, 321 insertions, 12 deletions
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h index d0617769..8ffb81f1 100644 --- a/pdf/mupdf-internal.h +++ b/pdf/mupdf-internal.h @@ -568,11 +568,15 @@ void *pdf_find_item(fz_context *ctx, fz_store_free_fn *free, pdf_obj *key); void pdf_remove_item(fz_context *ctx, fz_store_free_fn *free, pdf_obj *key); /* - * Javascript engine interface + * Javascript handler */ pdf_js *pdf_new_js(pdf_document *doc); void pdf_drop_js(pdf_js *js); +void pdf_js_execute(pdf_js *js, char *code); +/* + * Javascript engine interface + */ typedef struct pdf_jsimp_s pdf_jsimp; typedef struct pdf_jsimp_type_s pdf_jsimp_type; typedef struct pdf_jsimp_obj_s pdf_jsimp_obj; @@ -596,4 +600,6 @@ 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); + #endif diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c index d1bc7576..31e1ce49 100644 --- a/pdf/pdf_form.c +++ b/pdf/pdf_form.c @@ -580,6 +580,26 @@ void pdf_synthesize_missing_appearance(pdf_document *doc, pdf_obj *obj) } } +static void execute_action(pdf_document *doc, pdf_obj *obj) +{ + pdf_obj *a; + + a = pdf_dict_gets(obj, "A"); + while (a) + { + char *type = pdf_to_name(pdf_dict_gets(a, "S")); + + if (!strcmp(type, "JavaScript")) + { + pdf_obj *js = pdf_dict_gets(a, "JS"); + if (js) + pdf_js_execute(doc->js, pdf_to_str_buf(js)); + } + + a = pdf_dict_gets(a, "Next"); + } +} + static void toggle_check_box(pdf_document *doc, pdf_obj *obj) { pdf_obj *as; @@ -673,6 +693,8 @@ int pdf_pass_event(pdf_document *doc, pdf_page *page, fz_ui_event *ui_event) changed = 1; break; } + + execute_action(doc, annot->obj); } break; } diff --git a/pdf/pdf_js.c b/pdf/pdf_js.c index 4c2e30ab..408f7bf2 100644 --- a/pdf/pdf_js.c +++ b/pdf/pdf_js.c @@ -46,7 +46,7 @@ static pdf_jsimp_obj *doc_getField(void *jsctx, void *obj, int argc, pdf_jsimp_o pdf_obj *t; field = pdf_array_get(js->form, i); t = pdf_dict_gets(field, "T"); - if (!strcmp(name, pdf_to_name(t))) + if (!strcmp(name, pdf_to_str_buf(t))) break; } @@ -111,4 +111,9 @@ void pdf_drop_js(pdf_js *js) pdf_drop_jsimp(js->imp); fz_free(ctx, js); } +} + +void pdf_js_execute(pdf_js *js, char *code) +{ + pdf_jsimp_execute(js->imp, code); }
\ No newline at end of file diff --git a/pdf/pdf_jsimp.c b/pdf/pdf_jsimp.c index 080b1df4..c0a11c58 100644 --- a/pdf/pdf_jsimp.c +++ b/pdf/pdf_jsimp.c @@ -1,59 +1,335 @@ +/* + * 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. + */ + + #include "fitz-internal.h" #include "mupdf-internal.h" +enum +{ + FUNC_NONE, + FUNC_PLUS, + FUNC_MINUS, + FUNC_MULT, + FUNC_DIV +}; + struct pdf_jsimp_s { - int x; + fz_context *ctx; + void *jsctx; + double accum; + double entry; + double multiplier; + double divisor; + int func; + pdf_jsimp_obj *jsthis; + pdf_jsimp_obj *display; + pdf_jsimp_obj *funcfield; }; +/* We need only a couple of specific methods for calc.pdf */ struct pdf_jsimp_type_s { - int x; + pdf_jsimp_dtr *dtr; + pdf_jsimp_method *getField; + pdf_jsimp_getter *getValue; + pdf_jsimp_setter *setValue; }; struct pdf_jsimp_obj_s { - int x; + pdf_jsimp_type *type; + void *obj; }; +static double digit_button(pdf_jsimp *imp, int digit) +{ + imp->entry = imp->entry * imp->multiplier + digit / imp->divisor; + + if (imp->divisor >= 10) + { + imp->divisor = imp->divisor * 10; + } + else + { + imp->multiplier = 10; + } + + return imp->entry; +} + +static void assign_display_value(pdf_jsimp *imp, double val) +{ + char valstr[256]; + pdf_jsimp_obj *valobj; + + if (imp->display == NULL) + { + pdf_jsimp_obj *str_arg = pdf_jsimp_fromString(imp, "Display"); + pdf_jsimp_obj *doc = imp->jsthis; + imp->display = doc->type->getField(imp->jsctx, doc->obj, 1, &str_arg); + } + + snprintf(valstr, sizeof(valstr), "%f", val); + if (imp->display && imp->display->type->setValue) + { + valobj = pdf_jsimp_fromString(imp, valstr); + imp->display->type->setValue(imp->jsctx, imp->display->obj, valobj); + } +} + +static void assign_func_value(pdf_jsimp *imp, int val) +{ + pdf_jsimp_obj *valobj = NULL; + + if (imp->funcfield == NULL) + { + pdf_jsimp_obj *str_arg = pdf_jsimp_fromString(imp, "Func"); + pdf_jsimp_obj *doc = imp->jsthis; + imp->funcfield = doc->type->getField(imp->jsctx, doc->obj, 1, &str_arg); + } + + if (imp->funcfield && imp->funcfield->type->setValue) + { + switch(val) + { + case FUNC_NONE: + valobj = pdf_jsimp_fromString(imp, ""); + break; + case FUNC_MULT: + valobj = pdf_jsimp_fromString(imp, "MULT"); + break; + case FUNC_DIV: + valobj = pdf_jsimp_fromString(imp, "DIV"); + break; + case FUNC_PLUS: + valobj = pdf_jsimp_fromString(imp, "PLUS"); + break; + case FUNC_MINUS: + valobj = pdf_jsimp_fromString(imp, "MINUS"); + break; + } + + if (valobj) + imp->funcfield->type->setValue(imp->jsctx, imp->funcfield->obj, valobj); + } +} + +static void clear_entry(pdf_jsimp *imp) +{ + imp->entry = 0; + imp->multiplier = 1; + imp->divisor = 1; +} + +static void update_result(pdf_jsimp *imp) +{ + switch(imp->func) + { + case FUNC_PLUS: + imp->accum = imp->accum + imp->entry; + break; + case FUNC_MINUS: + imp->accum = imp->accum - imp->entry; + break; + case FUNC_MULT: + imp->accum = imp->accum * imp->entry; + break; + case FUNC_DIV: + if (imp->entry != 0) + imp->accum = imp->accum / imp->entry; + break; + } + + imp->func = FUNC_NONE; + assign_func_value(imp, FUNC_NONE); + clear_entry(imp); +} + +static void func_button(pdf_jsimp *imp, int func) +{ + if (imp->func != FUNC_NONE) + { + update_result(imp); + } + else + { + if (imp->entry != 0) + imp->accum = imp->entry; + + imp->func = func; + assign_func_value(imp, func); + clear_entry(imp); + } +} + +static void all_cancel(pdf_jsimp *imp) +{ + clear_entry(imp); + assign_display_value(imp, 0); + imp->accum = 0; + assign_func_value(imp, FUNC_NONE); +} + pdf_jsimp *pdf_new_jsimp(fz_context *ctx, void *jsctx) { - return NULL; + pdf_jsimp *imp = fz_malloc_struct(ctx, pdf_jsimp); + + imp->ctx = ctx; + imp->jsctx = jsctx; + imp->accum = 0; + imp->entry = 0; + imp->divisor = 1; + imp->multiplier = 1; + + return imp; } void pdf_drop_jsimp(pdf_jsimp *imp) { + if (imp) + { + fz_free(imp->ctx, imp); + } } pdf_jsimp_type *pdf_jsimp_new_type(pdf_jsimp *imp, pdf_jsimp_dtr *dtr) { - return NULL; + pdf_jsimp_type *type = fz_malloc_struct(imp->ctx, pdf_jsimp_type); + type->dtr = dtr; + + return type; } void pdf_jsimp_addmethod(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth) { + if (!strcmp(name, "getField")) + { + type->getField = meth; + } } void pdf_jsimp_addproperty(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set) { + if (!strcmp(name, "value")) + { + type->getValue = get; + type->setValue = set; + } } -pdf_jsimp_obj *pdf_jsimp_new_obj(pdf_jsimp *imp, pdf_jsimp_type *type, void *obj) +pdf_jsimp_obj *pdf_jsimp_new_obj(pdf_jsimp *imp, pdf_jsimp_type *type, void *natobj) { - return NULL; + pdf_jsimp_obj *obj = fz_malloc_struct(imp->ctx, pdf_jsimp_obj); + obj->type = type; + obj->obj = natobj; + + return obj; } void pdf_jsimp_set_this(pdf_jsimp *imp, pdf_jsimp_obj *obj) { + imp->jsthis = obj; } + pdf_jsimp_obj *pdf_jsimp_fromString(pdf_jsimp *imp, char *str) { - return NULL; + /* Represent a string object as a pdf_jsimp_obj with a NULL type */ + pdf_jsimp_obj *obj = fz_malloc_struct(imp->ctx, pdf_jsimp_obj); + obj->obj = fz_strdup(imp->ctx, str); + + return obj; } char *pdf_jsimp_toString(pdf_jsimp *imp, pdf_jsimp_obj *obj) { - return NULL; + return (char *)(obj->type ? NULL : obj->obj); +} + +void pdf_jsimp_execute(pdf_jsimp *imp, char *code) +{ + if (!strcmp(code, "display.value = digit_button(0);")) + { + assign_display_value(imp, digit_button(imp, 0)); + } + else if (!strcmp(code, "display.value = digit_button(1);\r")) + { + assign_display_value(imp, digit_button(imp, 1)); + } + else if (!strcmp(code, "display.value = digit_button(2)")) + { + assign_display_value(imp, digit_button(imp, 2)); + } + else if (!strcmp(code, "display.value = digit_button(3)")) + { + assign_display_value(imp, digit_button(imp, 3)); + } + else if (!strcmp(code, "display.value = digit_button(4)")) + { + assign_display_value(imp, digit_button(imp, 4)); + } + else if (!strcmp(code, "display.value = digit_button(5)")) + { + assign_display_value(imp, digit_button(imp, 5)); + } + else if (!strcmp(code, "display.value = digit_button(6);")) + { + assign_display_value(imp, digit_button(imp, 6)); + } + else if (!strcmp(code, "display.value = digit_button(7);")) + { + assign_display_value(imp, digit_button(imp, 7)); + } + else if (!strcmp(code, "display.value = digit_button(8);")) + { + assign_display_value(imp, digit_button(imp, 8)); + } + else if (!strcmp(code, "display.value = digit_button(9);")) + { + assign_display_value(imp, digit_button(imp, 9)); + } + else if (!strcmp(code, "if (divisor == 1) {\r divisor = 10;\r multiplier = 1;\r }")) + { + if (imp->divisor == 1) + { + imp->divisor = 10; + imp->multiplier = 1; + } + } + else if (!strcmp(code, "all_cancel();")) + { + all_cancel(imp); + } + else if (!strcmp(code, "clear_entry();\rdisplay.value = 0;")) + { + clear_entry(imp); + assign_display_value(imp, 0); + } + else if (!strcmp(code, "func_button(\"MULT\");")) + { + func_button(imp, FUNC_MULT); + } + else if (!strcmp(code, "func_button(\"DIV\");")) + { + func_button(imp, FUNC_DIV); + } + else if (!strcmp(code, "func_button(\"PLUS\");")) + { + func_button(imp, FUNC_PLUS); + } + else if (!strcmp(code, "func_button(\"MINUS\");")) + { + func_button(imp, FUNC_MINUS); + } + else if (!strcmp(code, "update_result();\rdisplay.value = accum;")) + { + update_result(imp); + assign_display_value(imp, imp->accum); + } }
\ No newline at end of file diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c index e73ce72a..82407b80 100644 --- a/pdf/pdf_xref.c +++ b/pdf/pdf_xref.c @@ -690,8 +690,8 @@ pdf_open_document_with_stream(fz_stream *file) fz_try(ctx) { - xref->js = pdf_new_js(xref); pdf_load_xref(xref, &xref->lexbuf.base); + xref->js = pdf_new_js(xref); } fz_catch(ctx) { |