1 /* This file is part of the GNU libxmi package.  Copyright (C) 1998, 1999,
2    2000, 2005, Free Software Foundation, Inc.
3 
4    The GNU libxmi 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 libxmi 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 #include "sys-defines.h"
20 #include "extern.h"
21 
22 /* These functions create, manipulate and destroy miGC structures.  A
23    pointer to an miGC is passed as the third argument to each of libxmi's
24    public drawing functions.  It comprises high-level drawing parameters.
25    The miGC structure is defined in mi_gc.h. */
26 
27 #include "xmi.h"
28 #include "mi_spans.h"
29 #include "mi_gc.h"
30 #include "mi_api.h"
31 
32 /* create a new miGC, with elements initialized to default values (the same
33    default values that are used by X11) */
34 
35 miGC *
miNewGC(int npixels,const miPixel * pixels)36 miNewGC (int npixels, const miPixel *pixels)
37 {
38   miGC *new_gc;
39   int i;
40 
41   new_gc = (miGC *)mi_xmalloc (sizeof (miGC));
42   new_gc->fillRule = MI_EVEN_ODD_RULE;
43   new_gc->joinStyle = MI_JOIN_MITER;
44   new_gc->capStyle = MI_CAP_BUTT;
45   new_gc->lineStyle = MI_LINE_SOLID;
46   new_gc->arcMode = MI_ARC_PIE_SLICE;
47   new_gc->lineWidth = (unsigned int)0;
48   new_gc->miterLimit = 10.43;	/* same as hardcoded in X11 */
49   new_gc->dashOffset = 0;
50   new_gc->numInDashList = 2;
51   new_gc->dash = (unsigned int *)mi_xmalloc (2 * sizeof(unsigned int));
52   for (i = 0; i < 2; i++)
53     new_gc->dash[i] = 4;	/* { 4, 4 }; same as in X11? */
54   new_gc->numPixels = npixels;
55   new_gc->pixels = (miPixel *)mi_xmalloc (npixels * sizeof (miPixel));
56   for (i = 0; i < npixels; i++)
57     new_gc->pixels[i] = pixels[i];
58 
59   return new_gc;
60 }
61 
62 /* destroy (deallocate) an miGC */
63 
64 void
miDeleteGC(miGC * pGC)65 miDeleteGC (miGC *pGC)
66 {
67   if (pGC == (miGC *)NULL)
68     return;
69   if (pGC->dash)
70     free (pGC->dash);
71   free (pGC->pixels);
72   free (pGC);
73 }
74 
75 /* copy an miGC */
76 
77 miGC *
miCopyGC(const miGC * pGC)78 miCopyGC (const miGC *pGC)
79 {
80   miGC *new_gc;
81   int i;
82 
83   if (pGC == (const miGC *)pGC)
84     return (miGC *)NULL;
85 
86   new_gc = (miGC *)mi_xmalloc (sizeof (miGC));
87   new_gc->fillRule = pGC->fillRule;
88   new_gc->joinStyle = pGC->joinStyle;
89   new_gc->capStyle = pGC->capStyle;
90   new_gc->lineStyle = pGC->lineStyle;
91   new_gc->arcMode = pGC->arcMode;
92   new_gc->lineWidth = pGC->lineWidth;
93   new_gc->miterLimit = pGC->miterLimit;
94   new_gc->dashOffset = pGC->dashOffset;
95   new_gc->numInDashList = pGC->numInDashList;
96   if (pGC->numInDashList == 0)
97     new_gc->dash = (unsigned int *)NULL;
98   else
99     {
100       new_gc->dash =
101 	(unsigned int *)mi_xmalloc (pGC->numInDashList * sizeof(unsigned int));
102       for (i = 0; i < pGC->numInDashList; i++)
103 	new_gc->dash[i] = pGC->dash[i];
104     }
105   new_gc->pixels =
106     (miPixel *)mi_xmalloc (pGC->numPixels * sizeof(miPixel));
107   for (i = 0; i < pGC->numPixels; i++)
108     new_gc->pixels[i] = pGC->pixels[i];
109 
110   return new_gc;
111 }
112 
113 /* set a single integer-valued miGC attribute */
114 
115 void
miSetGCAttrib(miGC * pGC,miGCAttribute attribute,int value)116 miSetGCAttrib (miGC *pGC, miGCAttribute attribute, int value)
117 {
118   if (pGC == (miGC *)NULL || value < 0)
119     return;
120   switch ((int)attribute)
121     {
122     case (int)MI_GC_FILL_RULE:
123       pGC->fillRule = value;
124       break;
125     case (int)MI_GC_JOIN_STYLE:
126       pGC->joinStyle = value;
127       break;
128     case (int)MI_GC_CAP_STYLE:
129       pGC->capStyle = value;
130       break;
131     case (int)MI_GC_LINE_STYLE:
132       pGC->lineStyle = value;
133       break;
134     case (int)MI_GC_ARC_MODE:
135       pGC->arcMode = value;
136       break;
137     case (int)MI_GC_LINE_WIDTH:
138       if (value >= 0)
139 	pGC->lineWidth = (unsigned int)value;
140       break;
141     default:			/* unknown attribute type */
142       break;
143     }
144 }
145 
146 /* set many integer-valued miGC attributes, at a single time */
147 
148 void
miSetGCAttribs(miGC * pGC,int nattributes,const miGCAttribute * attributes,const int * values)149 miSetGCAttribs (miGC *pGC, int nattributes, const miGCAttribute *attributes, const int *values)
150 {
151   int i;
152   miGCAttribute attribute;
153   int value;
154 
155   if (nattributes <= 0 || pGC == (miGC *)NULL)
156     return;
157   for (i = 0; i < nattributes; i++)
158     {
159       attribute = *attributes++;
160       value = *values++;
161 
162       if (value < 0)		/* invalid; be tolerant */
163 	continue;
164       switch ((int)attribute)
165 	{
166 	case (int)MI_GC_FILL_RULE:
167 	  pGC->fillRule = value;
168 	  break;
169 	case (int)MI_GC_JOIN_STYLE:
170 	  pGC->joinStyle = value;
171 	  break;
172 	case (int)MI_GC_CAP_STYLE:
173 	  pGC->capStyle = value;
174 	  break;
175 	case (int)MI_GC_LINE_STYLE:
176 	  pGC->lineStyle = value;
177 	  break;
178 	case (int)MI_GC_ARC_MODE:
179 	  pGC->arcMode = value;
180 	  break;
181 	case (int)MI_GC_LINE_WIDTH:
182 	  if (value >= 0)
183 	    pGC->lineWidth = (unsigned int)value;
184 	  break;
185 	default:			/* unknown attribute type */
186 	  break;
187 	}
188     }
189 }
190 
191 /* set the only float-valued miGC attribute (the miter limit) */
192 
193 void
miSetGCMiterLimit(miGC * pGC,double value)194 miSetGCMiterLimit (miGC *pGC, double value)
195 {
196   if (pGC == (miGC *)NULL)
197     return;
198   pGC->miterLimit = value;
199 }
200 
201 /* set the dash-related attributes in an miGC */
202 
203 void
miSetGCDashes(miGC * pGC,int ndashes,const unsigned int * dashes,int offset)204 miSetGCDashes (miGC *pGC, int ndashes, const unsigned int *dashes, int offset)
205 {
206   int i;
207 
208   if (pGC == (miGC *)NULL || ndashes < 0)
209     return;
210   if (pGC->dash)
211     free (pGC->dash);
212   pGC->dashOffset = offset;
213   pGC->numInDashList = ndashes;
214   if (ndashes == 0)
215     pGC->dash = (unsigned int *)NULL;
216   else
217     {
218       pGC->dash = (unsigned int *)mi_xmalloc (ndashes * sizeof(unsigned int));
219       for (i = 0; i < ndashes; i++)
220 	pGC->dash[i] = dashes[i];
221     }
222 }
223 
224 /* set the pixel array in a miGC */
225 void
miSetGCPixels(miGC * pGC,int npixels,const miPixel * pixels)226 miSetGCPixels (miGC *pGC, int npixels, const miPixel *pixels)
227 {
228   int i;
229 
230   if (pGC == (miGC *)NULL || npixels < 2)
231     return;
232   free (pGC->pixels);
233   pGC->numPixels = npixels;
234   pGC->pixels = (miPixel *)mi_xmalloc (npixels * sizeof (miPixel));
235   for (i = 0; i < npixels; i++)
236     pGC->pixels[i] = pixels[i];
237 }
238