summaryrefslogtreecommitdiff
path: root/pdf/pdf_form.c
diff options
context:
space:
mode:
authorPaul Gardiner <paul@glidos.net>2012-05-28 13:51:30 +0100
committerPaul Gardiner <paul@glidos.net>2012-05-28 13:51:30 +0100
commit741fe4a4d7bbd6ee914504be7e85356a741601c4 (patch)
treec25f6f4ea0d06c97fe4b021571a7a897eef856f5 /pdf/pdf_form.c
parentfa5ee3a96cb4cb184cf6cc807a67632666b936bf (diff)
downloadmupdf-741fe4a4d7bbd6ee914504be7e85356a741601c4.tar.xz
Forms: implement JavaScript Field methods setFillColor and setTextColor
Diffstat (limited to 'pdf/pdf_form.c')
-rw-r--r--pdf/pdf_form.c186
1 files changed, 175 insertions, 11 deletions
diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c
index 177eb9e7..92eda83f 100644
--- a/pdf/pdf_form.c
+++ b/pdf/pdf_form.c
@@ -42,6 +42,16 @@ struct fz_widget_text_s
char *text;
};
+typedef struct da_parse_state_s
+{
+ char *name;
+ float stack[32];
+ int top;
+ char *font_name;
+ int font_size;
+ float col[4];
+ int col_size;
+} da_parse_state;
static const char *fmt_re = "%f %f %f %f re\n";
static const char *fmt_f = "f\n";
@@ -191,18 +201,21 @@ static int get_field_type(pdf_document *doc, pdf_obj *obj)
static void pdf_field_mark_dirty(fz_context *ctx, pdf_obj *field)
{
- pdf_obj *nullobj = pdf_new_null(ctx);
- fz_try(ctx)
- {
- pdf_dict_puts(field, "Dirty", nullobj);
- }
- fz_always(ctx)
- {
- pdf_drop_obj(nullobj);
- }
- fz_catch(ctx)
+ if (!pdf_dict_gets(field, "Dirty"))
{
- fz_rethrow(ctx);
+ pdf_obj *nullobj = pdf_new_null(ctx);
+ fz_try(ctx)
+ {
+ pdf_dict_puts(field, "Dirty", nullobj);
+ }
+ fz_always(ctx)
+ {
+ pdf_drop_obj(nullobj);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
}
}
@@ -292,6 +305,110 @@ static int read_font_size_from_da(fz_context *ctx, char *da)
return fontsize;
}
+static void da_init(fz_context *ctx, da_parse_state *da_state)
+{
+ da_state->name = NULL;
+ da_state->top = 0;
+ da_state->font_name = NULL;
+ da_state->font_size = 0;
+ da_state->col_size = 0;
+}
+
+static void da_fin(fz_context *ctx, da_parse_state *da_state)
+{
+ fz_free(ctx, da_state->name);
+ da_state->name = NULL;
+ fz_free(ctx, da_state->font_name);
+ da_state->font_name = NULL;
+}
+
+static void da_reset(fz_context *ctx, da_parse_state *da_state)
+{
+ fz_free(ctx, da_state->name);
+ da_state->name = NULL;
+ da_state->top = 0;
+}
+
+static void da_check_stack(da_parse_state *da_state)
+{
+ if (da_state->top == 32)
+ {
+ memmove(da_state->stack, da_state->stack + 1,
+ 31 * sizeof(da_state->stack[0]));
+ da_state->top = 31;
+ }
+}
+
+static void parse_da(fz_context *ctx, char *da, da_parse_state *da_state)
+{
+ int tok;
+ pdf_lexbuf lbuf;
+ fz_stream *str = fz_open_memory(ctx, da, strlen(da));
+
+ memset(lbuf.scratch, 0, sizeof(lbuf.scratch));
+ lbuf.size = sizeof(lbuf.scratch);
+ fz_try(ctx)
+ {
+ for (tok = pdf_lex(str, &lbuf); tok != PDF_TOK_EOF; tok = pdf_lex(str, &lbuf))
+ {
+ switch (tok)
+ {
+ case PDF_TOK_NAME:
+ fz_free(ctx, da_state->name);
+ da_state->name = fz_strdup(ctx, lbuf.scratch);
+ break;
+
+ case PDF_TOK_INT:
+ da_check_stack(da_state);
+ da_state->stack[da_state->top] = lbuf.i;
+ da_state->top ++;
+ break;
+
+ case PDF_TOK_REAL:
+ da_check_stack(da_state);
+ da_state->stack[da_state->top] = lbuf.f;
+ da_state->top ++;
+ break;
+
+ case PDF_TOK_KEYWORD:
+ if (!strcmp(lbuf.scratch, "Tf"))
+ {
+ da_state->font_size = da_state->stack[0];
+ da_state->font_name = da_state->name;
+ da_state->name = NULL;
+ }
+ else if (!strcmp(lbuf.scratch, "rg"))
+ {
+ da_state->col[0] = da_state->stack[0];
+ da_state->col[1] = da_state->stack[1];
+ da_state->col[2] = da_state->stack[2];
+ da_state->col_size = 3;
+ }
+
+ da_reset(ctx, da_state);
+ break;
+ }
+ }
+ }
+ fz_always(ctx)
+ {
+ fz_close(str);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+static void fzbuf_print_da(fz_context *ctx, fz_buffer *fzbuf, da_parse_state *da)
+{
+ if (da->font_name != NULL && da->font_size != 0)
+ fz_buffer_printf(ctx, fzbuf, "/%s %d Tf", da->font_name, da->font_size);
+
+ if (da->col_size != 0)
+ fz_buffer_printf(ctx, fzbuf, " %f %f %f rg", da->col[0], da->col[1], da->col[2]);
+}
+
static void copy_da_with_altered_size(fz_context *ctx, fz_buffer *fzbuf, char *da, int size)
{
int tok;
@@ -1318,6 +1435,53 @@ void pdf_field_buttonSetCaption(pdf_document *doc, pdf_obj *field, char *text)
}
}
+void pdf_field_setFillColor(pdf_document *doc, pdf_obj *field, pdf_obj *col)
+{
+ pdf_dict_putp(field, "MK/BG", col);
+ pdf_field_mark_dirty(doc->ctx, field);
+}
+
+void pdf_field_setTextColor(pdf_document *doc, pdf_obj *field, pdf_obj *col)
+{
+ fz_context *ctx = doc->ctx;
+ da_parse_state da_state;
+ fz_buffer *fzbuf = NULL;
+ char *da = pdf_to_str_buf(pdf_dict_gets(field, "DA"));
+ unsigned char *buf;
+ int len;
+ pdf_obj *daobj = NULL;
+
+ da_init(ctx, &da_state);
+
+ fz_var(fzbuf);
+ fz_var(da_state);
+ fz_var(daobj);
+ fz_try(ctx)
+ {
+ parse_da(ctx, da, &da_state);
+ da_state.col_size = 3;
+ da_state.col[0] = pdf_to_real(pdf_array_get(col, 0));
+ da_state.col[1] = pdf_to_real(pdf_array_get(col, 1));
+ da_state.col[2] = pdf_to_real(pdf_array_get(col, 2));
+ fzbuf = fz_new_buffer(ctx, 0);
+ fzbuf_print_da(ctx, fzbuf, &da_state);
+ len = fz_buffer_storage(ctx, fzbuf, &buf);
+ daobj = pdf_new_string(ctx, buf, len);
+ pdf_dict_puts(field, "DA", daobj);
+ pdf_field_mark_dirty(ctx, field);
+ }
+ fz_always(ctx)
+ {
+ da_fin(ctx, &da_state);
+ fz_drop_buffer(ctx, fzbuf);
+ pdf_drop_obj(daobj);
+ }
+ fz_catch(ctx)
+ {
+ fz_warn(ctx, "%s", ctx->error->message);
+ }
+}
+
char *fz_widget_text_get_text(fz_widget_text *tw)
{
pdf_document *doc = tw->super.doc;