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