1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4 * Parts Copyright (c) 1989-2007 by Brian V. Smith
5 * Parts Copyright (c) 1991 by Paul King
6 *
7 * Any party obtaining a copy of these files is granted, free of charge, a
8 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
9 * nonexclusive right and license to deal in this software and documentation
10 * files (the "Software"), including without limitation the rights to use,
11 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
12 * the Software, and to permit persons who receive copies from any such
13 * party to do so, with the only requirement being that the above copyright
14 * and this permission notice remain intact.
15 *
16 */
17
18 #include "fig.h"
19 #include "figx.h"
20 #include "resources.h"
21 #include "mode.h"
22 #include "paintop.h"
23 #include "object.h"
24 #include "w_indpanel.h"
25 #include "w_setup.h"
26 #include "w_util.h"
27 #include "w_zoom.h"
28
29 #include "u_redraw.h"
30
31 #define null_width 32
32 #define null_height 32
33
34 static char null_bits[null_width * null_height / 8] = {0};
35
36 static Pixmap null_pm, grid_pm = 0;
37 static unsigned long bg, fg;
38
39
40
init_grid(void)41 void init_grid(void)
42 {
43 DeclareArgs(2);
44
45 if (null_pm == 0) {
46 FirstArg(XtNbackground, &bg);
47 NextArg(XtNforeground, &fg);
48 GetValues(canvas_sw);
49
50 null_pm = XCreatePixmapFromBitmapData(tool_d, canvas_win,
51 (char *) null_bits, null_width, null_height,
52 fg, bg, tool_dpth);
53 }
54 }
55
56 /* grid in X11 is simply the background of the canvas */ // isometric grid
57
setup_grid(void)58 void setup_grid(void)
59 {
60 double spacing; /* grid spacing in pixels */
61 double x, x0c, y, y0c, y1c;
62 int grid, grid_unit;
63 int dim; /* size of grid pixmap in pixels */
64 int xdim, ydim;
65 double xs, ys, yd;
66 static int prev_grid = -1;
67
68 DeclareArgs(2);
69
70 grid = cur_gridmode;
71
72 if( grid == GRID_0 ) {
73 FirstArg( XtNbackgroundPixmap, null_pm );
74 } else if( cur_gridtype == GRID_ISO ) {
75 grid_unit = cur_gridunit;
76
77 /* user scale not = 1.0, use tenths of inch if inch scale */
78 if (appres.userscale != 1.0 && appres.INCHES)
79 grid_unit = TENTH_UNIT;
80 ys = grid_spacing[grid_unit][(grid-1)%GRID_4] * zoomscale/appres.userscale;
81
82 /* if zoom is small, use larger grid */
83 while( ys < 5.0 && ++grid <= GRID_4 ) {
84 ys = grid_spacing[grid_unit][(grid-1)%GRID_4] * zoomscale/appres.userscale;
85 }
86
87 /* round to three decimal places */
88 xs = ys * cos( 30.0 / 180.0 * M_PI );
89 ys = (int) ( ys * 1000.0 ) / 1000.0;
90 xs = (int) ( xs * 1000.0 ) / 1000.0;
91
92 if( ys <= 4.0 ) {
93 /* too small at this zoom, no grid */
94 FirstArg(XtNbackgroundPixmap, null_pm);
95 redisplay_canvas();
96 } else {
97 /* size of the pixmap equal to 1 inch or 2 cm to reset any
98 error at those boundaries */
99 dim = (int) round(appres.INCHES?
100 PIX_PER_INCH*zoomscale/appres.userscale:
101 2*PIX_PER_CM*zoomscale/appres.userscale);
102
103 /* HOWEVER, if that is a ridiculous size, limit it to approx screen size */
104 if (dim > CANVAS_WD)
105 dim = CANVAS_WD;
106
107 /* set both dimensions */
108 xdim = ydim = dim;
109
110 /* align vertical dim and spacing */
111 while( fabs( (float) ydim / ys - (int) ( (float) ydim / ys ) ) > 0.01 ) {
112 ydim++;
113 if( ydim > CANVAS_HT ) break;
114 }
115 /* align horizontal dim and spacing */
116 while( fabs( (float) xdim / ( 2.0 * xs ) - (int) ( (float) xdim / ( 2.0 * xs ) ) ) > 0.01 ) {
117 xdim++;
118 if( xdim > CANVAS_WD ) break;
119 }
120
121 /* debug dump */
122 // printf( "xs: %f\t ys: %f\n", xs, ys );
123 // printf( "xdim: %i\t ydim: %i\n", xdim, ydim );
124
125 /* clear pixmap */
126 if (grid_pm) XFreePixmap(tool_d, grid_pm);
127 grid_pm = XCreatePixmap(tool_d, canvas_win, xdim, ydim, tool_dpth);
128
129 /* first fill the pixmap with the background color */
130 XSetForeground(tool_d, grid_gc, bg);
131 XFillRectangle(tool_d, grid_pm, grid_gc, 0, 0, xdim, ydim);
132
133 /* calculate horizontal offset */
134 x0c = -fmod( (double) zoomscale * zoomxoff, ( 2.0 * xs ) );
135 if( ( 2.0 * xs ) - x0c < 0.5 ) x0c = 0.0;
136
137 /* calculate vertical offsets */
138 y0c = fmod( -x0c * ( ys / 2.0 ) / xs - zoomscale * zoomyoff, ys );
139 y1c = fmod( x0c * ( ys / 2.0 ) / xs - zoomscale * zoomyoff, ys );
140 // printf( "y0c: %f\t y1c: %f\n", y0c, y1c );
141
142 /* set grid color */
143 XSetForeground(tool_d, grid_gc, grid_color);
144
145 /* draw horizontal lines */
146 for( x = x0c - xs; x < xdim; x += xs )
147 XDrawLine( tool_d, grid_pm, grid_gc, (int) round(x), 0, (int) round(x), ydim );
148
149 /* draw diagonal lines */
150 yd = xdim * ( ys / 2.0 ) / xs;
151 for( y = y0c - (int) ( ydim / ys + 1 ) * ys; y < ydim; y += ys )
152 XDrawLine( tool_d, grid_pm, grid_gc, 0, (int) round(y), xdim, (int) round( y + yd ) );
153 for( y = y1c; y < ydim + (int) ( ydim / ys + 1 ) * ys; y += ys )
154 XDrawLine( tool_d, grid_pm, grid_gc, 0, (int) round(y), xdim, (int) round( y - yd ) );
155 // XDrawLine( tool_d, grid_pm, grid_gc, 0, 0, xdim, ydim );
156
157
158 FirstArg(XtNbackgroundPixmap, grid_pm);
159 }
160 } else {
161 grid_unit = cur_gridunit;
162
163 /* user scale not = 1.0, use tenths of inch if inch scale */
164 if (appres.userscale != 1.0 && appres.INCHES)
165 grid_unit = TENTH_UNIT;
166 spacing = grid_spacing[grid_unit][(grid-1)%GRID_4] * zoomscale/appres.userscale;
167
168 /* if zoom is small, use larger grid */
169 while (spacing < 5.0 && ++grid <= GRID_4) {
170 spacing = grid_spacing[grid_unit][(grid-1)%GRID_4] * zoomscale/appres.userscale;
171 }
172 /* round to three decimal places */
173 spacing = (int) (spacing*1000.0) / 1000.0;
174 // printf( "spacing: %f\n", spacing );
175
176 if (spacing <= 4.0) {
177 /* too small at this zoom, no grid */
178 FirstArg(XtNbackgroundPixmap, null_pm);
179 redisplay_canvas();
180 } else {
181 /* size of the pixmap equal to 1 inch or 2 cm to reset any
182 error at those boundaries */
183 dim = (int) round(appres.INCHES?
184 PIX_PER_INCH*zoomscale/appres.userscale:
185 2*PIX_PER_CM*zoomscale/appres.userscale);
186
187 // printf( "dim: %i\t", dim );
188
189 /* HOWEVER, if that is a ridiculous size, limit it to approx screen size */
190 if (dim > CANVAS_WD)
191 dim = CANVAS_WD;
192 // printf( "dim: %i\t", dim );
193
194 /* Do something... does not make sense... */
195 while (fabs((float) dim / spacing - (int) ((float) dim / spacing)) > 0.01) {
196 dim++;
197 if (dim > CANVAS_WD)
198 break;
199 }
200 // printf( "dim: %i\n", dim );
201
202 if (grid_pm) XFreePixmap(tool_d, grid_pm);
203 grid_pm = XCreatePixmap(tool_d, canvas_win, dim, dim, tool_dpth);
204
205 /* first fill the pixmap with the background color */
206 XSetForeground(tool_d, grid_gc, bg);
207 XFillRectangle(tool_d, grid_pm, grid_gc, 0, 0, dim, dim);
208
209 /* now write the grid in the grid color */
210 XSetForeground(tool_d, grid_gc, grid_color);
211 x0c = -fmod((double) zoomscale * zoomxoff, spacing);
212 y0c = -fmod((double) zoomscale * zoomyoff, spacing);
213 // printf( "zxo: %f\t zyo: %f\n", (double)zoomscale * zoomxoff, (double)zoomscale * zoomyoff );
214 // printf( "x0c: %f\t y0c: %f\n", x0c, y0c );
215
216 /* does not make sense, spacing > 4 and x0c < 0 */
217 if (spacing - x0c < 0.5) x0c = 0.0;
218 if (spacing - y0c < 0.5) y0c = 0.0;
219
220 /* draw the lines */
221 for (x = x0c; x < dim; x += spacing)
222 XDrawLine(tool_d, grid_pm, grid_gc, (int) round(x), 0, (int) round(x), dim);
223 for (y = y0c; y < dim; y += spacing)
224 XDrawLine(tool_d, grid_pm, grid_gc, 0, (int) round(y), dim, (int) round(y));
225 // printf( "done\n" );
226
227 FirstArg(XtNbackgroundPixmap, grid_pm);
228 }
229 }
230 SetValues(canvas_sw);
231 if (prev_grid == GRID_0 && grid == GRID_0)
232 redisplay_canvas();
233 prev_grid = grid;
234 }
235