summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/pdf/appearance.h1
-rw-r--r--include/mupdf/pdf/widget.h6
-rw-r--r--platform/android/jni/mupdf.c4
-rw-r--r--platform/ios/Classes/MuPageViewNormal.m4
-rw-r--r--platform/x11/pdfapp.c4
-rw-r--r--source/pdf/pdf-appearance.c252
-rw-r--r--source/pdf/pdf-form.c19
7 files changed, 272 insertions, 18 deletions
diff --git a/include/mupdf/pdf/appearance.h b/include/mupdf/pdf/appearance.h
index ddf64516..5ea92c63 100644
--- a/include/mupdf/pdf/appearance.h
+++ b/include/mupdf/pdf/appearance.h
@@ -15,6 +15,7 @@ void pdf_fzbuf_print_da(fz_context *ctx, fz_buffer *fzbuf, pdf_da_info *di);
void pdf_update_text_appearance(fz_context *ctx, pdf_document *doc, pdf_obj *obj, char *eventValue);
void pdf_update_combobox_appearance(fz_context *ctx, pdf_document *doc, pdf_obj *obj);
+void pdf_update_listbox_appearance(fz_context *ctx, pdf_document *doc, pdf_obj *obj);
void pdf_update_pushbutton_appearance(fz_context *ctx, pdf_document *doc, pdf_obj *obj);
void pdf_update_text_markup_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_annot_type type);
void pdf_update_ink_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *annot);
diff --git a/include/mupdf/pdf/widget.h b/include/mupdf/pdf/widget.h
index 45441e55..a4b5bd5e 100644
--- a/include/mupdf/pdf/widget.h
+++ b/include/mupdf/pdf/widget.h
@@ -96,9 +96,11 @@ int pdf_text_widget_set_text(fz_context *ctx, pdf_document *doc, pdf_widget *tw,
pdf_choice_widget_options: get the list of options for a list
box or combo box. Returns the number of options and fills in their
names within the supplied array. Should first be called with a
- NULL array to find out how big the array should be.
+ NULL array to find out how big the array should be. If exportval
+ is true, then the export values will be returned and not the list
+ values if there are export values present.
*/
-int pdf_choice_widget_options(fz_context *ctx, pdf_document *doc, pdf_widget *tw, char *opts[]);
+int pdf_choice_widget_options(fz_context *ctx, pdf_document *doc, pdf_widget *tw, int exportval, char *opts[]);
/*
pdf_choice_widget_is_multiselect: returns whether a list box or
diff --git a/platform/android/jni/mupdf.c b/platform/android/jni/mupdf.c
index 20026e81..72214597 100644
--- a/platform/android/jni/mupdf.c
+++ b/platform/android/jni/mupdf.c
@@ -2151,9 +2151,9 @@ JNI_FN(MuPDFCore_getFocusedWidgetChoiceOptions)(JNIEnv * env, jobject thiz)
fz_var(opts);
fz_try(ctx)
{
- nopts = pdf_choice_widget_options(ctx, idoc, focus, NULL);
+ nopts = pdf_choice_widget_options(ctx, idoc, focus, 0, NULL);
opts = fz_malloc(ctx, nopts * sizeof(*opts));
- (void)pdf_choice_widget_options(ctx, idoc, focus, opts);
+ (void)pdf_choice_widget_options(ctx, idoc, focus, 0, opts);
}
fz_catch(ctx)
{
diff --git a/platform/ios/Classes/MuPageViewNormal.m b/platform/ios/Classes/MuPageViewNormal.m
index 671702fe..429785fe 100644
--- a/platform/ios/Classes/MuPageViewNormal.m
+++ b/platform/ios/Classes/MuPageViewNormal.m
@@ -1301,9 +1301,9 @@ static void updatePixmap(fz_document *doc, fz_display_list *page_list, fz_displa
case PDF_WIDGET_TYPE_LISTBOX:
case PDF_WIDGET_TYPE_COMBOBOX:
{
- int nopts = pdf_choice_widget_options(ctx, idoc, focus, NULL);
+ int nopts = pdf_choice_widget_options(ctx, idoc, focus, 0, NULL);
opts = fz_malloc(ctx, nopts * sizeof(*opts));
- (void)pdf_choice_widget_options(ctx, idoc, focus, opts);
+ (void)pdf_choice_widget_options(ctx, idoc, focus, 0, opts);
NSMutableArray *arr = [[NSMutableArray arrayWithCapacity:nopts] retain];
for (int i = 0; i < nopts; i++)
{
diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c
index 006cba1b..5a036d04 100644
--- a/platform/x11/pdfapp.c
+++ b/platform/x11/pdfapp.c
@@ -1665,9 +1665,9 @@ void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int sta
fz_try(ctx)
{
- nopts = pdf_choice_widget_options(ctx, idoc, widget, NULL);
+ nopts = pdf_choice_widget_options(ctx, idoc, widget, 0, NULL);
opts = fz_malloc(ctx, nopts * sizeof(*opts));
- (void)pdf_choice_widget_options(ctx, idoc, widget, opts);
+ (void)pdf_choice_widget_options(ctx, idoc, widget, 0, opts);
nvals = pdf_choice_widget_value(ctx, idoc, widget, NULL);
vals = fz_malloc(ctx, MAX(nvals,nopts) * sizeof(*vals));
diff --git a/source/pdf/pdf-appearance.c b/source/pdf/pdf-appearance.c
index b0fa2207..cd1f0f93 100644
--- a/source/pdf/pdf-appearance.c
+++ b/source/pdf/pdf-appearance.c
@@ -9,6 +9,9 @@
#define UNDERLINE_HEIGHT (0.075f)
#define LINE_THICKNESS (0.07f)
#define SMALL_FLOAT (0.00001)
+#define LIST_SEL_COLOR_R (0.6)
+#define LIST_SEL_COLOR_G (0.75)
+#define LIST_SEL_COLOR_B (0.85)
enum
{
@@ -258,6 +261,38 @@ static void fzbuf_print_color(fz_context *ctx, fz_buffer *fzbuf, pdf_obj *arr, i
}
}
+static void fzbuf_print_rect_fill(fz_context *ctx, fz_buffer *fzbuf, const fz_rect *clip,
+ float col[4], int col_size, const fz_matrix *tm, const fz_rect *rect)
+{
+ if (clip)
+ {
+ fz_buffer_printf(ctx, fzbuf, fmt_re, clip->x0, clip->y0, clip->x1 - clip->x0, clip->y1 - clip->y0);
+ fz_buffer_printf(ctx, fzbuf, fmt_W);
+ }
+ if (col_size > 0)
+ {
+ switch (col_size)
+ {
+ case 1:
+ fz_buffer_printf(ctx, fzbuf, "%f g\n", col[0]);
+ break;
+ case 3:
+ fz_buffer_printf(ctx, fzbuf, "%f %f %f rg\n", col[0], col[1], col[2]);
+ break;
+ case 4:
+ fz_buffer_printf(ctx, fzbuf, "%f %f %f %f k\n", col[0], col[1], col[2], col[3]);
+ break;
+ default:
+ break;
+ }
+ }
+ if (tm)
+ fz_buffer_printf(ctx, fzbuf, fmt_Tm, tm->a, tm->b, tm->c, tm->d, tm->e, tm->f);
+
+ fz_buffer_printf(ctx, fzbuf, fmt_re, rect->x0, rect->y0, rect->x1 - rect->x0, rect->y1 - rect->y0);
+ fz_buffer_printf(ctx, fzbuf, fmt_f);
+}
+
static void fzbuf_print_text(fz_context *ctx, fz_buffer *fzbuf, const fz_rect *clip, pdf_obj *col, font_info *font_rec, const fz_matrix *tm, char *text)
{
fz_buffer_printf(ctx, fzbuf, fmt_q);
@@ -521,7 +556,7 @@ static void text_splitter_retry(text_splitter *splitter)
}
}
-static void fzbuf_print_text_start(fz_context *ctx, fz_buffer *fzbuf, const fz_rect *clip, pdf_obj *col, font_info *font, const fz_matrix *tm)
+static void fzbuf_print_text_start1(fz_context *ctx, fz_buffer *fzbuf, const fz_rect *clip, pdf_obj *col)
{
fz_buffer_printf(ctx, fzbuf, fmt_Tx_BMC);
fz_buffer_printf(ctx, fzbuf, fmt_q);
@@ -540,7 +575,10 @@ static void fzbuf_print_text_start(fz_context *ctx, fz_buffer *fzbuf, const fz_r
fz_buffer_printf(ctx, fzbuf, fmt_n);
}
}
+}
+static void fzbuf_print_text_start2(fz_context *ctx, fz_buffer *fzbuf, font_info *font, const fz_matrix *tm)
+{
fz_buffer_printf(ctx, fzbuf, fmt_BT);
pdf_fzbuf_print_da(ctx, fzbuf, &font->da_rec);
@@ -662,7 +700,8 @@ static fz_buffer *create_text_appearance(fz_context *ctx, pdf_document *doc, con
tm.e = rect.x0;
tm.f = rect.y1 - (1.0+ascent-descent)*fontsize*splitter.scale/2.0;
- fzbuf_print_text_start(ctx, fzbuf, &rect, info->col, &info->font_rec, &tm);
+ fzbuf_print_text_start1(ctx, fzbuf, &rect, info->col);
+ fzbuf_print_text_start2(ctx, fzbuf, &info->font_rec, &tm);
fz_buffer_cat(ctx, fzbuf, fztmp);
@@ -679,7 +718,8 @@ static fz_buffer *create_text_appearance(fz_context *ctx, pdf_document *doc, con
fzbuf = fz_new_buffer(ctx, 0);
- fzbuf_print_text_start(ctx, fzbuf, &rect, info->col, &info->font_rec, &tm);
+ fzbuf_print_text_start1(ctx, fzbuf, &rect, info->col);
+ fzbuf_print_text_start2(ctx, fzbuf, &info->font_rec, &tm);
for (i = 0; i < n; i++)
fzbuf_print_text_word(ctx, fzbuf, i == 0 ? init_skip : comb_width, 0.0, text+i, 1);
@@ -1134,6 +1174,208 @@ void pdf_update_text_appearance(fz_context *ctx, pdf_document *doc, pdf_obj *obj
}
}
+void pdf_update_listbox_appearance(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
+{
+ text_widget_info info;
+ pdf_xobject *form = NULL;
+ fz_buffer *fzbuf = NULL;
+ fz_matrix tm;
+ fz_rect clip_rect;
+ fz_rect fill_rect;
+ int has_tm;
+ pdf_obj *valarr;
+ pdf_obj *optarr;
+ char *text;
+ int n, m, i, j;
+ char **opts = NULL;
+ char **vals = NULL;
+ int *sel_indices = NULL;
+ char **pos;
+ char *val_sel;
+ int index = -1;
+ float height, width;
+ float ascent, descent, lineheight;
+ int variable;
+ int fontsize;
+ float items_height;
+ fz_rect bbox;
+ int num_sel = 0;
+ int found_count;
+ int val_opt_ok = 1;
+ float color[4];
+
+ memset(&info, 0, sizeof(info));
+
+ fz_var(info);
+ fz_var(form);
+ fz_var(fzbuf);
+ fz_var(opts);
+ fz_var(vals);
+ fz_var(sel_indices);
+ fz_try(ctx)
+ {
+ optarr = pdf_dict_get(ctx, obj, PDF_NAME_Opt);
+ n = pdf_array_len(ctx, optarr);
+ opts = (char **)fz_malloc(ctx, n * sizeof(*opts));
+ vals = (char **)fz_malloc(ctx, n * sizeof(*vals));
+ sel_indices = (int*)fz_malloc(ctx, n * sizeof(int));
+ for (i = 0; i < n; i++)
+ {
+ m = pdf_array_len(ctx, pdf_array_get(ctx, optarr, i));
+ if (m == 2)
+ {
+ vals[i] = pdf_to_str_buf(ctx, pdf_array_get(ctx, pdf_array_get(ctx, optarr, i), 0));
+ opts[i] = pdf_to_str_buf(ctx, pdf_array_get(ctx, pdf_array_get(ctx, optarr, i), 1));
+ }
+ else
+ {
+ opts[i] = pdf_to_str_buf(ctx, pdf_array_get(ctx, optarr, i));
+ val_opt_ok = 0;
+ }
+ }
+
+ /* If ANY of the entries are not an array then just use the opts not
+ the vals. */
+ if (val_opt_ok)
+ pos = vals;
+ else
+ pos = opts;
+
+ get_text_widget_info(ctx, doc, obj, &info);
+ form = load_or_create_form(ctx, doc, obj, &clip_rect);
+ has_tm = get_matrix(ctx, doc, form, info.q, &tm);
+
+ /* See which ones are selected */
+ valarr = pdf_get_inheritable(ctx, doc, obj, PDF_NAME_V);
+ if (pdf_is_array(ctx, valarr))
+ {
+ num_sel = pdf_array_len(ctx, valarr);
+ /* Multiple selected */
+ found_count = 0;
+ for (i = 0; i < num_sel; i++)
+ {
+ text = pdf_to_str_buf(ctx, pdf_array_get(ctx, valarr, i));
+ /* See if we can find it. */
+ index = -1;
+ for (j = 0; j < n; j++)
+ {
+ if (!strcmp(text, pos[j]))
+ {
+ index = j;
+ break;
+ }
+ }
+ if (index > -1)
+ {
+ sel_indices[found_count] = index;
+ found_count += 1;
+ }
+ }
+ num_sel = found_count;
+ }
+ else
+ {
+ /* One or none selected */
+ text = pdf_to_str_buf(ctx, valarr);
+ num_sel = 0;
+ if (text)
+ {
+ index = -1;
+ for (i = 0; i < n; i++)
+ {
+ if (!strcmp(text, pos[i]))
+ {
+ index = i;
+ break;
+ }
+ }
+ if (index > -1)
+ {
+ num_sel = 1;
+ sel_indices[0] = index;
+ }
+ }
+ }
+
+ if (clip_rect.x1 - clip_rect.x0 > 3.0 && clip_rect.y1 - clip_rect.y0 > 3.0)
+ {
+ clip_rect.x0 += 1.0;
+ clip_rect.x1 -= 1.0;
+ clip_rect.y0 += 1.0;
+ clip_rect.y1 -= 1.0;
+ }
+ height = clip_rect.y1 - clip_rect.y0;
+ width = clip_rect.x1 - clip_rect.x0;
+ variable = (info.font_rec.da_rec.font_size == 0);
+ fontsize = variable
+ ? (info.multiline ? 14.0 : height / info.font_rec.lineheight)
+ : info.font_rec.da_rec.font_size;
+
+ /* Get the ascent, descent across the items list. */
+ ascent = 0;
+ descent = 0;
+ info.font_rec.da_rec.font_size = 1;
+ for (i = 0; i < n; i++)
+ {
+ measure_text(ctx, doc, &(info.font_rec), &fz_identity, opts[i], &bbox);
+ descent = fz_min(-bbox.y0, descent);
+ ascent = fz_max(bbox.y1, ascent);
+ }
+ info.font_rec.da_rec.font_size = fontsize;
+ lineheight = ascent - descent;
+
+ /* Check if all items will fit. If not, then place the "selected" item
+ at the top of our widget rect. */
+ items_height = n * fontsize * lineheight;
+ if (items_height <= height || !num_sel)
+ fz_translate(&tm, clip_rect.x0, clip_rect.y1 - lineheight * fontsize);
+ else
+ fz_translate(&tm, clip_rect.x0, clip_rect.y1 + (sel_indices[0] - 1) * lineheight * fontsize);
+
+ fzbuf = fz_new_buffer(ctx, 0);
+ /* Start the marked content */
+ fzbuf_print_text_start1(ctx, fzbuf, &clip_rect, NULL);
+ /* Add the selection rects */
+ if (num_sel > 0)
+ {
+ color[0] = LIST_SEL_COLOR_R;
+ color[1] = LIST_SEL_COLOR_G;
+ color[2] = LIST_SEL_COLOR_B;
+ fill_rect.x0 = 0.0;
+ fill_rect.x1 = width;
+ for (i = 0; i < num_sel; i++)
+ {
+ fill_rect.y0 = height - fontsize * lineheight * (sel_indices[i] + 1);
+ fill_rect.y1 = fill_rect.y0 + lineheight * fontsize;
+ fzbuf_print_rect_fill(ctx, fzbuf, NULL, color, 3, NULL, &fill_rect);
+ }
+ }
+ /* Continue with text related details */
+ fzbuf_print_text_start2(ctx, fzbuf, &info.font_rec, &tm);
+ /* And now finish with the text content */
+ for (i = 0; i < n; i++)
+ {
+ fzbuf_print_text_word(ctx, fzbuf, 0.0, i == 0 ? 0 : -fontsize *
+ lineheight, opts[i], strlen(opts[i]));
+ }
+ fzbuf_print_text_end(ctx, fzbuf);
+ update_marked_content(ctx, doc, form, fzbuf);
+ }
+ fz_always(ctx)
+ {
+ fz_free(ctx, opts);
+ fz_free(ctx, vals);
+ fz_free(ctx, sel_indices);
+ pdf_drop_xobject(ctx, form);
+ fz_drop_buffer(ctx, fzbuf);
+ font_info_fin(ctx, &info.font_rec);
+ }
+ fz_catch(ctx)
+ {
+ fz_warn(ctx, "update_text_appearance failed");
+ }
+}
+
void pdf_update_combobox_appearance(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
{
text_widget_info info;
@@ -2234,9 +2476,9 @@ void pdf_update_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *annot)
pdf_update_pushbutton_appearance(ctx, doc, obj);
break;
case PDF_WIDGET_TYPE_LISTBOX:
+ pdf_update_listbox_appearance(ctx, doc, obj);
+ break;
case PDF_WIDGET_TYPE_COMBOBOX:
- /* Treating listbox and combobox identically for now,
- * and the behaviour is most appropriate for a combobox */
pdf_update_combobox_appearance(ctx, doc, obj);
break;
}
diff --git a/source/pdf/pdf-form.c b/source/pdf/pdf-form.c
index dcb08bc7..ce51ae4f 100644
--- a/source/pdf/pdf-form.c
+++ b/source/pdf/pdf-form.c
@@ -1276,26 +1276,35 @@ int pdf_text_widget_set_text(fz_context *ctx, pdf_document *doc, pdf_widget *tw,
return accepted;
}
-int pdf_choice_widget_options(fz_context *ctx, pdf_document *doc, pdf_widget *tw, char *opts[])
+/* Get either the listed value or the export value. */
+int pdf_choice_widget_options(fz_context *ctx, pdf_document *doc, pdf_widget *tw, int exportval, char *opts[])
{
pdf_annot *annot = (pdf_annot *)tw;
pdf_obj *optarr;
- int i, n;
+ int i, n, m;
if (!annot)
return 0;
optarr = pdf_dict_get(ctx, annot->obj, PDF_NAME_Opt);
n = pdf_array_len(ctx, optarr);
-
+
if (opts)
{
for (i = 0; i < n; i++)
{
- opts[i] = pdf_to_str_buf(ctx, pdf_array_get(ctx, optarr, i));
+ m = pdf_array_len(ctx, pdf_array_get(ctx, optarr, i));
+ /* If it is a two element array, the second item is the one that we want
+ if we want the listing value */
+ if (m == 2)
+ if (exportval)
+ opts[i] = pdf_to_str_buf(ctx, pdf_array_get(ctx, pdf_array_get(ctx, optarr, i), 0));
+ else
+ opts[i] = pdf_to_str_buf(ctx, pdf_array_get(ctx, pdf_array_get(ctx, optarr, i), 1));
+ else
+ opts[i] = pdf_to_str_buf(ctx, pdf_array_get(ctx, optarr, i));
}
}
-
return n;
}