diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-08-16 08:10:47 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-08-16 08:10:47 +0000 |
commit | 54319b9ec014682aec96a7b67f2debf26fd0757d (patch) | |
tree | 233c484ba6363435891a9d2ff1faccd65cc8d0a6 /Build/source/texk/dvipdfm-x/epdf.c | |
parent | ad0c30ab1fc1553d293f9a5e6789953803a3ef9e (diff) |
Fix various inconsistent behaviors observed in pdf:bcontent/econtent
specials. Revise PSTricks clip support (S. Hirata)
git-svn-id: svn://tug.org/texlive/trunk@56121 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipdfm-x/epdf.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/epdf.c | 508 |
1 files changed, 247 insertions, 261 deletions
diff --git a/Build/source/texk/dvipdfm-x/epdf.c b/Build/source/texk/dvipdfm-x/epdf.c index c7ae614be8d..95094823c7b 100644 --- a/Build/source/texk/dvipdfm-x/epdf.c +++ b/Build/source/texk/dvipdfm-x/epdf.c @@ -1,6 +1,6 @@ /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2007-2018 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team. Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu> @@ -217,84 +217,84 @@ pdf_include_page (pdf_ximage *ximage, return -1; } -typedef enum { - OP_SETCOLOR = 1, - OP_CLOSEandCLIP = 2, - OP_CLIP = 3, - OP_CONCATMATRIX = 4, - OP_SETCOLORSPACE = 5, - OP_RECTANGLE = 6, - OP_CURVETO = 7, - OP_CLOSEPATH = 8, - OP_LINETO = 9, - OP_MOVETO = 10, - OP_NOOP = 11, - OP_GSAVE = 12, - OP_GRESTORE = 13, - OP_CURVETO1 = 14, - OP_CURVETO2 = 15, - OP_UNKNOWN = 16 -} pdf_opcode; +enum action { + action_unknown, + action_discard, + action_path, + action_rect, + action_trans, + action_clip, + action_save, + action_restore +}; static struct operator { const char *token; - int opcode; -} pdf_operators[] = { - {"SCN", OP_SETCOLOR}, - {"b*", OP_CLOSEandCLIP}, - {"B*", OP_CLIP}, - {"cm", OP_CONCATMATRIX}, - {"CS", OP_SETCOLORSPACE}, - {"f*", 0}, - {"gs", -1}, - {"re", OP_RECTANGLE}, - {"rg", -3}, - {"RG", -3}, - {"sc", OP_SETCOLOR}, - {"SC", OP_SETCOLOR}, - {"W*", OP_CLIP}, - {"b", OP_CLOSEandCLIP}, - {"B", OP_CLIP}, - {"c", OP_CURVETO}, - {"d", -2}, - {"f", 0}, - {"F", 0}, - {"g", -1}, - {"G", -1}, - {"h", OP_CLOSEPATH}, - {"i", -1}, - {"j", -1}, - {"J", -1}, - {"k", -4}, - {"K", -4}, - {"l", OP_LINETO}, - {"m", OP_MOVETO}, - {"M", -1}, - {"n", OP_NOOP}, - {"q", OP_GSAVE}, - {"Q", OP_GRESTORE}, - {"s", OP_CLOSEandCLIP}, - {"S", OP_CLIP}, - {"v", OP_CURVETO1}, - {"w", -1}, - {"W", OP_CLIP}, - {"y", OP_CURVETO2} + enum action action; + int n_args; +} operators[] = { + {"b*", action_clip, 0}, + {"B*", action_clip, 0}, + {"cm", action_trans, 6}, + {"f*", action_clip, 0}, + {"re", action_rect, 4}, + {"W*", action_path, 0}, + {"b", action_clip, 0}, + {"B", action_clip, 0}, + {"c", action_path, 6}, + {"f", action_clip, 0}, + {"F", action_clip, 0}, + {"h", action_path, 0}, + {"l", action_path, 2}, + {"m", action_path, 2}, + {"n", action_path, 0}, + {"q", action_save, 0}, + {"Q", action_restore, 0}, + {"s", action_clip, 0}, + {"S", action_clip, 0}, + {"v", action_path, 4}, + {"W", action_path, 0}, + {"y", action_path, 4} }; +#include "dpxutil.h" + +static int +get_numbers_from_stack (dpx_stack *stack, double *v, int n) +{ + int error = 0; + int i; + + for (i = 0; i < n; i++) { + pdf_obj *obj; + obj = dpx_stack_pop(stack); + if (!obj) { + error = -1; + break; + } else if (!PDF_OBJ_NUMBERTYPE(obj)) { + pdf_release_obj(obj); + error = -1; + break; + } + v[n-i-1] = pdf_number_value(obj); + pdf_release_obj(obj); + } + return error; +} int pdf_copy_clip (FILE *image_file, int pageNo, double x_user, double y_user) { pdf_obj *page_tree, *contents; - int depth = 0, top = -1; - const char *clip_path, *end_path; - char *save_path, *temp; + int depth = 0; + const char *p, *endptr; pdf_tmatrix M; - double stack[6]; pdf_rect bbox; pdf_tmatrix mtrx; pdf_file *pf; + dpx_stack stack; + int error = 0; pf = pdf_open(NULL, image_file); if (!pf) @@ -309,6 +309,7 @@ pdf_copy_clip (FILE *image_file, int pageNo, double x_user, double y_user) pdf_close(pf); return -1; } + contents = get_page_content(pf, page_tree); pdf_release_obj(page_tree); if (!contents) { @@ -318,215 +319,200 @@ pdf_copy_clip (FILE *image_file, int pageNo, double x_user, double y_user) pdf_doc_add_page_content(" ", 1); - save_path = NEW(pdf_stream_length(contents) + 1, char); - strncpy(save_path, (const char *) pdf_stream_dataptr(contents), pdf_stream_length(contents)); - clip_path = save_path; - end_path = clip_path + pdf_stream_length(contents); - depth = 0; - - for (; clip_path < end_path; clip_path++) { - int color_dimen = 0; /* silence uninitialized warning */ - char *token; - skip_white(&clip_path, end_path); - if (clip_path == end_path) - break; + p = pdf_stream_dataptr(contents); + endptr = p + pdf_stream_length(contents); + depth = 0; + dpx_stack_init(&stack); + + skip_white(&p, endptr); + while (p < endptr && !error) { + enum action action = action_discard; + char *token = NULL; + pdf_obj *obj = NULL; + int n_args = 0; + char buf[1024]; + size_t len = 0; + if (depth > 1) { - if (*clip_path == 'q') + if (*p == 'q') depth++; - if (*clip_path == 'Q') - depth--; - parse_ident(&clip_path, end_path); + if (*p == 'Q') + depth--; + token = parse_ident(&p, endptr); + skip_white(&p, endptr); + RELEASE(token); + continue; + } + + switch (*p) { + case '-': case '+': case'.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + obj = parse_pdf_number(&p, endptr); + break; + case '[': + obj = parse_pdf_array(&p, endptr, NULL); /* No indirect reference allowed here */ + break; + case '/': + obj = parse_pdf_name(&p, endptr); + break; + case '(': + obj = parse_pdf_string(&p, endptr); + break; + case '<': + if (p < endptr - 1 && p[1] == '<') { + obj = parse_pdf_dict(&p, endptr, NULL); + } else { + obj = parse_pdf_string(&p, endptr); + } + break; + } + if (obj) { + skip_white(&p, endptr); + dpx_stack_push(&stack, obj); continue; - } else if (*clip_path == '-' - || *clip_path == '+' - || *clip_path == '.' - || isdigit((unsigned char)*clip_path)) { - stack[++top] = strtod(clip_path, &temp); - clip_path = temp; - } else if (*clip_path == '[') { - /* Ignore, but put a dummy value on the stack (in case of d operator) */ - parse_pdf_array(&clip_path, end_path, pf); - stack[++top] = 0; - } else if (*clip_path == '/') { - if (strncmp("/DeviceGray", clip_path, 11) == 0 - || strncmp("/Indexed", clip_path, 8) == 0 - || strncmp("/CalGray", clip_path, 8) == 0) { - color_dimen = 1; - continue; + } + + /* operator */ + token = parse_ident(&p, endptr); + skip_white(&p, endptr); + if (!token) { + break; + } else { + int i; + for (i = 0; i < sizeof(operators) / sizeof(operators[0]); i++) { + if (!strcmp(token, operators[i].token)) { + action = operators[i].action; + n_args = operators[i].n_args; + break; + } } - else if (strncmp("/DeviceRGB", clip_path, 10) == 0 - || strncmp("/CalRGB", clip_path, 7) == 0 - || strncmp("/Lab", clip_path, 4) == 0) { - color_dimen = 3; - continue; + } + switch (action) { + case action_rect: + { + double v[4]; + + error = get_numbers_from_stack(&stack, v, n_args); /* n_args = 4 */ + if (!error) { + /* Not sure if this switch is required */ + if (M.b == 0.0 && M.c == 0.0) { + /* Use "re" operator */ + pdf_coord p0; + double w, h; + + p0.x = v[0]; p0.y = v[1]; + w = M.a * v[2]; h = M.d * v[3]; + pdf_dev_transform(&p0, &M); + buf[len++] = ' '; + len += pdf_sprint_coord(buf+len, &p0); + buf[len++] = ' '; + len += pdf_sprint_length(buf+len, w); + buf[len++] = ' '; + len += pdf_sprint_length(buf+len, h); + len += sprintf(buf+len, " re"); + } else { + /* Converted to lineto */ + pdf_coord p0, p1, p2, p3; + double w, h; + + w = v[2]; h = v[3]; + p0.x = v[0]; p0.y = v[1]; + p1.x = p0.x + w; p1.y = p0.y; + p2.x = p1.x; p2.y = p1.y + h; + p3.x = p0.x; p3.y = p2.y; + pdf_dev_transform(&p0, &M); + pdf_dev_transform(&p1, &M); + pdf_dev_transform(&p2, &M); + pdf_dev_transform(&p3, &M); + buf[len++] = ' '; + len += pdf_sprint_coord(buf+len, &p0); + len += sprintf(buf+len, " m"); + buf[len++] = ' '; + len += pdf_sprint_coord(buf+len, &p1); + len += sprintf(buf+len, " l"); + buf[len++] = ' '; + len += pdf_sprint_coord(buf+len, &p2); + len += sprintf(buf+len, " l"); + buf[len++] = ' '; + len += pdf_sprint_coord(buf+len, &p3); + len += sprintf(buf+len, " l h"); + } + pdf_doc_add_page_content(buf, len); + } } - else if (strncmp("/DeviceCMYK", clip_path, 11) == 0) { - color_dimen = 4; - continue; + break; + case action_path: + { + double v[6]; + pdf_coord pt; + int i; + + error = get_numbers_from_stack(&stack, v, n_args); + if (!error) { + for (i = 0; i < n_args/2; i++) { + pt.x = v[2*i]; + pt.y = v[2*i+1]; + pdf_dev_transform(&pt, &M); + buf[len++] = ' '; + len += pdf_sprint_coord(buf+len, &pt); + } + len += sprintf(buf+len, " %s", token); + pdf_doc_add_page_content(buf, len); + } } - else { - clip_path++; - parse_ident(&clip_path, end_path); - skip_white(&clip_path, end_path); - token = parse_ident(&clip_path, end_path); - if (strcmp(token, "gs") == 0) { - continue; - } - return -1; + break; + case action_trans: + { + double v[6]; + pdf_tmatrix T; + error = get_numbers_from_stack(&stack, v, n_args); + if (!error) { + T.a = v[0]; T.b = v[1]; T.c = v[2]; T.d = v[3]; + T.e = v[4]; T.f = v[5]; + pdf_concatmatrix(&M, &T); + } } - } else { - int j; - pdf_tmatrix T; - pdf_coord p0, p1, p2, p3; - - token = parse_ident(&clip_path, end_path); - for (j = 0; j < sizeof(pdf_operators) / sizeof(pdf_operators[0]); j++) - if (strcmp(token, pdf_operators[j].token) == 0) - break; - if (j == sizeof(pdf_operators) / sizeof(pdf_operators[0])) { - return -1; + break; + case action_clip: + if (token[0] >= 'a' && token[0] <= 'z') { + /* close path */ + len += sprintf(buf+len, " h"); } - switch (pdf_operators[j].opcode) { - case 0: - case -1: - case -2: - case -3: - case -4: - /* Just pop the stack and do nothing. */ - top += pdf_operators[j].opcode; - if (top < -1) - return -1; - break; - case OP_SETCOLOR: - top -= color_dimen; - if (top < -1) - return -1; - break; - case OP_CLOSEandCLIP: - pdf_dev_closepath(); - case OP_CLIP: -#if 0 - pdf_dev_clip(); -#else - pdf_dev_flushpath('W', PDF_FILL_RULE_NONZERO); -#endif - break; - case OP_CONCATMATRIX: - if (top < 5) - return -1; - T.f = stack[top--]; - T.e = stack[top--]; - T.d = stack[top--]; - T.c = stack[top--]; - T.b = stack[top--]; - T.a = stack[top--]; - pdf_concatmatrix(&M, &T); - break; - case OP_SETCOLORSPACE: - /* Do nothing. */ - break; - case OP_RECTANGLE: - if (top < 3) - return -1; - p1.y = stack[top--]; - p1.x = stack[top--]; - p0.y = stack[top--]; - p0.x = stack[top--]; - if (M.b == 0 && M.c == 0) { - pdf_tmatrix M0; - M0.a = M.a; M0.b = M.b; M0.c = M.c; M0.d = M.d; - M0.e = 0; M0.f = 0; - pdf_dev_transform(&p0, &M); - pdf_dev_transform(&p1, &M0); - pdf_dev_rectadd(p0.x, p0.y, p1.x, p1.y); - } else { - p2.x = p0.x + p1.x; p2.y = p0.y + p1.y; - p3.x = p0.x; p3.y = p0.y + p1.y; - p1.x += p0.x; p1.y = p0.y; - pdf_dev_transform(&p0, &M); - pdf_dev_transform(&p1, &M); - pdf_dev_transform(&p2, &M); - pdf_dev_transform(&p3, &M); - pdf_dev_moveto(p0.x, p0.y); - pdf_dev_lineto(p1.x, p1.y); - pdf_dev_lineto(p2.x, p2.y); - pdf_dev_lineto(p3.x, p3.y); - pdf_dev_closepath(); - } - break; - case OP_CURVETO: - if (top < 5) - return -1; - p0.y = stack[top--]; - p0.x = stack[top--]; - pdf_dev_transform(&p0, &M); - p1.y = stack[top--]; - p1.x = stack[top--]; - pdf_dev_transform(&p1, &M); - p2.y = stack[top--]; - p2.x = stack[top--]; - pdf_dev_transform(&p2, &M); - pdf_dev_curveto(p2.x, p2.y, p1.x, p1.y, p0.x, p0.y); - break; - case OP_CLOSEPATH: - pdf_dev_closepath(); - break; - case OP_LINETO: - if (top < 1) - return -1; - p0.y = stack[top--]; - p0.x = stack[top--]; - pdf_dev_transform(&p0, &M); - pdf_dev_lineto(p0.x, p0.y); - break; - case OP_MOVETO: - if (top < 1) - return -1; - p0.y = stack[top--]; - p0.x = stack[top--]; - pdf_dev_transform(&p0, &M); - pdf_dev_moveto(p0.x, p0.y); - break; - case OP_NOOP: - pdf_doc_add_page_content(" n", 2); - break; - case OP_GSAVE: - depth++; - break; - case OP_GRESTORE: - depth--; - break; - case OP_CURVETO1: - if (top < 3) - return -1; - p0.y = stack[top--]; - p0.x = stack[top--]; - pdf_dev_transform(&p0, &M); - p1.y = stack[top--]; - p1.x = stack[top--]; - pdf_dev_transform(&p1, &M); - pdf_dev_vcurveto(p1.x, p1.y, p0.x, p0.y); - break; - case OP_CURVETO2: - if (top < 3) - return -1; - p0.y = stack[top--]; - p0.x = stack[top--]; - pdf_dev_transform(&p0, &M); - p1.y = stack[top--]; - p1.x = stack[top--]; - pdf_dev_transform(&p1, &M); - pdf_dev_ycurveto(p1.x, p1.y, p0.x, p0.y); - break; - default: - return -1; + if (strlen(token) >= 2 && token[1] == '*') { + len += sprintf(buf+len, " W* n"); + } else { + len += sprintf(buf+len, " W n"); + } + pdf_doc_add_page_content(buf, len); + break; + case action_save: + depth++; + break; + case action_restore: + depth--; + break; + case action_discard: + /* stack clearing behavior */ + while ((obj = dpx_stack_pop(&stack)) != NULL) { + pdf_release_obj(obj); } + break; + case action_unknown: + error = -1; + break; + } + RELEASE(token); + } + { + pdf_obj *obj; + + while ((obj = dpx_stack_pop(&stack)) != NULL) { + pdf_release_obj(obj); } } - RELEASE(save_path); - pdf_release_obj(contents); pdf_close(pf); - return 0; + return error; } |