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
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
9 The GNU plotutils package is distributed in the hope that it will be
10 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with the GNU plotutils package; see the file COPYING. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
17 Boston, MA 02110-1301, USA. */
18
19 /* This file defines the initializations for HPGLPlotter and PCLPlotter
20 objects including both private data and public methods. There is a
21 one-to-one correspondence between public methods and user-callable
22 functions in the C API. */
23
24 /* Originally, the only differences between the two types of Plotter were
25 the PCL5 control codes that must be emitted to switch a PCL5 printer
26 into HP-GL/2 mode, and back out of it.
27
28 More recently, the two types of Plotter are distinguished by their
29 viewport positioning. A PCL Plotter positions its viewport on the page
30 in the same position that a PS, AI, or Fig Plotter does, i.e. it centers
31 it. But a pure HPGL[/2] Plotter doesn't know where on the page the
32 origin of the device coordinate system lies. (Though it's probably
33 close to a corner.) Nor does can it set programmatically whether it's
34 plotting in portrait or landscape mode. (It can flip between them, but
35 it doesn't know which is which.)
36
37 So HPGL Plotters use a viewport of the same default size as PCL, PS, AI,
38 and Fig Plotters. But they don't position it: the lower left corner of
39 the viewport is chosen to be the origin of the device coordinate system:
40 what in HP-GL[/2] jargon is called "scaling point P1".
41
42 For this to look reasonably good, the viewport needs to have a size
43 appropriate for an HP-GL[/2] device. And in fact, that's what
44 determines our choice of default viewport size -- for all Plotters, not
45 just HPGLPlotters. See comments in g_pagetype.h. */
46
47 #include "sys-defines.h"
48 #include "extern.h"
49
50 #define MAX_COLOR_NAME_LEN 32 /* long enough for all known colors */
51
52 #ifndef LIBPLOTTER
53 /* In libplot, this is the initialization for the function-pointer part of
54 a HPGLPlotter struct. */
55 const Plotter _pl_h_default_plotter =
56 {
57 /* initialization (after creation) and termination (before deletion) */
58 _pl_h_initialize, _pl_h_terminate,
59 /* page manipulation */
60 _pl_h_begin_page, _pl_h_erase_page, _pl_h_end_page,
61 /* drawing state manipulation */
62 _pl_g_push_state, _pl_g_pop_state,
63 /* internal path-painting methods (endpath() is a wrapper for the first) */
64 _pl_h_paint_path, _pl_h_paint_paths, _pl_g_path_is_flushable, _pl_g_maybe_prepaint_segments,
65 /* internal methods for drawing of markers and points */
66 _pl_g_paint_marker, _pl_h_paint_point,
67 /* internal methods that plot strings in Hershey, non-Hershey fonts */
68 _pl_g_paint_text_string_with_escapes, _pl_h_paint_text_string,
69 _pl_g_get_text_width,
70 /* private low-level `retrieve font' method */
71 _pl_g_retrieve_font,
72 /* `flush output' method, called only if Plotter handles its own output */
73 _pl_g_flush_output,
74 /* error handlers */
75 _pl_g_warning,
76 _pl_g_error,
77 };
78 #endif /* not LIBPLOTTER */
79
80 #ifndef LIBPLOTTER
81 /* In libplot, this is the initialization for the function-pointer part of
82 a PCLPlotter struct. It is the same as the above except for the
83 different initialization and termination routines. */
84 const Plotter _pl_q_default_plotter =
85 {
86 /* initialization (after creation) and termination (before deletion) */
87 _pl_q_initialize, _pl_q_terminate,
88 /* page manipulation */
89 _pl_h_begin_page, _pl_h_erase_page, _pl_h_end_page,
90 /* drawing state manipulation */
91 _pl_g_push_state, _pl_g_pop_state,
92 /* internal path-painting methods (endpath() is a wrapper for the first) */
93 _pl_h_paint_path, _pl_h_paint_paths, _pl_g_path_is_flushable, _pl_g_maybe_prepaint_segments,
94 /* internal methods for drawing of markers and points */
95 _pl_g_paint_marker, _pl_h_paint_point,
96 /* internal methods that plot strings in Hershey, non-Hershey fonts */
97 _pl_g_paint_text_string_with_escapes, _pl_h_paint_text_string,
98 _pl_g_get_text_width,
99 /* private low-level `retrieve font' method */
100 _pl_g_retrieve_font,
101 /* `flush output' method, called only if Plotter handles its own output */
102 _pl_g_flush_output,
103 /* error handlers */
104 _pl_g_warning,
105 _pl_g_error,
106 };
107 #endif /* not LIBPLOTTER */
108
109 /* The private `initialize' method, which is invoked when a Plotter is
110 created. It is used for such things as initializing capability flags
111 from the values of class variables, allocating storage, etc. When this
112 is invoked, _plotter points to the Plotter that has just been
113 created. */
114
115 /* The initializations for HPGL and PCL Plotters are similar.
116
117 For HPGL Plotters, we determine the HP-GL version from the environment
118 variable HPGL_VERSION ("1", "1.5", or "2", meaning generic HP-GL,
119 HP7550A, and modern HP-GL/2 respectively), and determine the page size
120 and the location on the page of the viewport, so that we'll be able to
121 work out the map from user coordinates to device coordinates in
122 g_space.c.
123
124 We allow the user to shift the location of the viewport by specifying an
125 offset vector, since the origin of the HP-GL coordinate system and the
126 size of the `hard-clip region' within which graphics can be drawn are
127 not known. (There are so many HP-GL and HP-GL/2 devices.)
128
129 We also work out which pens are available, and whether the device, if an
130 HP-GL/2 device, supports the Palette Extension so that new logical pens
131 can be defined as RGB triples. The HPGL_PENS and HPGL_ASSIGN_COLORS
132 environment variables are used for this. (The default is for a generic
133 HP-GL device to have exactly 1 pen, #1, and for an HP7550A or HP-GL/2
134 device to have 7 pens, #1 through #7, with colors equal to the seven
135 non-white vertices of the RGB color cube. We allow the user to specify
136 up to 31 pens, #1 through #31, via HPGL_PENS. */
137
138 void
_pl_h_initialize(S___ (Plotter * _plotter))139 _pl_h_initialize (S___(Plotter *_plotter))
140 {
141 int i;
142 #ifndef LIBPLOTTER
143 /* in libplot, manually invoke superclass initialization method */
144 _pl_g_initialize (S___(_plotter));
145 #endif
146
147 /* override generic initializations (which are appropriate to the base
148 Plotter class), as necessary */
149
150 #ifndef LIBPLOTTER
151 /* tag field, differs in derived classes */
152 _plotter->data->type = PL_HPGL;
153 #endif
154
155 /* output model */
156 _plotter->data->output_model = PL_OUTPUT_ONE_PAGE_AT_A_TIME;
157
158 /* user-queryable capabilities: 0/1/2 = no/yes/maybe */
159 _plotter->data->have_wide_lines = 1;
160 _plotter->data->have_dash_array = 1;
161 _plotter->data->have_solid_fill = 1;
162 _plotter->data->have_odd_winding_fill = 1;
163 _plotter->data->have_nonzero_winding_fill = 1;
164 _plotter->data->have_settable_bg = 0;
165 _plotter->data->have_escaped_string_support = 0;
166 #ifdef USE_PS_FONTS_IN_PCL
167 _plotter->data->have_ps_fonts = 1;
168 #else
169 _plotter->data->have_ps_fonts = 0;
170 #endif
171 _plotter->data->have_pcl_fonts = 1;
172 _plotter->data->have_stick_fonts = 1;
173 _plotter->data->have_extra_stick_fonts = 1;
174 _plotter->data->have_other_fonts = 0;
175
176 /* text and font-related parameters (internal, not queryable by user) */
177 _plotter->data->default_font_type = PL_F_HERSHEY;
178 _plotter->data->pcl_before_ps = true;
179 _plotter->data->have_horizontal_justification = false;
180 _plotter->data->have_vertical_justification = false;
181 _plotter->data->kern_stick_fonts = true;
182 _plotter->data->issue_font_warning = true;
183
184 /* path-related parameters (also internal); note that we
185 don't set max_unfilled_path_length, because it was set by the
186 superclass initialization */
187 _plotter->data->have_mixed_paths = true;
188 _plotter->data->allowed_arc_scaling = AS_UNIFORM;
189 _plotter->data->allowed_ellarc_scaling = AS_NONE;
190 _plotter->data->allowed_quad_scaling = AS_NONE;
191 _plotter->data->allowed_cubic_scaling = AS_NONE;
192 _plotter->data->allowed_box_scaling = AS_AXES_PRESERVED;
193 _plotter->data->allowed_circle_scaling = AS_UNIFORM;
194 _plotter->data->allowed_ellipse_scaling = AS_NONE;
195
196 /* dimensions */
197 _plotter->data->display_model_type = (int)DISP_MODEL_PHYSICAL;
198 _plotter->data->display_coors_type = (int)DISP_DEVICE_COORS_INTEGER_NON_LIBXMI;
199 _plotter->data->flipped_y = false;
200 _plotter->data->imin = 0;
201 _plotter->data->imax = 0;
202 _plotter->data->jmin = 0;
203 _plotter->data->jmax = 0;
204 _plotter->data->xmin = HPGL_SCALED_DEVICE_LEFT;
205 _plotter->data->xmax = HPGL_SCALED_DEVICE_RIGHT;
206 _plotter->data->ymin = HPGL_SCALED_DEVICE_BOTTOM;
207 _plotter->data->ymax = HPGL_SCALED_DEVICE_TOP;
208 _plotter->data->page_data = (plPageData *)NULL;
209
210 /* compute the NDC to device-frame affine map, set it in Plotter */
211 _compute_ndc_to_device_map (_plotter->data);
212
213 /* initialize data members specific to this derived class */
214 /* parameters */
215 _plotter->hpgl_version = 2;
216 _plotter->hpgl_rotation = 0;
217 _plotter->hpgl_p1.x = 0.0;
218 _plotter->hpgl_p1.y = 8128.0;
219 _plotter->hpgl_p2.x = 0.0;
220 _plotter->hpgl_p2.y = 8128.0;
221 _plotter->hpgl_plot_length = 10668.0;
222 _plotter->hpgl_have_screened_vectors = false;
223 _plotter->hpgl_have_char_fill = false;
224 _plotter->hpgl_can_assign_colors = false;
225 _plotter->hpgl_use_opaque_mode = true;
226 /* dynamic variables */
227 /* pen_color[] and pen_defined[] arrays also used */
228 _plotter->hpgl_pen = 1;
229 _plotter->hpgl_free_pen = 2;
230 _plotter->hpgl_bad_pen = false;
231 _plotter->hpgl_pendown = false;
232 _plotter->hpgl_pen_width = 0.001;
233 _plotter->hpgl_line_type = HPGL_L_SOLID;
234 _plotter->hpgl_cap_style = HPGL_CAP_BUTT;
235 _plotter->hpgl_join_style = HPGL_JOIN_MITER;
236 _plotter->hpgl_miter_limit = 5.0; /* default HP-GL/2 value */
237 _plotter->hpgl_pen_type = HPGL_PEN_SOLID;
238 _plotter->hpgl_pen_option1 = 0.0;
239 _plotter->hpgl_pen_option2 = 0.0;
240 _plotter->hpgl_fill_type = HPGL_FILL_SOLID_BI;
241 _plotter->hpgl_fill_option1 = 0.0;
242 _plotter->hpgl_fill_option2 = 0.0;
243 _plotter->hpgl_char_rendering_type = HPGL_CHAR_FILL_SOLID_AND_MAYBE_EDGE;
244 _plotter->hpgl_symbol_set = PCL_ROMAN_8;
245 _plotter->hpgl_spacing = 0;
246 _plotter->hpgl_posture = 0;
247 _plotter->hpgl_stroke_weight = 0;
248 _plotter->hpgl_pcl_typeface = PCL_STICK_TYPEFACE;
249 _plotter->hpgl_charset_lower = HPGL_CHARSET_ASCII;
250 _plotter->hpgl_charset_upper = HPGL_CHARSET_ASCII;
251 _plotter->hpgl_rel_char_height = 0.0;
252 _plotter->hpgl_rel_char_width = 0.0;
253 _plotter->hpgl_rel_label_rise = 0.0;
254 _plotter->hpgl_rel_label_run = 0.0;
255 _plotter->hpgl_tan_char_slant = 0.0;
256 _plotter->hpgl_position_is_unknown = true;
257 _plotter->hpgl_pos.x = 0;
258 _plotter->hpgl_pos.y = 0;
259
260 /* note: this driver also uses pen_color[], pen_defined[] arrays;
261 see initializations below */
262
263 /* initialize certain data members from device driver parameters */
264
265 /* determine HP-GL version */
266 {
267 const char *version_s;
268
269 version_s = (const char *)_get_plot_param (_plotter->data, "HPGL_VERSION");
270 /* there are three subcases: "1", "1.5", and "2" (default, see above) */
271 if (strcmp (version_s, "1") == 0) /* generic HP-GL, HP7220 or HP7475A */
272 {
273 _plotter->hpgl_version = 0;
274 _plotter->data->have_wide_lines = 0;
275 _plotter->data->have_dash_array = 0;
276 _plotter->data->have_solid_fill = 0;
277 _plotter->data->have_odd_winding_fill = 1;
278 _plotter->data->have_nonzero_winding_fill = 0;
279 _plotter->data->have_ps_fonts = 0;
280 _plotter->data->have_pcl_fonts = 0;
281 _plotter->data->have_stick_fonts = 1;
282 _plotter->data->have_extra_stick_fonts = 0;
283 _plotter->data->kern_stick_fonts = true;
284 _plotter->data->have_other_fonts = 0;
285 }
286 else if (strcmp (version_s, "1.5") == 0) /* HP7550A */
287 {
288 _plotter->hpgl_version = 1;
289 _plotter->data->have_wide_lines = 0;
290 _plotter->data->have_dash_array = 0;
291 _plotter->data->have_solid_fill = 1;
292 _plotter->data->have_odd_winding_fill = 1;
293 _plotter->data->have_nonzero_winding_fill = 0;
294 _plotter->data->have_ps_fonts = 0;
295 _plotter->data->have_pcl_fonts = 0;
296 _plotter->data->have_stick_fonts = 1;
297 _plotter->data->have_extra_stick_fonts = 1;
298 _plotter->data->kern_stick_fonts = true;
299 _plotter->data->have_other_fonts = 0;
300 }
301 }
302
303 /* Determine range of device coordinates over which the viewport will
304 extend (and hence the transformation from user to device coordinates;
305 see g_space.c). */
306
307 /* NOTE: HP-GL Plotters, unlike PCL Plotters, ignore the xorigin and
308 yorigin fields of the PAGESIZE parameter. That's because the device
309 coordinate system isn't well specified. However, the viewport can be
310 shifted relative to its default location, as usual, by specifying the
311 xoffset and yoffset fields. */
312
313 /* We use the corners of the viewport, in device coordinates, as our
314 `scaling points' P1 and P2 (see h_openpl.c). The coordinates we use
315 in our output file will be normalized device coordinates, not physical
316 device coordinates (for the map from the former to the latter, which
317 is accomplished by the HP-GL `SC' instruction, see h_openpl.c). */
318 {
319 /* determine page type, and viewport size and location */
320 _set_page_type (_plotter->data);
321
322 /* by default, viewport lower left corner is (0,0) in HP-GL
323 coordinates; if a user wishes to change this, the xoffset and
324 yoffset parameters should be added to PAGESIZE */
325 _plotter->hpgl_p1.x = (HPGL_UNITS_PER_INCH
326 * (0.0
327 + _plotter->data->viewport_xoffset));
328 _plotter->hpgl_p2.x = (HPGL_UNITS_PER_INCH
329 * (0.0
330 + _plotter->data->viewport_xoffset
331 + _plotter->data->viewport_xsize));
332
333 _plotter->hpgl_p1.y = (HPGL_UNITS_PER_INCH
334 * (0.0
335 + _plotter->data->viewport_yoffset));
336 _plotter->hpgl_p2.y = (HPGL_UNITS_PER_INCH
337 * (0.0
338 + _plotter->data->viewport_yoffset
339 + _plotter->data->viewport_ysize));
340
341 _plotter->data->xmin = HPGL_SCALED_DEVICE_LEFT;
342 _plotter->data->xmax = HPGL_SCALED_DEVICE_RIGHT;
343 _plotter->data->ymin = HPGL_SCALED_DEVICE_BOTTOM;
344 _plotter->data->ymax = HPGL_SCALED_DEVICE_TOP;
345
346 /* plot length (to be emitted in an HP-GL/2 `PS' instruction, important
347 mostly for roll plotters; see h_openpl.c) */
348 _plotter->hpgl_plot_length =
349 _plotter->data->page_data->hpgl2_plot_length * HPGL_UNITS_PER_INCH;
350 }
351
352 /* determine whether to rotate the figure (e.g. horizontal instead of
353 vertical, see h_openpl.c) */
354 {
355 const char *rotate_s;
356
357 rotate_s = (const char *)_get_plot_param (_plotter->data, "HPGL_ROTATE");
358 /* four subcases: 0 (default), 90, 180, 270 (latter two only if "2") */
359 if (strcasecmp (rotate_s, "yes") == 0
360 || strcmp (rotate_s, "90") == 0)
361 _plotter->hpgl_rotation = 90;
362 else if (strcmp (rotate_s, "180") == 0 && _plotter->hpgl_version == 2)
363 _plotter->hpgl_rotation = 180;
364 else if (strcmp (rotate_s, "270") == 0 && _plotter->hpgl_version == 2)
365 _plotter->hpgl_rotation = 270;
366 else
367 _plotter->hpgl_rotation = 0;
368 }
369
370 /* Should we avoid emitting the `white is opaque' HP-GL/2 instruction?
371 (HP-GL/2 pen plotters may not like it) */
372 {
373 const char *transparent_s;
374
375 transparent_s = (const char *)_get_plot_param (_plotter->data, "HPGL_OPAQUE_MODE" );
376 if (strcasecmp (transparent_s, "no") == 0)
377 _plotter->hpgl_use_opaque_mode = false;
378 }
379
380 /* do we support the HP-GL/2 palette extension, i.e. can we define new
381 logical pens as RGB triples? (user must request this with
382 HPGL_ASSIGN_COLORS) */
383 if (_plotter->hpgl_version == 2)
384 {
385 const char *palette_s;
386
387 palette_s = (const char *)_get_plot_param (_plotter->data, "HPGL_ASSIGN_COLORS");
388 if (strcasecmp (palette_s, "yes") == 0)
389 _plotter->hpgl_can_assign_colors = true;
390 }
391
392 /* initialize pen color array, typically 0..31 */
393 for (i = 0; i < HPGL2_MAX_NUM_PENS; i++)
394 _plotter->hpgl_pen_defined[i] = 0; /* pen absent, or at least undefined */
395
396 /* pen #0 (white pen, RGB=255,255,255) is always defined */
397 _plotter->hpgl_pen_color[0].red = 255;
398 _plotter->hpgl_pen_color[0].green = 255;
399 _plotter->hpgl_pen_color[0].blue = 255;
400 _plotter->hpgl_pen_defined[0] = 2; /* i.e. hard-defined */
401
402 /* determine initial palette, i.e. available pens in 1..31 range */
403 {
404 const char *pen_s;
405
406 pen_s = (const char *)_get_plot_param (_plotter->data, "HPGL_PENS");
407
408 if (pen_s == NULL
409 || _pl_h_parse_pen_string (R___(_plotter) pen_s) == false
410 || (_plotter->hpgl_can_assign_colors == false
411 && _plotter->hpgl_pen_defined[1] == 0))
412 /* Either user didn't assign a value, or it was bad; use default.
413 Note that if no logical pens, we insist on pen #1 being present
414 (for backward compatibility?). */
415 {
416 if (_plotter->hpgl_version == 0) /* i.e. generic HP-GL */
417 pen_s = HPGL_DEFAULT_PEN_STRING;
418 else
419 pen_s = HPGL2_DEFAULT_PEN_STRING;
420 _pl_h_parse_pen_string (R___(_plotter) pen_s); /* default is guaranteed to parse */
421 }
422 }
423
424 /* Examine presence or absence of hard-defined pens in 2..31 range.
425 0 = undefined, 1 = soft-defined (not yet), 2 = hard-defined. */
426 {
427 bool undefined_pen_seen = false;
428
429 for (i = 2; i < HPGL2_MAX_NUM_PENS; i++)
430 {
431 if (_plotter->hpgl_pen_defined[i] == 0)
432 /* at least one pen with number > 1 is not yet defined */
433 {
434 /* record which such was encountered first */
435 _plotter->hpgl_free_pen = i;
436 undefined_pen_seen = true;
437 break;
438 }
439 }
440 if (!undefined_pen_seen)
441 /* too many pens specified, can't soft-define colors */
442 _plotter->hpgl_can_assign_colors = false;
443 }
444 }
445
446 /* Initialization for the PCLPlotter class, which is subclassed from the
447 HPGLPlotter class. */
448
449 void
_pl_q_initialize(S___ (Plotter * _plotter))450 _pl_q_initialize (S___(Plotter *_plotter))
451 {
452 int i;
453
454 #ifndef LIBPLOTTER
455 /* in libplot, manually invoke superclass initialization method */
456 _pl_h_initialize (S___(_plotter));
457 #endif
458
459 /* Superclass initialization (i.e., of an HPGLPlotter) may well have
460 screwed things up, since e.g. for a PCLPlotter, hpgl_version should
461 always be equal to 2, irrespective of what HPGL_VERSION is; also the
462 viewport positioning is different. So we redo a large part of the
463 initialization, most of which is redundant (FIXME). */
464
465 #ifndef LIBPLOTTER
466 /* tag field, differs in derived classes */
467 _plotter->data->type = PL_PCL;
468 #endif
469
470 /* output model */
471 _plotter->data->output_model = PL_OUTPUT_ONE_PAGE_AT_A_TIME;
472
473 /* user-queryable capabilities: 0/1/2 = no/yes/maybe */
474 _plotter->data->have_wide_lines = 1;
475 _plotter->data->have_dash_array = 1;
476 _plotter->data->have_solid_fill = 1;
477 _plotter->data->have_odd_winding_fill = 1;
478 _plotter->data->have_nonzero_winding_fill = 1;
479 _plotter->data->have_settable_bg = 0;
480 _plotter->data->have_escaped_string_support = 0;
481 #ifdef USE_PS_FONTS_IN_PCL
482 _plotter->data->have_ps_fonts = 1;
483 #else
484 _plotter->data->have_ps_fonts = 0;
485 #endif
486 _plotter->data->have_pcl_fonts = 1;
487 _plotter->data->have_stick_fonts = 1;
488 _plotter->data->have_extra_stick_fonts = 0;
489 _plotter->data->have_other_fonts = 0;
490
491 /* text and font-related parameters (internal, not queryable by user) */
492 _plotter->data->default_font_type = PL_F_PCL;
493 _plotter->data->pcl_before_ps = true;
494 _plotter->data->have_horizontal_justification = false;
495 _plotter->data->have_vertical_justification = false;
496 _plotter->data->kern_stick_fonts = false; /* in PCL5 printers' HP-GL/2 emulation */
497 _plotter->data->issue_font_warning = true;
498
499 /* path-related parameters (also internal); note that we
500 don't set max_unfilled_path_length, because it was set by the
501 superclass initialization */
502 _plotter->data->have_mixed_paths = true;
503 _plotter->data->allowed_arc_scaling = AS_UNIFORM;
504 _plotter->data->allowed_ellarc_scaling = AS_NONE;
505 _plotter->data->allowed_quad_scaling = AS_NONE;
506 _plotter->data->allowed_cubic_scaling = AS_ANY;
507 _plotter->data->allowed_box_scaling = AS_AXES_PRESERVED;
508 _plotter->data->allowed_circle_scaling = AS_UNIFORM;
509 _plotter->data->allowed_ellipse_scaling = AS_NONE;
510
511 /* dimensions, differ in derived classes */
512 _plotter->data->display_model_type = (int)DISP_MODEL_PHYSICAL;
513 _plotter->data->display_coors_type = (int)DISP_DEVICE_COORS_INTEGER_NON_LIBXMI;
514 _plotter->data->flipped_y = false;
515 _plotter->data->imin = 0;
516 _plotter->data->imax = 0;
517 _plotter->data->jmin = 0;
518 _plotter->data->jmax = 0;
519 _plotter->data->xmin = HPGL_SCALED_DEVICE_LEFT;
520 _plotter->data->xmax = HPGL_SCALED_DEVICE_RIGHT;
521 _plotter->data->ymin = HPGL_SCALED_DEVICE_BOTTOM;
522 _plotter->data->ymax = HPGL_SCALED_DEVICE_TOP;
523 _plotter->data->page_data = (plPageData *)NULL;
524
525 /* compute the NDC to device-frame affine map, set it in Plotter */
526 _compute_ndc_to_device_map (_plotter->data);
527
528 /* initialize data members specific to this derived class */
529 /* parameters */
530 _plotter->hpgl_version = 2;
531 _plotter->hpgl_rotation = 0;
532 _plotter->hpgl_p1.x = 0.0;
533 _plotter->hpgl_p1.y = 8128.0;
534 _plotter->hpgl_p2.x = 0.0;
535 _plotter->hpgl_p2.y = 8128.0;
536 _plotter->hpgl_plot_length = 10668.0;
537 _plotter->hpgl_have_screened_vectors = true; /* different from HPGLPlotter */
538 _plotter->hpgl_have_char_fill = true; /* different from HPGLPlotter */
539 _plotter->hpgl_can_assign_colors = false;
540 _plotter->hpgl_use_opaque_mode = true;
541 /* dynamic variables */
542 /* pen_color[] and pen_defined[] arrays also used */
543 _plotter->hpgl_pen = 1;
544 _plotter->hpgl_free_pen = 2;
545 _plotter->hpgl_bad_pen = false;
546 _plotter->hpgl_pendown = false;
547 _plotter->hpgl_pen_width = 0.001;
548 _plotter->hpgl_line_type = HPGL_L_SOLID;
549 _plotter->hpgl_cap_style = HPGL_CAP_BUTT;
550 _plotter->hpgl_join_style = HPGL_JOIN_MITER;
551 /* Maximum value the cosecant of the half-angle between any two line
552 segments can have, if the join is to be mitered rather than beveled.
553 Default HP-GL/2 value is 5.0. */
554 _plotter->hpgl_miter_limit = 5.0;
555 _plotter->hpgl_pen_type = HPGL_PEN_SOLID;
556 _plotter->hpgl_pen_option1 = 0.0;
557 _plotter->hpgl_pen_option2 = 0.0;
558 _plotter->hpgl_fill_type = HPGL_FILL_SOLID_BI;
559 _plotter->hpgl_fill_option1 = 0.0;
560 _plotter->hpgl_fill_option2 = 0.0;
561 _plotter->hpgl_char_rendering_type = HPGL_CHAR_FILL_SOLID_AND_MAYBE_EDGE;
562 _plotter->hpgl_symbol_set = PCL_ROMAN_8;
563 _plotter->hpgl_spacing = 0;
564 _plotter->hpgl_posture = 0;
565 _plotter->hpgl_stroke_weight = 0;
566 _plotter->hpgl_pcl_typeface = PCL_STICK_TYPEFACE;
567 _plotter->hpgl_charset_lower = HPGL_CHARSET_ASCII;
568 _plotter->hpgl_charset_upper = HPGL_CHARSET_ASCII;
569 _plotter->hpgl_rel_char_height = 0.0;
570 _plotter->hpgl_rel_char_width = 0.0;
571 _plotter->hpgl_rel_label_rise = 0.0;
572 _plotter->hpgl_rel_label_run = 0.0;
573 _plotter->hpgl_tan_char_slant = 0.0;
574
575 /* note: this driver also uses pen_color[], pen_defined[] arrays;
576 see initializations below */
577
578 /* initialize certain data members from device driver parameters */
579
580 /* Determine range of device coordinates over which the viewport will
581 extend (and hence the transformation from user to device coordinates;
582 see g_space.c). */
583
584 /* We use the corners of the viewport, in device coordinates, as our
585 `scaling points' P1 and P2 (see h_openpl.c). The coordinates we use
586 in our output file will be normalized device coordinates, not physical
587 device coordinates (for the map from the former to the latter, which
588 is accomplished by the HP-GL `SC' instruction, see h_openpl.c). */
589 {
590 /* determine page type, viewport size and location */
591 _set_page_type (_plotter->data);
592
593 /* convert viewport size-and-location data (in terms of inches) to
594 device coordinates (i.e. HP-GL units) */
595
596 /* NOTE: origin of HP-GL/2 coordinate system used by a PCL5 device is
597 not at lower left corner of page; must compensate by subtracting the
598 `pcl_hpgl2_?origin' quantities. */
599 _plotter->hpgl_p1.x = (HPGL_UNITS_PER_INCH
600 * (_plotter->data->viewport_xorigin
601 + _plotter->data->viewport_xoffset
602 - _plotter->data->page_data->pcl_hpgl2_xorigin));
603 _plotter->hpgl_p2.x = (HPGL_UNITS_PER_INCH
604 * (_plotter->data->viewport_xorigin
605 + _plotter->data->viewport_xoffset
606 + _plotter->data->viewport_xsize
607 - _plotter->data->page_data->pcl_hpgl2_xorigin));
608
609 _plotter->hpgl_p1.y = (HPGL_UNITS_PER_INCH
610 * (_plotter->data->viewport_yorigin
611 + _plotter->data->viewport_yoffset
612 - _plotter->data->page_data->pcl_hpgl2_yorigin));
613 _plotter->hpgl_p2.y = (HPGL_UNITS_PER_INCH
614 * (_plotter->data->viewport_yorigin
615 + _plotter->data->viewport_yoffset
616 + _plotter->data->viewport_ysize
617 - _plotter->data->page_data->pcl_hpgl2_yorigin));
618
619 /* plot length (to be emitted in an HP-GL/2 `PS' instruction, important
620 mostly for roll plotters; see h_openpl.c) */
621 _plotter->hpgl_plot_length =
622 _plotter->data->page_data->hpgl2_plot_length * HPGL_UNITS_PER_INCH;
623 }
624
625 /* don't make use of HP-GL/2's plotting-area rotation facility; if we
626 wish to switch between portrait and landscape modes we'll do so from
627 within PCL5 */
628 _plotter->hpgl_rotation = 0;
629
630 /* do we support the HP-GL/2 palette extension, i.e. can we define new
631 logical pens as RGB triples? (user must request this with
632 PCL_ASSIGN_COLORS) */
633 _plotter->hpgl_can_assign_colors = false;
634 {
635 const char *palette_s;
636
637 palette_s = (const char *)_get_plot_param (_plotter->data, "PCL_ASSIGN_COLORS");
638 if (strcasecmp (palette_s, "yes") == 0)
639 _plotter->hpgl_can_assign_colors = true;
640 }
641
642 /* do we use the HP-GL/2 `BZ' instruction for drawing Beziers? (the
643 LaserJet III did not support it) */
644 {
645 const char *bezier_s;
646
647 bezier_s = (const char *)_get_plot_param (_plotter->data, "PCL_BEZIERS");
648
649 if (strcasecmp (bezier_s, "yes") != 0)
650 _plotter->data->allowed_cubic_scaling = AS_NONE;
651 }
652
653 /* initialize pen color array, typically 0..31 */
654 for (i = 0; i < HPGL2_MAX_NUM_PENS; i++)
655 _plotter->hpgl_pen_defined[i] = 0; /* pen absent, or at least undefined */
656
657 /* pen #0 (white pen, RGB=255,255,255) is always defined */
658 _plotter->hpgl_pen_color[0].red = 255;
659 _plotter->hpgl_pen_color[0].green = 255;
660 _plotter->hpgl_pen_color[0].blue = 255;
661 _plotter->hpgl_pen_defined[0] = 2; /* i.e. hard-defined */
662
663 /* determine initial palette, i.e. available pens in 1..31 range; for a
664 PCLPlotter we use the default HP-GL/2 pen string */
665 {
666 const char *pen_s;
667
668 pen_s = HPGL2_DEFAULT_PEN_STRING;
669 _pl_h_parse_pen_string (R___(_plotter) pen_s); /* default is guaranteed to parse */
670 }
671
672 /* Examine presence or absence of hard-defined pens in 2..31 range.
673 0 = undefined, 1 = soft-defined (not yet), 2 = hard-defined. */
674 {
675 bool undefined_pen_seen = false;
676
677 for (i = 2; i < HPGL2_MAX_NUM_PENS; i++)
678 {
679 if (_plotter->hpgl_pen_defined[i] == 0)
680 /* at least one pen with number > 1 is not yet defined */
681 {
682 /* record which such was encountered first */
683 _plotter->hpgl_free_pen = i;
684 undefined_pen_seen = true;
685 break;
686 }
687 }
688 if (!undefined_pen_seen)
689 /* too many pens specified, can't soft-define colors */
690 _plotter->hpgl_can_assign_colors = false;
691 }
692 }
693
694 /* Parse a pen string, e.g. a user-specified HPGL_PENS environment
695 variable, specifying which pens are available. Result is stored in the
696 Plotter. More pens (logical pens) may be added later to the array of
697 available pens, if the plotter is an HP-GL/2 device and supports the
698 palette extension. User specifies this by setting the
699 HPGL_ASSIGN_COLORS environment variable to "yes"; see above. */
700 bool
_pl_h_parse_pen_string(R___ (Plotter * _plotter)const char * pen_s)701 _pl_h_parse_pen_string (R___(Plotter *_plotter) const char *pen_s)
702 {
703 const char *charp;
704 char name[MAX_COLOR_NAME_LEN];
705 int i;
706
707 charp = pen_s;
708 while (*charp)
709 {
710 int pen_num;
711 bool got_digit;
712 const char *tmp;
713 plColor color;
714
715 if (*charp == ':') /* skip any ':' */
716 {
717 charp++;
718 continue; /* back to top of while loop */
719 }
720 pen_num = 0;
721 got_digit = false;
722 while (*charp >= '0' && *charp <= '9')
723 {
724 pen_num = 10 * pen_num + (int)*charp - (int)'0';
725 got_digit = true;
726 charp++;
727 }
728 if (!got_digit || pen_num < 1 || pen_num >= HPGL2_MAX_NUM_PENS)
729 return false;
730 if (*charp != '=')
731 return false;
732 charp++;
733 for (tmp = charp, i = 0; i < MAX_COLOR_NAME_LEN; tmp++, i++)
734 {
735 if (*tmp == ':') /* end of color name string */
736 {
737 name[i] = '\0';
738 charp = tmp + 1;
739 break;
740 }
741 else if (*tmp == '\0') /* end of name string and env var also */
742 {
743 name[i] = '\0';
744 charp = tmp;
745 break;
746 }
747 else
748 name[i] = *tmp;
749 }
750
751 /* got color name string, parse it */
752 if (_string_to_color (name, &color, _plotter->data->color_name_cache))
753 {
754 _plotter->hpgl_pen_color[pen_num] = color;
755 _plotter->hpgl_pen_defined[pen_num] = 2; /* hard-defined */
756 }
757 else /* couldn't match color name string */
758 return false;
759 }
760
761 return true;
762 }
763
764 /* The private `terminate' method, which is invoked when a Plotter is
765 deleted. It may do such things as write to an output stream from
766 internal storage, deallocate storage, etc. When this is invoked,
767 _plotter points to the Plotter that is about to be deleted. */
768
769 void
_pl_h_terminate(S___ (Plotter * _plotter))770 _pl_h_terminate (S___(Plotter *_plotter))
771 {
772 #ifndef LIBPLOTTER
773 /* in libplot, manually invoke superclass termination method */
774 _pl_g_terminate (S___(_plotter));
775 #endif
776 }
777
778 void
_pl_q_terminate(S___ (Plotter * _plotter))779 _pl_q_terminate (S___(Plotter *_plotter))
780 {
781 #ifndef LIBPLOTTER
782 /* in libplot, manually invoke superclass termination method */
783 _pl_h_terminate (S___(_plotter));
784 #endif
785 }
786
787 #ifdef LIBPLOTTER
HPGLPlotter(FILE * infile,FILE * outfile,FILE * errfile)788 HPGLPlotter::HPGLPlotter (FILE *infile, FILE *outfile, FILE *errfile)
789 :Plotter (infile, outfile, errfile)
790 {
791 _pl_h_initialize ();
792 }
793
HPGLPlotter(FILE * outfile)794 HPGLPlotter::HPGLPlotter (FILE *outfile)
795 :Plotter (outfile)
796 {
797 _pl_h_initialize ();
798 }
799
HPGLPlotter(istream & in,ostream & out,ostream & err)800 HPGLPlotter::HPGLPlotter (istream& in, ostream& out, ostream& err)
801 : Plotter (in, out, err)
802 {
803 _pl_h_initialize ();
804 }
805
HPGLPlotter(ostream & out)806 HPGLPlotter::HPGLPlotter (ostream& out)
807 : Plotter (out)
808 {
809 _pl_h_initialize ();
810 }
811
HPGLPlotter()812 HPGLPlotter::HPGLPlotter ()
813 {
814 _pl_h_initialize ();
815 }
816
HPGLPlotter(FILE * infile,FILE * outfile,FILE * errfile,PlotterParams & parameters)817 HPGLPlotter::HPGLPlotter (FILE *infile, FILE *outfile, FILE *errfile, PlotterParams ¶meters)
818 :Plotter (infile, outfile, errfile, parameters)
819 {
820 _pl_h_initialize ();
821 }
822
HPGLPlotter(FILE * outfile,PlotterParams & parameters)823 HPGLPlotter::HPGLPlotter (FILE *outfile, PlotterParams ¶meters)
824 :Plotter (outfile, parameters)
825 {
826 _pl_h_initialize ();
827 }
828
HPGLPlotter(istream & in,ostream & out,ostream & err,PlotterParams & parameters)829 HPGLPlotter::HPGLPlotter (istream& in, ostream& out, ostream& err, PlotterParams ¶meters)
830 : Plotter (in, out, err, parameters)
831 {
832 _pl_h_initialize ();
833 }
834
HPGLPlotter(ostream & out,PlotterParams & parameters)835 HPGLPlotter::HPGLPlotter (ostream& out, PlotterParams ¶meters)
836 : Plotter (out, parameters)
837 {
838 _pl_h_initialize ();
839 }
840
HPGLPlotter(PlotterParams & parameters)841 HPGLPlotter::HPGLPlotter (PlotterParams ¶meters)
842 : Plotter (parameters)
843 {
844 _pl_h_initialize ();
845 }
846
~HPGLPlotter()847 HPGLPlotter::~HPGLPlotter ()
848 {
849 /* if luser left the Plotter open, close it */
850 if (_plotter->data->open)
851 _API_closepl ();
852
853 _pl_h_terminate ();
854 }
855 #endif
856
857 #ifdef LIBPLOTTER
PCLPlotter(FILE * infile,FILE * outfile,FILE * errfile)858 PCLPlotter::PCLPlotter (FILE *infile, FILE *outfile, FILE *errfile)
859 :HPGLPlotter (infile, outfile, errfile)
860 {
861 _pl_q_initialize ();
862 }
863
PCLPlotter(FILE * outfile)864 PCLPlotter::PCLPlotter (FILE *outfile)
865 :HPGLPlotter (outfile)
866 {
867 _pl_q_initialize ();
868 }
869
PCLPlotter(istream & in,ostream & out,ostream & err)870 PCLPlotter::PCLPlotter (istream& in, ostream& out, ostream& err)
871 : HPGLPlotter (in, out, err)
872 {
873 _pl_q_initialize ();
874 }
875
PCLPlotter(ostream & out)876 PCLPlotter::PCLPlotter (ostream& out)
877 : HPGLPlotter (out)
878 {
879 _pl_q_initialize ();
880 }
881
PCLPlotter()882 PCLPlotter::PCLPlotter ()
883 {
884 _pl_q_initialize ();
885 }
886
PCLPlotter(FILE * infile,FILE * outfile,FILE * errfile,PlotterParams & parameters)887 PCLPlotter::PCLPlotter (FILE *infile, FILE *outfile, FILE *errfile, PlotterParams ¶meters)
888 :HPGLPlotter (infile, outfile, errfile, parameters)
889 {
890 _pl_q_initialize ();
891 }
892
PCLPlotter(FILE * outfile,PlotterParams & parameters)893 PCLPlotter::PCLPlotter (FILE *outfile, PlotterParams ¶meters)
894 :HPGLPlotter (outfile, parameters)
895 {
896 _pl_q_initialize ();
897 }
898
PCLPlotter(istream & in,ostream & out,ostream & err,PlotterParams & parameters)899 PCLPlotter::PCLPlotter (istream& in, ostream& out, ostream& err, PlotterParams ¶meters)
900 : HPGLPlotter (in, out, err, parameters)
901 {
902 _pl_q_initialize ();
903 }
904
PCLPlotter(ostream & out,PlotterParams & parameters)905 PCLPlotter::PCLPlotter (ostream& out, PlotterParams ¶meters)
906 : HPGLPlotter (out, parameters)
907 {
908 _pl_q_initialize ();
909 }
910
PCLPlotter(PlotterParams & parameters)911 PCLPlotter::PCLPlotter (PlotterParams ¶meters)
912 : HPGLPlotter (parameters)
913 {
914 _pl_q_initialize ();
915 }
916
~PCLPlotter()917 PCLPlotter::~PCLPlotter ()
918 {
919 /* if luser left the Plotter open, close it */
920 if (_plotter->data->open)
921 _API_closepl ();
922
923 _pl_q_terminate ();
924 }
925 #endif
926
927 #ifndef LIBPLOTTER
928 /* The following forwarding functions provide special support in libplot
929 for deriving the PCLPlotter class from the HPGLPlotter class. In
930 libplotter, forwarding is implemented by a virtual function; see
931 plotter.h. */
932
933 /* Two forwarding functions called by any HPGLPlotter/PCLPlotter in
934 begin_page() and end_page(), respectively. See h_openpl.c and
935 h_closepl.c for the forwarded-to functions _pl_h_maybe_switch_to_hpgl(),
936 _pl_q_maybe_switch_to_hpgl(), _pl_h_maybe_switch_from_hpgl(),
937 _pl_q_maybe_switch_from_hpgl(). The HPGLPlotter versions are no-ops, but
938 the PCLPlotter versions switch the printer to HP-GL/2 mode from PCL 5
939 mode, and back to PCL 5 mode from HP-GL/2 mode. */
940
941 /* Eject page (if page number > 1) and switch from PCL 5 mode to HP-GL/2
942 mode, if a PCL 5 printer (otherwise it's a no-op). Invoked by
943 begin_page(). */
944 void
_maybe_switch_to_hpgl(Plotter * _plotter)945 _maybe_switch_to_hpgl (Plotter *_plotter)
946 {
947 switch ((int)(_plotter->data->type))
948 {
949 case (int)PL_HPGL:
950 default:
951 _pl_h_maybe_switch_to_hpgl (_plotter); /* no-op */
952 break;
953 case (int)PL_PCL:
954 _pl_q_maybe_switch_to_hpgl (_plotter);
955 break;
956 }
957 }
958
959 /* Switch back to PCL 5 mode from HP-GL/2 mode, if a PCL 5 printer
960 (otherwise it's a no-op). Invoked by end_page(). */
961 void
_maybe_switch_from_hpgl(Plotter * _plotter)962 _maybe_switch_from_hpgl (Plotter *_plotter)
963 {
964 switch ((int)(_plotter->data->type))
965 {
966 case (int)PL_HPGL:
967 default:
968 _pl_h_maybe_switch_from_hpgl (_plotter); /* no-op */
969 break;
970 case (int)PL_PCL:
971 _pl_q_maybe_switch_from_hpgl (_plotter);
972 break;
973 }
974 }
975 #endif /* not LIBPLOTTER */
976