1
/* $Header: /home/cvsroot/dvipdfmx/src/mpost.c,v 1.43 2011/03/06 03:14:14 chofchof Exp $
3
This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
5
Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata,
6
the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
8
Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 2 of the License, or
13
(at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
52
#include "pdfximage.h"
57
* In PDF, current path is not a part of graphics state parameter.
58
* Hence, current path is not saved by the "q" operator and is not
59
* recovered by the "Q" operator. This means that the following PS
62
* <path construction> gsave <path painting> grestore ...
64
* can't be translated to PDF code
66
* <path construction> q <path painting> Q ...
68
* . Only clipping path (which is graphics state parameter in PDF
69
* too) is treated in the same way. So, we write clipping path
70
* immediately and forget about it but remember current path.
73
static int mp_parse_body (const char **start, const char *end, double x_user, double y_user);
79
int tfm_id; /* Used for text width calculation */
82
} font_stack[PDF_GSAVE_MAX] = {
85
static int currentfont = -1;
87
#define CURRENT_FONT() ((currentfont < 0) ? NULL : &font_stack[currentfont])
90
#define MP_CMODE_MPOST 0
91
#define MP_CMODE_DVIPSK 1
92
#define MP_CMODE_PTEXVERT 2
93
static int mp_cmode = MP_CMODE_MPOST;
96
mp_setfont (const char *font_name, double pt_size)
98
const char *name = font_name;
103
font = CURRENT_FONT();
106
if (!strcmp(font->font_name, font_name) &&
107
font->pt_size == pt_size)
109
} else { /* No currentfont */
110
/* ***TODO*** Here some problem exists! */
111
font = &font_stack[0];
112
font->font_name = NULL;
116
mrec = pdf_lookup_fontmap_record(font_name);
117
if (mrec && mrec->charmap.sfd_name && mrec->charmap.subfont_id) {
118
subfont_id = sfd_load_record(mrec->charmap.sfd_name, mrec->charmap.subfont_id);
121
/* See comments in dvi_locate_font() in dvi.c. */
122
if (mrec && mrec->map_name) {
123
name = mrec->map_name;
129
RELEASE(font->font_name);
130
font->font_name = NEW(strlen(font_name) + 1, char);
131
strcpy(font->font_name, font_name);
132
font->subfont_id = subfont_id;
133
font->pt_size = pt_size;
134
font->tfm_id = tfm_open(font_name, 0); /* Need not exist in MP mode */
135
font->font_id = pdf_dev_locate_font(name,
136
(spt_t) (pt_size * dev_unit_dviunit()));
138
if (font->font_id < 0) {
139
ERROR("MPOST: No physical font assigned for \"%s\".", font_name);
149
struct mp_font *current, *next;
151
if (currentfont < 0) {
152
font_stack[0].font_name = NEW(strlen("Courier") + 1, char);
153
strcpy(font_stack[0].font_name, "Courier");
154
font_stack[0].pt_size = 1;
155
font_stack[0].tfm_id = 0;
156
font_stack[0].subfont_id = 0;
160
current = &font_stack[currentfont++];
161
next = &font_stack[currentfont ];
162
next->font_name = NEW(strlen(current->font_name)+1, char);
163
strcpy(next->font_name, current->font_name);
164
next->pt_size = current->pt_size;
166
next->subfont_id = current->subfont_id;
167
next->tfm_id = current->tfm_id;
173
struct mp_font *current;
175
current = CURRENT_FONT();
177
if (current->font_name)
178
RELEASE(current->font_name);
179
current->font_name = NULL;
181
ERROR("No currentfont...");
190
while (currentfont >= 0) {
191
if (font_stack[currentfont].font_name)
192
RELEASE(font_stack[currentfont].font_name);
198
is_fontname (const char *token)
202
mrec = pdf_lookup_fontmap_record(token);
206
return tfm_exists(token);
210
mps_scan_bbox (const char **pp, const char *endptr, pdf_rect *bbox)
216
/* skip_white() skips lines starting '%'... */
217
while (*pp < endptr && isspace(**pp))
220
/* Scan for bounding box record */
221
while (*pp < endptr && **pp == '%') {
222
if (*pp + 14 < endptr &&
223
!strncmp(*pp, "%%BoundingBox:", 14)) {
227
for (i = 0; i < 4; i++) {
228
skip_white(pp, endptr);
229
number = parse_number(pp, endptr);
233
values[i] = atof(number);
239
bbox->llx = values[0];
240
bbox->lly = values[1];
241
bbox->urx = values[2];
242
bbox->ury = values[3];
247
skip_line (pp, endptr);
248
while (*pp < endptr && isspace(**pp))
256
skip_prolog (const char **start, const char *end)
258
int found_prolog = 0;
262
while (*start < end) {
264
skip_white(start, end);
267
if (!strncmp(*start, "%%EndProlog", 11)) {
269
skip_line(start, end);
271
} else if (!strncmp(*start, "%%Page:", 7)) {
272
skip_line(start, end);
275
skip_line(start, end);
284
/* PostScript Operators */
325
#define SETLINEWIDTH 60
327
#define SETLINECAP 62
328
#define SETLINEJOIN 63
329
#define SETMITERLIMIT 64
332
#define SETRGBCOLOR 71
333
#define SETCMYKCOLOR 72
335
#define CURRENTPOINT 80
336
#define IDTRANSFORM 81
337
#define DTRANSFORM 82
340
#define SCALEFONT 202
342
#define CURRENTFONT 204
344
#define STRINGWIDTH 210
356
static struct operators
366
{"truncate", TRUNCATE},
374
{"closepath", CLOSEPATH},
377
{"newpath", NEWPATH},
379
{"rmoveto", RMOVETO},
381
{"rlineto", RLINETO},
382
{"curveto", CURVETO},
383
{"rcurveto", RCURVETO},
390
{"showpage", SHOWPAGE},
393
{"grestore", GRESTORE},
394
{"translate", TRANSLATE},
398
{"setlinecap", SETLINECAP},
399
{"setlinejoin", SETLINEJOIN},
400
{"setlinewidth", SETLINEWIDTH},
401
{"setmiterlimit", SETMITERLIMIT},
402
{"setdash", SETDASH},
404
{"setgray", SETGRAY},
405
{"setrgbcolor", SETRGBCOLOR},
406
{"setcmykcolor", SETCMYKCOLOR},
408
{"currentpoint", CURRENTPOINT}, /* This is here for rotate support
409
in graphics package-not MP support */
410
{"dtransform", DTRANSFORM},
411
{"idtransform", IDTRANSFORM},
413
{"findfont", FINDFONT},
414
{"scalefont", SCALEFONT},
415
{"setfont", SETFONT},
416
{"currentfont", CURRENTFONT},
418
{"stringwidth", STRINGWIDTH},
420
{"def", DEF} /* not implemented yet; just work with mptopdf */
423
static struct operators mps_operators[] = {
424
{"fshow", FSHOW}, /* exch findfont exch scalefont setfont show */
425
{"startTexFig", STEXFIG},
426
{"endTexFig", ETEXFIG},
427
{"hlw", HLW}, /* 0 dtransform exch truncate exch idtransform pop setlinewidth */
428
{"vlw", VLW}, /* 0 exch dtransform truncate idtransform pop setlinewidth pop */
439
{"ml", SETMITERLIMIT},
448
{"rd", RD}, /* [] 0 setdash */
450
{"B", B}, /* gsave fill grestore */
454
#define NUM_PS_OPERATORS (sizeof(ps_operators)/sizeof(ps_operators[0]))
455
#define NUM_MPS_OPERATORS (sizeof(mps_operators)/sizeof(mps_operators[0]))
457
get_opcode (const char *token)
461
for (i = 0; i < NUM_PS_OPERATORS; i++) {
462
if (!strcmp(token, ps_operators[i].token)) {
463
return ps_operators[i].opcode;
467
for (i = 0; i < NUM_MPS_OPERATORS; i++) {
468
if (!strcmp(token, mps_operators[i].token)) {
469
return mps_operators[i].opcode;
476
#define PS_STACK_SIZE 1024
478
static pdf_obj *stack[PS_STACK_SIZE];
479
static unsigned top_stack = 0;
481
#define POP_STACK() ((top_stack > 0) ? stack[--top_stack] : NULL)
482
#define PUSH_STACK(o,e) { \
483
if (top_stack < PS_STACK_SIZE) { \
484
stack[top_stack++] = (o); \
486
WARN("PS stack overflow including MetaPost file or inline PS code"); \
499
tmp = stack[top_stack-1];
500
stack[top_stack-1] = stack[top_stack-2];
501
stack[top_stack-2] = tmp;
511
while (top_stack > 0) {
514
pdf_release_obj(tmp);
520
/* This should be set_bottom and clear (or
521
* have independent stack) to ensure stack
522
* depth do not go below real stack bottom.
525
mps_stack_clear_to (int depth)
529
while (top_stack > depth) {
532
pdf_release_obj(tmp);
539
pop_get_numbers (double *values, int count)
543
while (count-- > 0) {
546
WARN("mpost: Stack underflow.");
548
} else if (!PDF_OBJ_NUMBERTYPE(tmp)) {
549
WARN("mpost: Not a number!");
550
pdf_release_obj(tmp);
553
values[count] = pdf_number_value(tmp);
554
pdf_release_obj(tmp);
561
cvr_array (pdf_obj *array, double *values, int count)
563
if (!PDF_OBJ_ARRAYTYPE(array)) {
564
WARN("mpost: Not an array!");
568
while (count-- > 0) {
569
tmp = pdf_get_array(array, count);
570
if (!PDF_OBJ_NUMBERTYPE(tmp)) {
571
WARN("mpost: Not a number!");
574
values[count] = pdf_number_value(tmp);
578
pdf_release_obj(array);
584
is_fontdict (pdf_obj *dict)
588
if (!PDF_OBJ_DICTTYPE(dict))
591
tmp = pdf_lookup_dict(dict, "Type");
592
if (!tmp || !PDF_OBJ_NAMETYPE(tmp) ||
593
strcmp(pdf_name_value(tmp), "Font")) {
597
tmp = pdf_lookup_dict(dict, "FontName");
598
if (!tmp || !PDF_OBJ_NAMETYPE(tmp)) {
602
tmp = pdf_lookup_dict(dict, "FontScale");
603
if (!tmp || !PDF_OBJ_NUMBERTYPE(tmp)) {
614
pdf_obj *font_dict, *font_name;
616
font_name = POP_STACK();
619
else if (PDF_OBJ_STRINGTYPE(font_name) ||
620
PDF_OBJ_NAMETYPE(font_name)) {
621
/* Do not check the existence...
622
* The reason for this is that we cannot locate PK font without
625
font_dict = pdf_new_dict();
626
pdf_add_dict(font_dict,
627
pdf_new_name("Type"), pdf_new_name("Font"));
628
if (PDF_OBJ_STRINGTYPE(font_name)) {
629
pdf_add_dict(font_dict,
630
pdf_new_name("FontName"),
631
pdf_new_name(pdf_string_value(font_name)));
632
pdf_release_obj(font_name);
634
pdf_add_dict(font_dict,
635
pdf_new_name("FontName"), font_name);
637
pdf_add_dict(font_dict,
638
pdf_new_name("FontScale"), pdf_new_number(1.0));
640
if (top_stack < PS_STACK_SIZE) {
641
stack[top_stack++] = font_dict;
643
WARN("PS stack overflow including MetaPost file or inline PS code");
644
pdf_release_obj(font_dict);
662
error = pop_get_numbers(&scale, 1);
666
font_dict = POP_STACK();
669
else if (is_fontdict(font_dict)) {
670
font_scale = pdf_lookup_dict(font_dict, "FontScale");
671
pdf_set_number(font_scale, pdf_number_value(font_scale)*scale);
672
if (top_stack < PS_STACK_SIZE) {
673
stack[top_stack++] = font_dict;
675
WARN("PS stack overflow including MetaPost file or inline PS code");
676
pdf_release_obj(font_dict);
694
font_dict = POP_STACK();
695
if (!is_fontdict(font_dict))
698
/* Subfont support prevent us from managing
699
* font in a single place...
701
font_name = pdf_name_value (pdf_lookup_dict(font_dict, "FontName"));
702
font_scale = pdf_number_value(pdf_lookup_dict(font_dict, "FontScale"));
704
error = mp_setfont(font_name, font_scale);
706
pdf_release_obj(font_dict);
711
/* Push dummy font dict onto PS stack */
713
do_currentfont (void)
716
struct mp_font *font;
719
font = CURRENT_FONT();
721
WARN("Currentfont undefined...");
724
font_dict = pdf_new_dict();
725
pdf_add_dict(font_dict,
726
pdf_new_name("Type"),
727
pdf_new_name("Font"));
728
pdf_add_dict(font_dict,
729
pdf_new_name("FontName"),
730
pdf_new_name(font->font_name));
731
pdf_add_dict(font_dict,
732
pdf_new_name("FontScale"),
733
pdf_new_number(font->pt_size));
734
if (top_stack < PS_STACK_SIZE) {
735
stack[top_stack++] = font_dict;
737
WARN("PS stack overflow...");
738
pdf_release_obj(font_dict);
749
struct mp_font *font;
753
unsigned char *strptr;
756
font = CURRENT_FONT();
758
WARN("Currentfont not set."); /* Should not be error... */
762
pdf_dev_currentpoint(&cp);
764
text_str = POP_STACK();
765
if (!PDF_OBJ_STRINGTYPE(text_str)) {
767
pdf_release_obj(text_str);
770
if (font->font_id < 0) {
771
WARN("mpost: not set."); /* Should not be error... */
772
pdf_release_obj(text_str);
776
strptr = pdf_string_value (text_str);
777
length = pdf_string_length(text_str);
779
if (font->tfm_id < 0) {
780
WARN("mpost: TFM not found for \"%s\".", font->font_name);
781
WARN("mpost: Text width not calculated...");
785
if (font->subfont_id >= 0) {
790
ustr = NEW(length * 2, unsigned char);
791
for (i = 0; i < length; i++) {
792
uch = lookup_sfd_record(font->subfont_id, strptr[i]);
793
ustr[2*i ] = uch >> 8;
794
ustr[2*i+1] = uch & 0xff;
795
if (font->tfm_id >= 0) {
796
text_width += tfm_get_width(font->tfm_id, strptr[i]);
799
text_width *= font->pt_size;
801
pdf_dev_set_string((spt_t)(cp.x * dev_unit_dviunit()),
802
(spt_t)(cp.y * dev_unit_dviunit()),
804
(spt_t)(text_width*dev_unit_dviunit()),
808
#define FWBASE ((double) (1<<20))
809
if (font->tfm_id >= 0) {
810
text_width = (double) tfm_string_width(font->tfm_id, strptr, length)/FWBASE;
811
text_width *= font->pt_size;
813
pdf_dev_set_string((spt_t)(cp.x * dev_unit_dviunit()),
814
(spt_t)(cp.y * dev_unit_dviunit()),
816
(spt_t)(text_width*dev_unit_dviunit()),
820
if (pdf_dev_get_font_wmode(font->font_id)) {
821
pdf_dev_rmoveto(0.0, -text_width);
823
pdf_dev_rmoveto(text_width, 0.0);
827
pdf_release_obj(text_str);
833
do_mpost_bind_def (const char *ps_code, double x_user, double y_user)
836
const char *start, *end;
839
end = start + strlen(start);
841
error = mp_parse_body(&start, end, x_user, y_user);
847
do_texfig_operator (int opcode, double x_user, double y_user)
849
static transform_info fig_p;
850
static int in_tfig = 0;
851
static int xobj_id = -1;
852
static int count = 0;
858
error = pop_get_numbers(values, 6);
863
transform_info_clear(&fig_p);
864
dvi2pts = 1.0/dev_unit_dviunit();
866
fig_p.width = values[0] * dvi2pts;
867
fig_p.height = values[1] * dvi2pts;
868
fig_p.bbox.llx = values[2] * dvi2pts;
869
fig_p.bbox.lly = -values[3] * dvi2pts;
870
fig_p.bbox.urx = values[4] * dvi2pts;
871
fig_p.bbox.ury = -values[5] * dvi2pts;
872
fig_p.flags |= INFO_HAS_USER_BBOX;
874
sprintf(resname, "__tf%d__", count);
875
xobj_id = pdf_doc_begin_grabbing(resname,
876
fig_p.bbox.llx, fig_p.bbox.ury, &fig_p.bbox);
884
ERROR("endTexFig without valid startTexFig!.");
886
pdf_doc_end_grabbing(NULL);
887
pdf_dev_put_image(xobj_id, &fig_p, x_user, y_user);
902
* CTM(Current Transformation Matrix) means the transformation of User Space
903
* to Device Space coordinates. Because DVIPDFMx does not know the resolution
904
* of Device Space, we assume that the resolution is 1/1000.
906
#define DEVICE_RESOLUTION 1000
908
ps_dev_CTM (pdf_tmatrix *M)
910
pdf_dev_currentmatrix(M);
911
M->a *= DEVICE_RESOLUTION; M->b *= DEVICE_RESOLUTION;
912
M->c *= DEVICE_RESOLUTION; M->d *= DEVICE_RESOLUTION;
913
M->e *= DEVICE_RESOLUTION; M->f *= DEVICE_RESOLUTION;
919
* Again, the only piece that needs x_user and y_user is
920
* that piece dealing with texfig.
923
do_operator (const char *token, double x_user, double y_user)
934
if (top_stack < PS_STACK_SIZE) { \
935
stack[top_stack++] = (o); \
937
WARN("PS stack overflow including MetaPost file or inline PS code"); \
943
opcode = get_opcode(token);
948
* Arithmetic operators
951
error = pop_get_numbers(values, 2);
953
PUSH(pdf_new_number(values[0] + values[1]));
956
error = pop_get_numbers(values, 2);
958
PUSH(pdf_new_number(values[0]*values[1]));
961
error = pop_get_numbers(values, 1);
963
PUSH(pdf_new_number(-values[0]));
966
error = pop_get_numbers(values, 2);
968
PUSH(pdf_new_number(values[0] - values[1]));
971
error = pop_get_numbers(values, 2);
973
PUSH(pdf_new_number(values[0]/values[1]));
975
case TRUNCATE: /* Round toward zero. */
976
error = pop_get_numbers(values, 1);
978
PUSH(pdf_new_number(((values[0] > 0) ? floor(values[0]) : ceil(values[0]))));
981
/* Stack operation */
988
pdf_release_obj(tmp);
994
/* Path construction */
996
error = pop_get_numbers(values, 2);
998
error = pdf_dev_moveto(values[0], values[1]);
1001
error = pop_get_numbers(values, 2);
1003
error = pdf_dev_rmoveto(values[0], values[1]);
1006
error = pop_get_numbers(values, 2);
1008
error = pdf_dev_lineto(values[0], values[1]);
1011
error = pop_get_numbers(values, 2);
1013
error = pdf_dev_rlineto(values[0], values[1]);
1016
error = pop_get_numbers(values, 6);
1018
error = pdf_dev_curveto(values[0], values[1],
1019
values[2], values[3],
1020
values[4], values[5]);
1023
error = pop_get_numbers(values, 6);
1025
error = pdf_dev_rcurveto(values[0], values[1],
1026
values[2], values[3],
1027
values[4], values[5]);
1030
error = pdf_dev_closepath();
1033
error = pop_get_numbers(values, 5);
1035
error = pdf_dev_arc(values[0], values[1],
1036
values[2], /* rad */
1037
values[3], values[4]);
1040
error = pop_get_numbers(values, 5);
1042
error = pdf_dev_arcn(values[0], values[1],
1043
values[2], /* rad */
1044
values[3], values[4]);
1051
/* fill rule not supported yet */
1052
pdf_dev_flushpath('S', PDF_FILL_RULE_NONZERO);
1055
pdf_dev_flushpath('f', PDF_FILL_RULE_NONZERO);
1059
error = pdf_dev_clip();
1062
error = pdf_dev_eoclip();
1065
/* Graphics state operators: */
1067
error = pdf_dev_gsave();
1071
error = pdf_dev_grestore();
1077
error = cvr_array(tmp, values, 6); /* This does pdf_release_obj() */
1080
WARN("Missing array before \"concat\".");
1082
pdf_setmatrix(&matrix,
1083
values[0], values[1],
1084
values[2], values[3],
1085
values[4], values[5]);
1086
error = pdf_dev_concat(&matrix);
1090
error = pop_get_numbers(values, 2);
1093
#ifndef WITHOUT_ASCII_PTEX
1094
case MP_CMODE_PTEXVERT:
1095
pdf_setmatrix(&matrix,
1100
#endif /* !WITHOUT_ASCII_PTEX */
1102
pdf_setmatrix(&matrix,
1109
error = pdf_dev_concat(&matrix);
1112
/* Positive angle means clock-wise direction in graphicx-dvips??? */
1114
error = pop_get_numbers(values, 1);
1116
values[0] = values[0] * M_PI / 180;
1119
case MP_CMODE_DVIPSK:
1120
case MP_CMODE_MPOST: /* Really? */
1121
#ifndef WITHOUT_ASCII_PTEX
1122
case MP_CMODE_PTEXVERT:
1123
#endif /* !WITHOUT_ASCII_PTEX */
1124
pdf_setmatrix(&matrix,
1125
cos(values[0]), -sin(values[0]),
1126
sin(values[0]), cos(values[0]),
1130
pdf_setmatrix(&matrix,
1131
cos(values[0]) , sin(values[0]),
1132
-sin(values[0]), cos(values[0]),
1136
error = pdf_dev_concat(&matrix);
1140
error = pop_get_numbers(values, 2);
1142
pdf_setmatrix(&matrix,
1145
values[0], values[1]);
1146
error = pdf_dev_concat(&matrix);
1151
error = pop_get_numbers(values, 1);
1153
pdf_obj *pattern, *dash;
1155
double dash_values[PDF_DASH_SIZE_MAX];
1159
pattern = POP_STACK();
1160
if (!PDF_OBJ_ARRAYTYPE(pattern)) {
1162
pdf_release_obj(pattern);
1166
num_dashes = pdf_array_length(pattern);
1167
if (num_dashes > PDF_DASH_SIZE_MAX) {
1168
WARN("Too many dashes...");
1169
pdf_release_obj(pattern);
1174
i < num_dashes && !error ; i++) {
1175
dash = pdf_get_array(pattern, i);
1176
if (!PDF_OBJ_NUMBERTYPE(dash))
1179
dash_values[i] = pdf_number_value(dash);
1182
pdf_release_obj(pattern);
1184
error = pdf_dev_setdash(num_dashes, dash_values, offset);
1189
error = pop_get_numbers(values, 1);
1191
error = pdf_dev_setlinecap(values[0]);
1194
error = pop_get_numbers(values, 1);
1196
error = pdf_dev_setlinejoin(values[0]);
1199
error = pop_get_numbers(values, 1);
1201
error = pdf_dev_setlinewidth(values[0]);
1204
error = pop_get_numbers(values, 1);
1206
error = pdf_dev_setmiterlimit(values[0]);
1210
error = pop_get_numbers(values, 4);
1211
/* Not handled properly */
1213
pdf_color_cmykcolor(&color,
1214
values[0], values[1],
1215
values[2], values[3]);
1216
pdf_dev_set_strokingcolor(&color);
1217
pdf_dev_set_nonstrokingcolor(&color);
1221
/* Not handled properly */
1222
error = pop_get_numbers(values, 1);
1224
pdf_color_graycolor(&color, values[0]);
1225
pdf_dev_set_strokingcolor(&color);
1226
pdf_dev_set_nonstrokingcolor(&color);
1230
error = pop_get_numbers(values, 3);
1232
pdf_color_rgbcolor(&color,
1233
values[0], values[1], values[2]);
1234
pdf_dev_set_strokingcolor(&color);
1235
pdf_dev_set_nonstrokingcolor(&color);
1239
case SHOWPAGE: /* Let's ignore this for now */
1243
error = pdf_dev_currentpoint(&cp);
1245
PUSH(pdf_new_number(cp.x));
1246
PUSH(pdf_new_number(cp.y));
1255
if (PDF_OBJ_ARRAYTYPE(tmp)) {
1256
error = cvr_array(tmp, values, 6); /* This does pdf_release_obj() */
1260
pdf_setmatrix(&matrix,
1261
values[0], values[1],
1262
values[2], values[3],
1263
values[4], values[5]);
1268
if (!PDF_OBJ_NUMBERTYPE(tmp)) {
1272
cp.y = pdf_number_value(tmp);
1273
pdf_release_obj(tmp);
1276
if (!PDF_OBJ_NUMBERTYPE(tmp)) {
1280
cp.x = pdf_number_value(tmp);
1281
pdf_release_obj(tmp);
1284
ps_dev_CTM(&matrix); /* Here, we need real PostScript CTM */
1286
pdf_dev_dtransform(&cp, &matrix);
1287
PUSH(pdf_new_number(cp.x));
1288
PUSH(pdf_new_number(cp.y));
1297
if (PDF_OBJ_ARRAYTYPE(tmp)) {
1298
error = cvr_array(tmp, values, 6); /* This does pdf_release_obj() */
1302
pdf_setmatrix(&matrix,
1303
values[0], values[1],
1304
values[2], values[3],
1305
values[4], values[5]);
1310
if (!PDF_OBJ_NUMBERTYPE(tmp)) {
1314
cp.y = pdf_number_value(tmp);
1315
pdf_release_obj(tmp);
1318
if (!PDF_OBJ_NUMBERTYPE(tmp)) {
1322
cp.x = pdf_number_value(tmp);
1323
pdf_release_obj(tmp);
1326
ps_dev_CTM(&matrix); /* Here, we need real PostScript CTM */
1328
pdf_dev_idtransform(&cp, &matrix);
1329
PUSH(pdf_new_number(cp.x));
1330
PUSH(pdf_new_number(cp.y));
1335
error = do_findfont();
1338
error = do_scalefont();
1341
error = do_setfont();
1344
error = do_currentfont();
1357
error = do_mpost_bind_def("exch findfont exch scalefont setfont show", x_user, y_user);
1361
error = do_texfig_operator(opcode, x_user, y_user);
1364
error = do_mpost_bind_def("0 dtransform exch truncate exch idtransform pop setlinewidth", x_user, y_user);
1367
error = do_mpost_bind_def("0 exch dtransform truncate idtransform setlinewidth pop", x_user, y_user);
1370
error = do_mpost_bind_def("[] 0 setdash", x_user, y_user);
1373
error = do_mpost_bind_def("gsave fill grestore", x_user, y_user);
1379
/* do nothing; not implemented yet */
1383
if (is_fontname(token)) {
1384
PUSH(pdf_new_name(token));
1386
WARN("Unknown token \"%s\"", token);
1396
* The only sections that need to know x_user and y _user are those
1397
* dealing with texfig.
1400
mp_parse_body (const char **start, const char *end, double x_user, double y_user)
1406
skip_white(start, end);
1407
while (*start < end && !error) {
1408
if (isdigit(**start) ||
1409
(*start < end - 1 &&
1410
(**start == '+' || **start == '-' || **start == '.' ))) {
1414
value = strtod(*start, &next);
1415
if (next < end && !strchr("<([{/%", *next) && !isspace(*next)) {
1416
WARN("Unkown PostScript operator.");
1420
PUSH(pdf_new_number(value));
1424
* PDF parser can't handle PS operator inside arrays.
1425
* This shouldn't use parse_pdf_array().
1427
} else if (**start == '[' &&
1428
(obj = parse_pdf_array(start, end, NULL))) {
1430
/* This cannot handle ASCII85 string. */
1431
} else if (*start < end - 1 &&
1432
(**start == '<' && *(*start+1) == '<') &&
1433
(obj = parse_pdf_dict(start, end, NULL))) {
1435
} else if ((**start == '(' || **start == '<') &&
1436
(obj = parse_pdf_string (start, end))) {
1438
} else if (**start == '/' &&
1439
(obj = parse_pdf_name(start, end))) {
1442
token = parse_ident(start, end);
1446
error = do_operator(token, x_user, y_user);
1450
skip_white(start, end);
1457
mps_eop_cleanup (void)
1464
mps_stack_depth (void)
1470
mps_exec_inline (const char **p, const char *endptr,
1471
double x_user, double y_user)
1474
int dirmode, autorotate;
1476
/* Compatibility for dvipsk. */
1477
dirmode = pdf_dev_get_dirmode();
1479
mp_cmode = MP_CMODE_PTEXVERT;
1481
mp_cmode = MP_CMODE_DVIPSK;
1484
autorotate = pdf_dev_get_param(PDF_DEV_PARAM_AUTOROTATE);
1485
pdf_dev_set_param(PDF_DEV_PARAM_AUTOROTATE, 0);
1486
//pdf_color_push(); /* ... */
1488
/* Comment in dvipdfm:
1489
* Remember that x_user and y_user are off by 0.02 %
1491
pdf_dev_moveto(x_user, y_user);
1492
error = mp_parse_body(p, endptr, x_user, y_user);
1494
//pdf_color_pop(); /* ... */
1495
pdf_dev_set_param(PDF_DEV_PARAM_AUTOROTATE, autorotate);
1496
pdf_dev_set_dirmode(dirmode);
1501
/* mp inclusion is a bit of a hack. The routine
1502
* starts a form at the lower left corner of
1503
* the page and then calls begin_form_xobj telling
1504
* it to record the image drawn there and bundle it
1505
* up in an xojbect. This allows us to use the coordinates
1506
* in the MP file directly. This appears to be the
1507
* easiest way to be able to use the pdf_dev_set_string()
1508
* command (with its scaled and extended fonts) without
1509
* getting all confused about the coordinate system.
1510
* After the xobject is created, the whole thing can
1511
* be scaled any way the user wants
1514
/* Should implement save and restore. */
1516
mps_include_page (const char *ident, FILE *fp)
1520
int st_depth, gs_depth;
1522
const char *p, *endptr;
1523
long length, nb_read;
1524
int dirmode, autorotate, error;
1528
length = file_size(fp);
1530
WARN("Can't read any byte in the MPS file.");
1534
buffer = NEW(length + 1, char);
1535
buffer[length] = '\0';
1537
endptr = p + length;
1539
while (length > 0) {
1540
nb_read = fread(buffer, sizeof(char), length, fp);
1543
WARN("Reading file failed...");
1549
error = mps_scan_bbox(&p, endptr, &(info.bbox));
1551
WARN("Error occured while scanning MetaPost file headers: Could not find BoundingBox.");
1555
skip_prolog(&p, endptr);
1557
dirmode = pdf_dev_get_dirmode();
1558
autorotate = pdf_dev_get_param(PDF_DEV_PARAM_AUTOROTATE);
1559
pdf_dev_set_param(PDF_DEV_PARAM_AUTOROTATE, 0);
1562
form_id = pdf_doc_begin_grabbing(ident, 0.0, 0.0, &(info.bbox));
1564
mp_cmode = MP_CMODE_MPOST;
1565
gs_depth = pdf_dev_current_depth();
1566
st_depth = mps_stack_depth();
1567
/* At this point the gstate must be initialized, since it starts a new
1568
* XObject. Note that it increase gs_depth by 1. */
1569
pdf_dev_push_gstate();
1571
error = mp_parse_body(&p, endptr, 0.0, 0.0);
1575
WARN("Errors occured while interpreting MPS file.");
1576
/* WARN("Leaving garbage in output PDF file."); */
1580
/* It's time to pop the new gstate above. */
1581
pdf_dev_pop_gstate();
1582
mps_stack_clear_to (st_depth);
1583
pdf_dev_grestore_to(gs_depth);
1585
pdf_doc_end_grabbing(NULL);
1588
pdf_dev_set_param(PDF_DEV_PARAM_AUTOROTATE, autorotate);
1589
pdf_dev_set_dirmode(dirmode);
1595
mps_do_page (FILE *image_file)
1600
const char *start, *end;
1605
if ((size = file_size(image_file)) == 0) {
1606
WARN("Can't read any byte in the MPS file.");
1610
buffer = NEW(size+1, char);
1611
fread(buffer, sizeof(char), size, image_file);
1614
end = buffer + size;
1616
error = mps_scan_bbox(&start, end, &bbox);
1618
WARN("Error occured while scanning MetaPost file headers: Could not find BoundingBox.");
1623
mp_cmode = MP_CMODE_MPOST;
1625
pdf_doc_begin_page (1.0, 0.0, 0.0); /* scale, xorig, yorig */
1626
pdf_doc_set_mediabox(pdf_doc_current_page_number(), &bbox);
1628
dir_mode = pdf_dev_get_dirmode();
1629
pdf_dev_set_autorotate(0);
1631
skip_prolog(&start, end);
1633
error = mp_parse_body(&start, end, 0.0, 0.0);
1636
WARN("Errors occured while interpreting MetaPost file.");
1639
pdf_dev_set_autorotate(1);
1640
pdf_dev_set_dirmode(dir_mode);
1647
* The reason why we don't return XObject itself is
1648
* PDF inclusion may not be made so.
1650
return (error ? -1 : 0);
1654
check_for_mp (FILE *image_file)
1658
rewind (image_file);
1659
mfgets(work_buffer, WORK_BUFFER_SIZE, image_file);
1660
if (strncmp(work_buffer, "%!PS", 4))
1663
while (try_count > 0) {
1664
mfgets(work_buffer, WORK_BUFFER_SIZE, image_file);
1665
if (!strncmp(work_buffer, "%%Creator:", 10)) {
1666
if (strlen(work_buffer+10) >= 8 &&
1667
strstr(work_buffer+10, "MetaPost"))
1673
return ((try_count > 0) ? 1 : 0);