g_openpl.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /* This file is part of the GNU plotutils package. Copyright (C) 1995,
  2. 1996, 1997, 1998, 1999, 2000, 2005, 2008, Free Software Foundation, Inc.
  3. The GNU plotutils package is free software. You may redistribute it
  4. and/or modify it under the terms of the GNU General Public License as
  5. published by the Free Software foundation; either version 2, or (at your
  6. option) any later version.
  7. The GNU plotutils package is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. General Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. with the GNU plotutils package; see the file COPYING. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  14. Boston, MA 02110-1301, USA. */
  15. /* This file contains the openpl method, which is a standard part of
  16. libplot. It opens a Plotter object. */
  17. #include "sys-defines.h"
  18. #include "extern.h"
  19. int
  20. _API_openpl (S___(Plotter *_plotter))
  21. {
  22. bool retval;
  23. if (_plotter->data->open)
  24. {
  25. _plotter->error (R___(_plotter)
  26. "openpl: invalid operation");
  27. return -1;
  28. }
  29. /* prepare buffer in which we'll cache graphics code for this page */
  30. switch ((int)_plotter->data->output_model)
  31. {
  32. case (int)PL_OUTPUT_NONE:
  33. /* a single page buffer is created here, and will be deleted by
  34. closepl(); it's never actually written out */
  35. _plotter->data->page = _new_outbuf ();
  36. break;
  37. break;
  38. case (int)PL_OUTPUT_ONE_PAGE:
  39. case (int)PL_OUTPUT_ONE_PAGE_AT_A_TIME:
  40. /* a single page buffer is created here, and will be written out and
  41. deleted by closepl(); in the former case, only page #1 is written
  42. out */
  43. _plotter->data->page = _new_outbuf ();
  44. break;
  45. case (int)PL_OUTPUT_PAGES_ALL_AT_ONCE:
  46. {
  47. plOutbuf *new_page = _new_outbuf();
  48. if (_plotter->data->opened == false) /* first page */
  49. {
  50. _plotter->data->page = new_page;
  51. /* Save a pointer to the first page, since we'll be caching all
  52. pages until the Plotter is deleted. */
  53. _plotter->data->first_page = new_page;
  54. }
  55. else
  56. /* add new page to tail of list, update pointer to current page */
  57. {
  58. _plotter->data->page->next = new_page;
  59. _plotter->data->page = new_page;
  60. }
  61. }
  62. break;
  63. case (int)PL_OUTPUT_VIA_CUSTOM_ROUTINES:
  64. case (int)PL_OUTPUT_VIA_CUSTOM_ROUTINES_IN_REAL_TIME:
  65. case (int)PL_OUTPUT_VIA_CUSTOM_ROUTINES_TO_NON_STREAM:
  66. /* Plotter does its own output, and doesn't use libplot's
  67. plOutbuf-based output system */
  68. _plotter->data->page = (plOutbuf *)NULL;
  69. break;
  70. default: /* shouldn't happen */
  71. break;
  72. }
  73. /* flag device as open */
  74. _plotter->data->open = true;
  75. _plotter->data->opened = true;
  76. _plotter->data->page_number++;
  77. /* keep track of these; some lusers don't invoke ffontsize() or
  78. flinewidth(), so we need to choose a reasonable font size and/or line
  79. width for them */
  80. _plotter->data->fontsize_invoked = false;
  81. _plotter->data->linewidth_invoked = false;
  82. /* frames in page are numbered starting with zero */
  83. _plotter->data->frame_number = 0;
  84. /* create first drawing state, add it to the linked list of drawing
  85. states (this fills in only the device-independent part of the state) */
  86. _pl_g_create_first_drawing_state (S___(_plotter));
  87. /* copy background color, accessible to the user as a Plotter parameter,
  88. to the drawing state */
  89. {
  90. const char *bg_color_name_s;
  91. bg_color_name_s =
  92. (const char *)_get_plot_param (_plotter->data, "BG_COLOR");
  93. if (bg_color_name_s)
  94. _API_bgcolorname (R___(_plotter) bg_color_name_s);
  95. }
  96. /* invoke Plotter-specific `begin page' method, to create
  97. device-dependent part of drawing state, if any; and possibly, do
  98. device-specific initializations of Plotter variables, such as the
  99. (NDC_frame)->(device_frame) map, which some Plotters initialize, once
  100. they've realized how large their device-space drawing region will be,
  101. by calling _compute_ndc_to_device_map() in g_space.c */
  102. retval = _plotter->begin_page (S___(_plotter));
  103. /* Set the composite (user frame)->(NDC_frame->(device frame) map in the
  104. drawing state, as if fsetmatrix() had been called. At this point, the
  105. (user_frame)->(NDC_frame) map is the default, i.e., the identity, and
  106. we pass it to fsetmatrix as its argument. The fsetmatrix method
  107. computes the (user_frame)->(NDC_frame)->(device_frame) map by
  108. composing the (user_frame)->(NDC frame) map with the
  109. (NDC_frame)->(device_frame) map (mentioned above). Any subsequent
  110. user invocations of fsetmatrix() will not affect the latter. */
  111. _API_fsetmatrix (R___(_plotter)
  112. _plotter->drawstate->transform.m_user_to_ndc[0],
  113. _plotter->drawstate->transform.m_user_to_ndc[1],
  114. _plotter->drawstate->transform.m_user_to_ndc[2],
  115. _plotter->drawstate->transform.m_user_to_ndc[3],
  116. _plotter->drawstate->transform.m_user_to_ndc[4],
  117. _plotter->drawstate->transform.m_user_to_ndc[5]);
  118. return (retval == true ? 0 : -1);
  119. }
  120. /* Plotter-specific initializations that take place when openpl() is
  121. invoked. In a generic Plotter, this does nothing. */
  122. bool
  123. _pl_g_begin_page (S___(Plotter *_plotter))
  124. {
  125. return true;
  126. }
  127. /* Create a new drawing state that will become the first drawing state in a
  128. Plotter's linked list of drawing states. See above. */
  129. void
  130. _pl_g_create_first_drawing_state (S___(Plotter *_plotter))
  131. {
  132. plDrawState *drawstate;
  133. const plDrawState *copyfrom;
  134. char *fill_rule, *line_mode, *join_mode, *cap_mode;
  135. /* create a new state */
  136. drawstate = (plDrawState *)_pl_xmalloc (sizeof(plDrawState));
  137. /* copy from default drawing state (see g_defstate.c) */
  138. copyfrom = &_default_drawstate;
  139. memcpy (drawstate, copyfrom, sizeof(plDrawState));
  140. /* elements of state that are strings are treated specially */
  141. fill_rule = (char *)_pl_xmalloc (strlen (copyfrom->fill_rule) + 1);
  142. line_mode = (char *)_pl_xmalloc (strlen (copyfrom->line_mode) + 1);
  143. join_mode = (char *)_pl_xmalloc (strlen (copyfrom->join_mode) + 1);
  144. cap_mode = (char *)_pl_xmalloc (strlen (copyfrom->cap_mode) + 1);
  145. strcpy (fill_rule, copyfrom->fill_rule);
  146. strcpy (line_mode, copyfrom->line_mode);
  147. strcpy (join_mode, copyfrom->join_mode);
  148. strcpy (cap_mode, copyfrom->cap_mode);
  149. drawstate->fill_rule = fill_rule;
  150. drawstate->line_mode = line_mode;
  151. drawstate->join_mode = join_mode;
  152. drawstate->cap_mode = cap_mode;
  153. /* dash array, if non-empty, is treated specially too */
  154. if (copyfrom->dash_array_len > 0)
  155. {
  156. int i;
  157. double *dash_array;
  158. dash_array = (double *)_pl_xmalloc (copyfrom->dash_array_len * sizeof(double));
  159. for (i = 0; i < copyfrom->dash_array_len; i++)
  160. dash_array[i] = copyfrom->dash_array[i];
  161. drawstate->dash_array = dash_array;
  162. }
  163. /* The font_name, true_font_name, font_type, typeface_index, and
  164. font_index fields are special, since for the initial drawing state
  165. they're Plotter-dependent.
  166. The fill_rule_type field is also treated specially in the initial
  167. drawing state, because not all Plotters support both types of filling
  168. (odd vs. nonzero winding number). */
  169. {
  170. const char *font_name_init;
  171. char *font_name, *true_font_name;
  172. int typeface_index, font_index;
  173. switch (_plotter->data->default_font_type)
  174. {
  175. case PL_F_HERSHEY:
  176. default:
  177. font_name_init = PL_DEFAULT_HERSHEY_FONT;
  178. typeface_index = PL_DEFAULT_HERSHEY_TYPEFACE_INDEX;
  179. font_index = PL_DEFAULT_HERSHEY_FONT_INDEX;
  180. break;
  181. case PL_F_POSTSCRIPT:
  182. font_name_init = PL_DEFAULT_POSTSCRIPT_FONT;
  183. typeface_index = PL_DEFAULT_POSTSCRIPT_TYPEFACE_INDEX;
  184. font_index = PL_DEFAULT_POSTSCRIPT_FONT_INDEX;
  185. break;
  186. case PL_F_PCL:
  187. font_name_init = PL_DEFAULT_PCL_FONT;
  188. typeface_index = PL_DEFAULT_PCL_TYPEFACE_INDEX;
  189. font_index = PL_DEFAULT_PCL_FONT_INDEX;
  190. break;
  191. case PL_F_STICK:
  192. font_name_init = PL_DEFAULT_STICK_FONT;
  193. typeface_index = PL_DEFAULT_STICK_TYPEFACE_INDEX;
  194. font_index = PL_DEFAULT_STICK_FONT_INDEX;
  195. break;
  196. }
  197. font_name = (char *)_pl_xmalloc (strlen (font_name_init) + 1);
  198. strcpy (font_name, font_name_init);
  199. drawstate->font_name = font_name;
  200. true_font_name = (char *)_pl_xmalloc (strlen (font_name_init) + 1);
  201. strcpy (true_font_name, font_name_init);
  202. drawstate->true_font_name = true_font_name;
  203. drawstate->font_type = _plotter->data->default_font_type;
  204. drawstate->typeface_index = typeface_index;
  205. drawstate->font_index = font_index;
  206. /* Examine default fill mode. If Plotter doesn't support it, use the
  207. other fill mode. */
  208. if (drawstate->fill_rule_type == PL_FILL_ODD_WINDING
  209. && _plotter->data->have_odd_winding_fill == 0)
  210. drawstate->fill_rule_type = PL_FILL_NONZERO_WINDING;
  211. else if (drawstate->fill_rule_type == PL_FILL_NONZERO_WINDING
  212. && _plotter->data->have_nonzero_winding_fill == 0)
  213. drawstate->fill_rule_type = PL_FILL_ODD_WINDING;
  214. }
  215. /* page begins with no compound path under construction */
  216. drawstate->path = (plPath *)NULL;
  217. drawstate->paths = (plPath **)NULL;
  218. drawstate->num_paths = 0;
  219. /* install new state at head of the state list */
  220. drawstate->previous = NULL;
  221. _plotter->drawstate = drawstate;
  222. }