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 /* The paint_marker method, which is an internal function that is called
20 when the marker() method is invoked. It plots an object: a marker of a
21 specified type, at a specified size, at the current location.
22
23 If this returns `false', marker() will construct the marker from other
24 libplot primitives, in a generic way. */
25
26 /* This implementation is for CGM Plotters. CGM format supports the first
27 few of our marker types, as CGM primitive objects. */
28
29 #include "sys-defines.h"
30 #include "extern.h"
31
32 /* The maximum dimension of most markers, e.g. the diameter of the circle
33 marker (marker #4). Expressed as a fraction of the `size' argument. */
34 #define MAXIMUM_MARKER_DIMENSION (5.0/8.0)
35
36 bool
_pl_c_paint_marker(R___ (Plotter * _plotter)int type,double size)37 _pl_c_paint_marker (R___(Plotter *_plotter) int type, double size)
38 {
39 int desired_marker_type, desired_marker_size;
40 double xd, yd, size_d;
41 int i_x, i_y;
42
43 switch (type)
44 {
45 case M_DOT:
46 desired_marker_type = CGM_M_DOT;
47 break;
48 case M_PLUS:
49 desired_marker_type = CGM_M_PLUS;
50 break;
51 case M_ASTERISK:
52 desired_marker_type = CGM_M_ASTERISK;
53 break;
54 case M_CIRCLE:
55 desired_marker_type = CGM_M_CIRCLE;
56 break;
57 case M_CROSS:
58 desired_marker_type = CGM_M_CROSS;
59 break;
60 default:
61 return false; /* can't draw it in CGM format */
62 break;
63 }
64
65 if (_plotter->drawstate->pen_type != 0)
66 /* have a pen to draw with */
67 {
68 if (_plotter->cgm_marker_type != desired_marker_type)
69 /* emit "MARKER TYPE" command */
70 {
71 int byte_count, data_byte_count, data_len;
72
73 data_len = 2; /* number of bytes per index */
74 byte_count = data_byte_count = 0;
75 _cgm_emit_command_header (_plotter->data->page, _plotter->cgm_encoding,
76 CGM_ATTRIBUTE_ELEMENT, 6,
77 data_len, &byte_count,
78 "MARKERTYPE");
79 _cgm_emit_index (_plotter->data->page, false, _plotter->cgm_encoding,
80 desired_marker_type,
81 data_len, &data_byte_count, &byte_count);
82 _cgm_emit_command_terminator (_plotter->data->page, _plotter->cgm_encoding,
83 &byte_count);
84
85 /* update marker type */
86 _plotter->cgm_marker_type = desired_marker_type;
87 }
88
89 /* compute size of marker in device frame */
90 size_d = sqrt(XDV(size,0)*XDV(size,0)+YDV(size,0)*YDV(size,0));
91 desired_marker_size = IROUND(MAXIMUM_MARKER_DIMENSION * size_d);
92
93 if (desired_marker_type != CGM_M_DOT
94 && _plotter->cgm_marker_size != desired_marker_size)
95 /* emit "MARKER SIZE" command (for a dot we don't bother, since
96 dots are meant to be drawn as small as possible) */
97 {
98 int byte_count, data_byte_count, data_len;
99
100 data_len = CGM_BINARY_BYTES_PER_INTEGER;
101 byte_count = data_byte_count = 0;
102 _cgm_emit_command_header (_plotter->data->page, _plotter->cgm_encoding,
103 CGM_ATTRIBUTE_ELEMENT, 7,
104 data_len, &byte_count,
105 "MARKERSIZE");
106 _cgm_emit_integer (_plotter->data->page, false, _plotter->cgm_encoding,
107 desired_marker_size,
108 data_len, &data_byte_count, &byte_count);
109 _cgm_emit_command_terminator (_plotter->data->page, _plotter->cgm_encoding,
110 &byte_count);
111
112 /* update marker size */
113 _plotter->cgm_marker_size = desired_marker_size;
114 }
115
116 /* set CGM marker color */
117 _pl_c_set_pen_color (R___(_plotter) CGM_OBJECT_MARKER);
118
119 /* compute location in device frame */
120 xd = XD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y);
121 yd = YD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y);
122 i_x = IROUND(xd);
123 i_y = IROUND(yd);
124
125 /* emit "POLYMARKER" command, to draw a single marker */
126 {
127 int byte_count, data_byte_count, data_len;
128
129 data_len = 1 * 2 * CGM_BINARY_BYTES_PER_INTEGER;
130 byte_count = data_byte_count = 0;
131 _cgm_emit_command_header (_plotter->data->page, _plotter->cgm_encoding,
132 CGM_GRAPHICAL_PRIMITIVE_ELEMENT, 3,
133 data_len, &byte_count,
134 "MARKER");
135 _cgm_emit_point (_plotter->data->page, false, _plotter->cgm_encoding,
136 i_x, i_y,
137 data_len, &data_byte_count, &byte_count);
138 _cgm_emit_command_terminator (_plotter->data->page, _plotter->cgm_encoding,
139 &byte_count);
140 }
141 }
142
143 return true;
144 }
145
146