p_defplot.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. /* This file is part of the GNU plotutils package. Copyright (C) 1995,
  2. 1996, 1997, 1998, 1999, 2000, 2005, 2008, 2009, Free Software
  3. Foundation, Inc.
  4. The GNU plotutils package is free software. You may redistribute it
  5. and/or modify it under the terms of the GNU General Public License as
  6. published by the Free Software foundation; either version 2, or (at your
  7. option) any later version.
  8. The GNU plotutils package is distributed in the hope that it will be
  9. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License along
  13. with the GNU plotutils package; see the file COPYING. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  15. Boston, MA 02110-1301, USA. */
  16. /* This file defines the initialization for any PSPlotter object, including
  17. both private data and public methods. There is a one-to-one
  18. correspondence between public methods and user-callable functions in the
  19. C API. */
  20. #include "sys-defines.h"
  21. #include "extern.h"
  22. /* ctime_r() is currently not used, because there is apparently _no_
  23. universal way of ensuring that it is declared. On some systems
  24. (e.g. Red Hat Linux), `#define _POSIX_SOURCE' will do it. But on other
  25. systems, doing `#define _POSIX_SOURCE' **removes** the declaration! */
  26. #ifdef HAVE_CTIME_R
  27. #undef HAVE_CTIME_R
  28. #endif
  29. #ifdef MSDOS
  30. #include <unistd.h> /* for fsync() */
  31. #endif
  32. /* song and dance to define time_t, and declare both time() and ctime() */
  33. #ifdef HAVE_SYS_TYPES_H
  34. #include <sys/types.h> /* for time_t on some pre-ANSI Unix systems */
  35. #endif
  36. #ifdef TIME_WITH_SYS_TIME
  37. #include <sys/time.h> /* for time() on some pre-ANSI Unix systems */
  38. #include <time.h> /* for ctime() */
  39. #else /* not TIME_WITH_SYS_TIME, include only one (prefer <sys/time.h>) */
  40. #ifdef HAVE_SYS_TIME_H
  41. #include <sys/time.h>
  42. #else /* not HAVE_SYS_TIME_H */
  43. #include <time.h>
  44. #endif /* not HAVE_SYS_TIME_H */
  45. #endif /* not TIME_WITH_SYS_TIME */
  46. #include "p_header.h" /* idraw Postscript header (from InterViews) */
  47. #ifndef LIBPLOTTER
  48. /* In libplot, this is the initialization for the function-pointer part of
  49. a PSPlotter struct. */
  50. const Plotter _pl_p_default_plotter =
  51. {
  52. /* initialization (after creation) and termination (before deletion) */
  53. _pl_p_initialize, _pl_p_terminate,
  54. /* page manipulation */
  55. _pl_p_begin_page, _pl_p_erase_page, _pl_p_end_page,
  56. /* drawing state manipulation */
  57. _pl_g_push_state, _pl_g_pop_state,
  58. /* internal path-painting methods (endpath() is a wrapper for the first) */
  59. _pl_p_paint_path, _pl_p_paint_paths, _pl_g_path_is_flushable, _pl_g_maybe_prepaint_segments,
  60. /* internal methods for drawing of markers and points */
  61. _pl_g_paint_marker, _pl_p_paint_point,
  62. /* internal methods that plot strings in Hershey, non-Hershey fonts */
  63. _pl_g_paint_text_string_with_escapes, _pl_p_paint_text_string,
  64. _pl_g_get_text_width,
  65. /* private low-level `retrieve font' method */
  66. _pl_g_retrieve_font,
  67. /* `flush output' method, called only if Plotter handles its own output */
  68. _pl_g_flush_output,
  69. /* error handlers */
  70. _pl_g_warning,
  71. _pl_g_error,
  72. };
  73. #endif /* not LIBPLOTTER */
  74. /* The private `initialize' method, which is invoked when a Plotter is
  75. created. It is used for such things as initializing capability flags
  76. from the values of class variables, allocating storage, etc. When this
  77. is invoked, _plotter points to the Plotter that has just been
  78. created. */
  79. /* For PS Plotter objects, we initialize the used-font array(s). We also
  80. determine the page size and the location on the page of the graphics
  81. display, so that we'll be able to work out the map from user coordinates
  82. to device coordinates in space.c. */
  83. void
  84. _pl_p_initialize (S___(Plotter *_plotter))
  85. {
  86. #ifndef LIBPLOTTER
  87. /* in libplot, manually invoke superclass initialization method */
  88. _pl_g_initialize (S___(_plotter));
  89. #endif
  90. /* override generic initializations (which are appropriate to the base
  91. Plotter class), as necessary */
  92. #ifndef LIBPLOTTER
  93. /* tag field, differs in derived classes */
  94. _plotter->data->type = PL_PS;
  95. #endif
  96. /* output model */
  97. _plotter->data->output_model = PL_OUTPUT_PAGES_ALL_AT_ONCE;
  98. /* user-queryable capabilities: 0/1/2 = no/yes/maybe */
  99. _plotter->data->have_wide_lines = 1;
  100. _plotter->data->have_dash_array = 1;
  101. _plotter->data->have_solid_fill = 1;
  102. _plotter->data->have_odd_winding_fill = 1;
  103. _plotter->data->have_nonzero_winding_fill = 1;
  104. _plotter->data->have_settable_bg = 0;
  105. _plotter->data->have_escaped_string_support = 0;
  106. _plotter->data->have_ps_fonts = 1;
  107. #ifdef USE_LJ_FONTS_IN_PS
  108. _plotter->data->have_pcl_fonts = 1;
  109. #else
  110. _plotter->data->have_pcl_fonts = 0;
  111. #endif
  112. _plotter->data->have_stick_fonts = 0;
  113. _plotter->data->have_extra_stick_fonts = 0;
  114. _plotter->data->have_other_fonts = 0;
  115. /* text and font-related parameters (internal, not queryable by user);
  116. note that we don't set kern_stick_fonts, because it was set by the
  117. superclass initialization (and it's irrelevant for this Plotter type,
  118. anyway) */
  119. _plotter->data->default_font_type = PL_F_POSTSCRIPT;
  120. _plotter->data->pcl_before_ps = false;
  121. _plotter->data->have_horizontal_justification = false;
  122. _plotter->data->have_vertical_justification = false;
  123. _plotter->data->issue_font_warning = true;
  124. /* path-related parameters (also internal); note that we
  125. don't set max_unfilled_path_length, because it was set by the
  126. superclass initialization */
  127. _plotter->data->have_mixed_paths = false;
  128. _plotter->data->allowed_arc_scaling = AS_NONE;
  129. _plotter->data->allowed_ellarc_scaling = AS_NONE;
  130. _plotter->data->allowed_quad_scaling = AS_NONE;
  131. _plotter->data->allowed_cubic_scaling = AS_NONE;
  132. _plotter->data->allowed_box_scaling = AS_ANY;
  133. _plotter->data->allowed_circle_scaling = AS_ANY;
  134. _plotter->data->allowed_ellipse_scaling = AS_ANY;
  135. /* color-related parameters (also internal) */
  136. _plotter->data->emulate_color = false;
  137. /* dimensions */
  138. _plotter->data->display_model_type = (int)DISP_MODEL_PHYSICAL;
  139. _plotter->data->display_coors_type = (int)DISP_DEVICE_COORS_REAL;
  140. _plotter->data->flipped_y = false;
  141. _plotter->data->imin = 0;
  142. _plotter->data->imax = 0;
  143. _plotter->data->jmin = 0;
  144. _plotter->data->jmax = 0;
  145. _plotter->data->xmin = 0.0;
  146. _plotter->data->xmax = 0.0;
  147. _plotter->data->ymin = 0.0;
  148. _plotter->data->ymax = 0.0;
  149. _plotter->data->page_data = (plPageData *)NULL;
  150. /* initialize certain data members from device driver parameters */
  151. /* Determine range of device coordinates over which the viewport will
  152. extend (and hence the transformation from user to device coordinates;
  153. see g_space.c). */
  154. {
  155. /* determine page type, viewport size and location */
  156. _set_page_type (_plotter->data);
  157. /* convert viewport size-and-location data (in terms of inches) to
  158. device coordinates (i.e. points) */
  159. _plotter->data->xmin = 72 * (_plotter->data->viewport_xorigin
  160. + _plotter->data->viewport_xoffset);
  161. _plotter->data->xmax = 72 * (_plotter->data->viewport_xorigin
  162. + _plotter->data->viewport_xoffset
  163. + _plotter->data->viewport_xsize);
  164. _plotter->data->ymin = 72 * (_plotter->data->viewport_yorigin
  165. + _plotter->data->viewport_yoffset);
  166. _plotter->data->ymax = 72 * (_plotter->data->viewport_yorigin
  167. + _plotter->data->viewport_yoffset
  168. + _plotter->data->viewport_ysize);
  169. }
  170. /* compute the NDC to device-frame affine map, set it in Plotter */
  171. _compute_ndc_to_device_map (_plotter->data);
  172. }
  173. /* The private `terminate' method, which is invoked when a Plotter is
  174. deleted. It may do such things as write to an output stream from
  175. internal storage, deallocate storage, etc. When this is invoked,
  176. _plotter points to the Plotter that is about to be deleted. */
  177. /* This version is for Postscript Plotters. It writes out the
  178. idraw-derived PS prologue to the output stream, and copies each stored
  179. page of graphics to it too, making sure to include the proper DSC
  180. [Document Structuring Convention] comment lines at the beginning and the
  181. end of the document, and at the beginning and end of each page.
  182. (PS Plotters differ from most other plotters that do not plot in real
  183. time in that they emit output only after all pages have pages have been
  184. drawn, rather than at the end of each page. This is necessary for DSC
  185. compliance.)
  186. When this is called, the PS code for the body of each page is stored in
  187. a plOutbuf, and the page plOutbufs form a linked list. In this function
  188. we write the document header, the document trailer, and the
  189. header/trailer for each page, all to separate plOutbufs. We then copy
  190. the plOutbufs, one after another, to the output stream. */
  191. void
  192. _pl_p_terminate (S___(Plotter *_plotter))
  193. {
  194. double x_min, x_max, y_min, y_max;
  195. int i, n;
  196. time_t clock;
  197. plOutbuf *doc_header, *doc_trailer, *current_page;
  198. bool ps_font_used_in_doc[PL_NUM_PS_FONTS];
  199. #ifdef USE_LJ_FONTS_IN_PS
  200. bool pcl_font_used_in_doc[PL_NUM_PCL_FONTS];
  201. #endif
  202. char *time_string, time_string_buffer[32];
  203. #ifdef LIBPLOTTER
  204. if (_plotter->data->outfp || _plotter->data->outstream)
  205. #else
  206. if (_plotter->data->outfp)
  207. #endif
  208. /* have an output stream */
  209. {
  210. int num_pages = _plotter->data->page_number;
  211. /* First, prepare the document header (DSC lines, etc.), and write it
  212. to a plOutbuf. The header is very long: most of it is simply the
  213. idraw header (see p_header.h). */
  214. doc_header = _new_outbuf ();
  215. if (num_pages == 1)
  216. /* will plot an EPS file, not just a PS file */
  217. sprintf (doc_header->point, "\
  218. %%!PS-Adobe-3.0 EPSF-3.0\n");
  219. else
  220. sprintf (doc_header->point, "\
  221. %%!PS-Adobe-3.0\n");
  222. _update_buffer (doc_header);
  223. /* Compute an ASCII representation of the current time, in a
  224. reentrant way if we're supporting pthreads (i.e. by using ctime_r
  225. if it's available). */
  226. time (&clock);
  227. #ifdef PTHREAD_SUPPORT
  228. #ifdef HAVE_PTHREAD_H
  229. #ifdef HAVE_CTIME_R
  230. ctime_r (&clock, time_string_buffer);
  231. time_string = time_string_buffer;
  232. #else
  233. time_string = ctime (&clock);
  234. #endif
  235. #else
  236. time_string = ctime (&clock);
  237. #endif
  238. #else
  239. time_string = ctime (&clock);
  240. #endif
  241. sprintf (doc_header->point, "\
  242. %%%%Creator: GNU libplot drawing library %s\n\
  243. %%%%Title: PostScript plot\n\
  244. %%%%CreationDate: %s\
  245. %%%%DocumentData: Clean7Bit\n\
  246. %%%%LanguageLevel: 1\n\
  247. %%%%Pages: %d\n\
  248. %%%%PageOrder: Ascend\n\
  249. %%%%Orientation: Portrait\n",
  250. PL_LIBPLOT_VER_STRING, time_string, num_pages);
  251. _update_buffer (doc_header);
  252. /* emit the bounding box for the document */
  253. _bbox_of_outbufs (_plotter->data->first_page, &x_min, &x_max, &y_min, &y_max);
  254. if (x_min > x_max || y_min > y_max)
  255. /* all pages empty */
  256. sprintf (doc_header->point, "\
  257. %%%%BoundingBox: 0 0 0 0\n");
  258. else
  259. sprintf (doc_header->point, "\
  260. %%%%BoundingBox: %d %d %d %d\n",
  261. IROUND(x_min - 0.5), IROUND(y_min - 0.5),
  262. IROUND(x_max + 0.5), IROUND(y_max + 0.5));
  263. _update_buffer (doc_header);
  264. /* determine fonts needed by document, by examining all pages */
  265. {
  266. current_page = _plotter->data->first_page;
  267. for (i = 0; i < PL_NUM_PS_FONTS; i++)
  268. ps_font_used_in_doc[i] = false;
  269. #ifdef USE_LJ_FONTS_IN_PS
  270. for (i = 0; i < PL_NUM_PCL_FONTS; i++)
  271. pcl_font_used_in_doc[i] = false;
  272. #endif
  273. while (current_page)
  274. {
  275. for (i = 0; i < PL_NUM_PS_FONTS; i++)
  276. if (current_page->ps_font_used[i])
  277. ps_font_used_in_doc[i] = true;
  278. #ifdef USE_LJ_FONTS_IN_PS
  279. for (i = 0; i < PL_NUM_PCL_FONTS; i++)
  280. if (current_page->pcl_font_used[i])
  281. pcl_font_used_in_doc[i] = true;
  282. #endif
  283. current_page = current_page->next;
  284. }
  285. }
  286. /* write out list of fonts needed by the document */
  287. {
  288. bool first_font = true;
  289. strcpy (doc_header->point, "\
  290. %%DocumentNeededResources: ");
  291. _update_buffer (doc_header);
  292. for (i = 0; i < PL_NUM_PS_FONTS; i++)
  293. {
  294. if (ps_font_used_in_doc[i])
  295. {
  296. if (first_font == false)
  297. {
  298. strcpy (doc_header->point, "%%+ ");
  299. _update_buffer (doc_header);
  300. }
  301. strcpy (doc_header->point, "font ");
  302. _update_buffer (doc_header);
  303. strcpy (doc_header->point, _pl_g_ps_font_info[i].ps_name);
  304. _update_buffer (doc_header);
  305. strcpy (doc_header->point, "\n");
  306. _update_buffer (doc_header);
  307. first_font = false;
  308. }
  309. }
  310. #ifdef USE_LJ_FONTS_IN_PS
  311. for (i = 0; i < PL_NUM_PCL_FONTS; i++)
  312. {
  313. if (pcl_font_used_in_doc[i])
  314. {
  315. if (first_font == false)
  316. {
  317. strcpy (doc_header->point, "%%+ ");
  318. _update_buffer (doc_header);
  319. }
  320. strcpy (doc_header->point, "font ");
  321. _update_buffer (doc_header);
  322. /* use replacement font name if any (this is only to
  323. support the Tidbits-is-Wingdings botch) */
  324. if (_pl_g_pcl_font_info[i].substitute_ps_name)
  325. strcpy (doc_header->point, _pl_g_pcl_font_info[i].substitute_ps_name);
  326. else
  327. strcpy (doc_header->point, _pl_g_pcl_font_info[i].ps_name);
  328. _update_buffer (doc_header);
  329. strcpy (doc_header->point, "\n");
  330. _update_buffer (doc_header);
  331. first_font = false;
  332. }
  333. }
  334. #endif
  335. if (first_font) /* no fonts needed in document */
  336. {
  337. strcpy (doc_header->point, "\n");
  338. _update_buffer (doc_header);
  339. }
  340. }
  341. /* emit final DSC lines in header */
  342. if (num_pages > 0)
  343. {
  344. sprintf (doc_header->point, "\
  345. %%%%DocumentSuppliedResources: procset %s %s 0\n",
  346. PS_PROCSET_NAME, PS_PROCSET_VERSION);
  347. _update_buffer (doc_header);
  348. }
  349. strcpy (doc_header->point, "\
  350. %%EndComments\n\n");
  351. _update_buffer (doc_header);
  352. /* write out list of fonts needed by the document, all over again;
  353. this time it's interpreted as the default font list for each page */
  354. {
  355. bool first_font = true;
  356. strcpy (doc_header->point, "\
  357. %%BeginDefaults\n");
  358. _update_buffer (doc_header);
  359. strcpy (doc_header->point, "\
  360. %%PageResources: ");
  361. _update_buffer (doc_header);
  362. for (i = 0; i < PL_NUM_PS_FONTS; i++)
  363. {
  364. if (ps_font_used_in_doc[i])
  365. {
  366. if (first_font == false)
  367. {
  368. strcpy (doc_header->point, "%%+ ");
  369. _update_buffer (doc_header);
  370. }
  371. strcpy (doc_header->point, "font ");
  372. _update_buffer (doc_header);
  373. strcpy (doc_header->point, _pl_g_ps_font_info[i].ps_name);
  374. _update_buffer (doc_header);
  375. strcpy (doc_header->point, "\n");
  376. _update_buffer (doc_header);
  377. first_font = false;
  378. }
  379. }
  380. #ifdef USE_LJ_FONTS_IN_PS
  381. for (i = 0; i < PL_NUM_PCL_FONTS; i++)
  382. {
  383. if (pcl_font_used_in_doc[i])
  384. {
  385. if (first_font == false)
  386. {
  387. strcpy (doc_header->point, "%%+ ");
  388. _update_buffer (doc_header);
  389. }
  390. strcpy (doc_header->point, "font ");
  391. _update_buffer (doc_header);
  392. if (_pl_g_pcl_font_info[i].substitute_ps_name)
  393. /* this is to support the Tidbits-is-Wingdings botch */
  394. strcpy (doc_header->point, _pl_g_pcl_font_info[i].substitute_ps_name);
  395. else
  396. strcpy (doc_header->point, _pl_g_pcl_font_info[i].ps_name);
  397. _update_buffer (doc_header);
  398. strcpy (doc_header->point, "\n");
  399. _update_buffer (doc_header);
  400. first_font = false;
  401. }
  402. }
  403. #endif
  404. if (first_font) /* no fonts needed in document */
  405. {
  406. strcpy (doc_header->point, "\n");
  407. _update_buffer (doc_header);
  408. }
  409. strcpy (doc_header->point, "\
  410. %%EndDefaults\n\n");
  411. _update_buffer (doc_header);
  412. }
  413. /* Document Prolog */
  414. strcpy (doc_header->point, "\
  415. %%BeginProlog\n");
  416. _update_buffer (doc_header);
  417. if (num_pages > 1)
  418. /* PS [not EPS] file, include procset in document prolog */
  419. {
  420. sprintf (doc_header->point, "\
  421. %%%%BeginResource: procset %s %s 0\n",
  422. PS_PROCSET_NAME, PS_PROCSET_VERSION);
  423. _update_buffer (doc_header);
  424. /* write out idraw-derived PS prologue (makes many definitions) */
  425. for (i=0; *_ps_procset[i]; i++)
  426. {
  427. strcpy (doc_header->point, _ps_procset[i]);
  428. _update_buffer (doc_header);
  429. }
  430. strcpy (doc_header->point, "\
  431. %%EndResource\n");
  432. _update_buffer (doc_header);
  433. }
  434. strcpy (doc_header->point, "\
  435. %%EndProlog\n\n");
  436. _update_buffer (doc_header);
  437. /* Document Setup */
  438. strcpy (doc_header->point, "\
  439. %%BeginSetup\n");
  440. _update_buffer (doc_header);
  441. /* tell driver to include any PS [or PCL] fonts that are needed */
  442. for (i = 0; i < PL_NUM_PS_FONTS; i++)
  443. if (ps_font_used_in_doc[i])
  444. {
  445. sprintf (doc_header->point, "\
  446. %%%%IncludeResource: font %s\n", _pl_g_ps_font_info[i].ps_name);
  447. _update_buffer (doc_header);
  448. }
  449. #ifdef USE_LJ_FONTS_IN_PS
  450. for (i = 0; i < PL_NUM_PCL_FONTS; i++)
  451. if (pcl_font_used_in_doc[i])
  452. {
  453. /* this is to support the Tidbits-is-Wingdings botch */
  454. if (_pl_g_pcl_font_info[i].substitute_ps_name)
  455. sprintf (doc_header->point, "\
  456. %%%%IncludeResource: font %s\n", _pl_g_pcl_font_info[i].substitute_ps_name);
  457. else
  458. sprintf (doc_header->point, "\
  459. %%%%IncludeResource: font %s\n", _pl_g_pcl_font_info[i].ps_name);
  460. _update_buffer (doc_header);
  461. }
  462. #endif
  463. /* push private dictionary on stack */
  464. strcpy (doc_header->point, "\
  465. /DrawDict 50 dict def\n\
  466. DrawDict begin\n");
  467. _update_buffer (doc_header);
  468. /* do ISO-Latin-1 reencoding for any fonts that need it */
  469. {
  470. bool need_to_reencode = false;
  471. for (i = 0; i < PL_NUM_PS_FONTS; i++)
  472. if (ps_font_used_in_doc[i] && _pl_g_ps_font_info[i].iso8859_1)
  473. {
  474. need_to_reencode = true;
  475. break;
  476. }
  477. #ifdef USE_LJ_FONTS_IN_PS
  478. for (i = 0; i < PL_NUM_PCL_FONTS; i++)
  479. if (pcl_font_used_in_doc[i] && _pl_g_pcl_font_info[i].iso8859_1)
  480. {
  481. need_to_reencode = true;
  482. break;
  483. }
  484. #endif
  485. if (need_to_reencode)
  486. {
  487. strcpy (doc_header->point, _ps_fontproc);
  488. _update_buffer (doc_header);
  489. for (i = 0; i < PL_NUM_PS_FONTS; i++)
  490. {
  491. if (ps_font_used_in_doc[i] && _pl_g_ps_font_info[i].iso8859_1)
  492. {
  493. sprintf (doc_header->point, "\
  494. /%s reencodeISO def\n",
  495. _pl_g_ps_font_info[i].ps_name);
  496. _update_buffer (doc_header);
  497. }
  498. }
  499. #ifdef USE_LJ_FONTS_IN_PS
  500. for (i = 0; i < PL_NUM_PCL_FONTS; i++)
  501. {
  502. if (pcl_font_used_in_doc[i] && _pl_g_pcl_font_info[i].iso8859_1)
  503. {
  504. sprintf (doc_header->point, "\
  505. /%s reencodeISO def\n",
  506. _pl_g_pcl_font_info[i].ps_name);
  507. _update_buffer (doc_header);
  508. }
  509. }
  510. #endif
  511. }
  512. }
  513. if (num_pages == 1)
  514. /* EPS [not just PS] file, include procset in setup section,
  515. so that it will modify only the private dictionary */
  516. {
  517. sprintf (doc_header->point, "\
  518. %%%%BeginResource: procset %s %s 0\n",
  519. PS_PROCSET_NAME, PS_PROCSET_VERSION);
  520. _update_buffer (doc_header);
  521. /* write out idraw-derived PS prologue in p_header.h (makes many
  522. definitions) */
  523. for (i=0; *_ps_procset[i]; i++)
  524. {
  525. strcpy (doc_header->point, _ps_procset[i]);
  526. _update_buffer (doc_header);
  527. }
  528. strcpy (doc_header->point, "\
  529. %%EndResource\n");
  530. _update_buffer (doc_header);
  531. }
  532. strcpy (doc_header->point, "\
  533. %%EndSetup\n\n");
  534. _update_buffer (doc_header);
  535. /* Document header is now prepared, and stored in a plOutbuf.
  536. Now do the same for the doc trailer (much shorter). */
  537. /* Document Trailer: just pop private dictionary off stack */
  538. doc_trailer = _new_outbuf ();
  539. strcpy (doc_trailer->point, "\
  540. %%Trailer\n\
  541. end\n\
  542. %%EOF\n");
  543. _update_buffer (doc_trailer);
  544. /* WRITE DOCUMENT HEADER (and free its plOutbuf) */
  545. _write_string (_plotter->data, doc_header->base);
  546. _delete_outbuf (doc_header);
  547. /* now loop through pages, emitting each in turn */
  548. if (num_pages > 0)
  549. {
  550. for (current_page = _plotter->data->first_page, n=1;
  551. current_page;
  552. current_page = current_page->next, n++)
  553. {
  554. plOutbuf *page_header, *page_trailer;
  555. /* prepare page header, and store it in a plOutbuf */
  556. page_header = _new_outbuf ();
  557. sprintf (page_header->point, "\
  558. %%%%Page: %d %d\n", n, n);
  559. _update_buffer (page_header);
  560. /* write out list of fonts needed by the page */
  561. {
  562. bool first_font = true;
  563. strcpy (page_header->point, "\
  564. %%PageResources: ");
  565. _update_buffer (page_header);
  566. for (i = 0; i < PL_NUM_PS_FONTS; i++)
  567. {
  568. if (current_page->ps_font_used[i])
  569. {
  570. if (first_font == false)
  571. {
  572. strcpy (page_header->point, "%%+ ");
  573. _update_buffer (page_header);
  574. }
  575. strcpy (page_header->point, "font ");
  576. _update_buffer (page_header);
  577. strcpy (page_header->point, _pl_g_ps_font_info[i].ps_name);
  578. _update_buffer (page_header);
  579. strcpy (page_header->point, "\n");
  580. _update_buffer (page_header);
  581. first_font = false;
  582. }
  583. }
  584. #ifdef USE_LJ_FONTS_IN_PS
  585. for (i = 0; i < PL_NUM_PCL_FONTS; i++)
  586. {
  587. if (current_page->pcl_font_used[i])
  588. {
  589. if (first_font == false)
  590. {
  591. strcpy (page_header->point, "%%+ ");
  592. _update_buffer (page_header);
  593. }
  594. strcpy (page_header->point, "font ");
  595. _update_buffer (page_header);
  596. if (_pl_g_pcl_font_info[i].substitute_ps_name)
  597. /* this is to support the Tidbits-is-Wingdings botch */
  598. strcpy (page_header->point, _pl_g_pcl_font_info[i].substitute_ps_name);
  599. else
  600. strcpy (page_header->point, _pl_g_pcl_font_info[i].ps_name);
  601. _update_buffer (page_header);
  602. strcpy (page_header->point, "\n");
  603. _update_buffer (page_header);
  604. first_font = false;
  605. }
  606. }
  607. #endif
  608. if (first_font) /* no fonts needed on page */
  609. {
  610. strcpy (page_header->point, "\n");
  611. _update_buffer (page_header);
  612. }
  613. }
  614. /* emit the bounding box for the page */
  615. _bbox_of_outbuf (current_page, &x_min, &x_max, &y_min, &y_max);
  616. if (x_min > x_max || y_min > y_max)
  617. /* empty page */
  618. sprintf (page_header->point, "\
  619. %%%%PageBoundingBox: 0 0 0 0\n");
  620. else
  621. sprintf (page_header->point, "\
  622. %%%%PageBoundingBox: %d %d %d %d\n",
  623. IROUND(x_min - 0.5), IROUND(y_min - 0.5),
  624. IROUND(x_max + 0.5), IROUND(y_max + 0.5));
  625. _update_buffer (page_header);
  626. /* Page Setup */
  627. strcpy (page_header->point, "\
  628. %%BeginPageSetup\n");
  629. _update_buffer (page_header);
  630. /* emit initialization code (including idraw, PS directives) */
  631. /* N.B. `8' below is the version number of the idraw PS format
  632. we're producing; see <Unidraw/Components/psformat.h> */
  633. strcpy (page_header->point, "\
  634. %I Idraw 8\n\n\
  635. Begin\n\
  636. %I b u\n\
  637. %I cfg u\n\
  638. %I cbg u\n\
  639. %I f u\n\
  640. %I p u\n\
  641. %I t\n\
  642. [ 1 0 0 1 0 0 ] concat\n\
  643. /originalCTM matrix currentmatrix def\n\
  644. /trueoriginalCTM matrix currentmatrix def\n");
  645. _update_buffer (page_header);
  646. strcpy (page_header->point, "\
  647. %%EndPageSetup\n\n");
  648. _update_buffer (page_header);
  649. /* Page header is now prepared, and stored in a plOutbuf.
  650. Do the same for the page trailer (much shorter). */
  651. page_trailer = _new_outbuf ();
  652. /* Page Trailer: includes `showpage' */
  653. strcpy (page_trailer->point, "\
  654. %%PageTrailer\n\
  655. End %I eop\n\
  656. showpage\n\n");
  657. _update_buffer (page_trailer);
  658. /* Page trailer is now ready */
  659. /* WRITE PS CODE FOR THIS PAGE, including header, trailer */
  660. _write_string (_plotter->data, page_header->base);
  661. if (current_page->len > 0)
  662. _write_string (_plotter->data, current_page->base);
  663. _write_string (_plotter->data, page_trailer->base);
  664. /* free header, trailer plOutbufs */
  665. _delete_outbuf (page_trailer);
  666. _delete_outbuf (page_header);
  667. }
  668. }
  669. /* WRITE DOCUMENT TRAILER (and free its plOutbuf) */
  670. _write_string (_plotter->data, doc_trailer->base);
  671. _delete_outbuf (doc_trailer);
  672. }
  673. /* delete all plOutbufs in which document pages are stored */
  674. current_page = _plotter->data->first_page;
  675. while (current_page)
  676. {
  677. plOutbuf *next_page;
  678. next_page = current_page->next;
  679. _delete_outbuf (current_page);
  680. current_page = next_page;
  681. }
  682. /* flush output stream if any */
  683. if (_plotter->data->outfp)
  684. {
  685. if (fflush(_plotter->data->outfp) < 0
  686. #ifdef MSDOS
  687. /* data can be caught in DOS buffers, so do an fsync() too */
  688. || fsync (_plotter->data->outfp) < 0
  689. #endif
  690. )
  691. _plotter->error (R___(_plotter) "the output stream is jammed");
  692. }
  693. #ifdef LIBPLOTTER
  694. else if (_plotter->data->outstream)
  695. {
  696. _plotter->data->outstream->flush ();
  697. if (!(*(_plotter->data->outstream)))
  698. _plotter->error (R___(_plotter) "the output stream is jammed");
  699. }
  700. #endif
  701. #ifndef LIBPLOTTER
  702. /* in libplot, manually invoke superclass termination method */
  703. _pl_g_terminate (S___(_plotter));
  704. #endif
  705. }
  706. #ifdef LIBPLOTTER
  707. PSPlotter::PSPlotter (FILE *infile, FILE *outfile, FILE *errfile)
  708. :Plotter (infile, outfile, errfile)
  709. {
  710. _pl_p_initialize ();
  711. }
  712. PSPlotter::PSPlotter (FILE *outfile)
  713. :Plotter (outfile)
  714. {
  715. _pl_p_initialize ();
  716. }
  717. PSPlotter::PSPlotter (istream& in, ostream& out, ostream& err)
  718. : Plotter (in, out, err)
  719. {
  720. _pl_p_initialize ();
  721. }
  722. PSPlotter::PSPlotter (ostream& out)
  723. : Plotter (out)
  724. {
  725. _pl_p_initialize ();
  726. }
  727. PSPlotter::PSPlotter ()
  728. {
  729. _pl_p_initialize ();
  730. }
  731. PSPlotter::PSPlotter (FILE *infile, FILE *outfile, FILE *errfile, PlotterParams &parameters)
  732. :Plotter (infile, outfile, errfile, parameters)
  733. {
  734. _pl_p_initialize ();
  735. }
  736. PSPlotter::PSPlotter (FILE *outfile, PlotterParams &parameters)
  737. :Plotter (outfile, parameters)
  738. {
  739. _pl_p_initialize ();
  740. }
  741. PSPlotter::PSPlotter (istream& in, ostream& out, ostream& err, PlotterParams &parameters)
  742. : Plotter (in, out, err, parameters)
  743. {
  744. _pl_p_initialize ();
  745. }
  746. PSPlotter::PSPlotter (ostream& out, PlotterParams &parameters)
  747. : Plotter (out, parameters)
  748. {
  749. _pl_p_initialize ();
  750. }
  751. PSPlotter::PSPlotter (PlotterParams &parameters)
  752. : Plotter (parameters)
  753. {
  754. _pl_p_initialize ();
  755. }
  756. PSPlotter::~PSPlotter ()
  757. {
  758. /* if luser left the Plotter open, close it */
  759. if (_plotter->data->open)
  760. _API_closepl ();
  761. _pl_p_terminate ();
  762. }
  763. #endif