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