1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include "preferences.h"
32 /** Calculate the width (in cm) of the gap between grid lines in dynamic
36 calculate_dynamic_grid(DDisplay
*ddisp
, real
*width_x
, real
*width_y
)
38 real zoom
= ddisplay_untransform_length(ddisp
, 1.0);
39 /* Twiddle zoom to make change-over appropriate */
41 return pow(10, ceil(log10(zoom
)));
45 grid_draw_horizontal_lines(DDisplay
*ddisp
, Rectangle
*update
, real length
)
50 guint major_lines
= ddisp
->diagram
->data
->grid
.major_lines
;
51 DiaRenderer
*renderer
= ddisp
->renderer
;
52 DiaInteractiveRendererInterface
*irenderer
;
55 irenderer
= DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer
);
57 pos
= ceil( update
->top
/ length
) * length
;
58 ddisplay_transform_coords(ddisp
, update
->left
, pos
, &x
, &y
);
59 ddisplay_transform_coords(ddisp
, update
->right
, update
->bottom
, &width
, &height
);
62 major_count
= pos
/length
;
63 major_count
%= major_lines
;
69 DIA_RENDERER_GET_CLASS(renderer
)->set_linestyle(renderer
, LINESTYLE_SOLID
);
71 DIA_RENDERER_GET_CLASS(renderer
)->set_linestyle(renderer
, LINESTYLE_DOTTED
);
72 major_count
= (major_count
+1)%major_lines
;
74 irenderer
->draw_pixel_line(renderer
, x
, y
, width
, y
,
75 &ddisp
->diagram
->data
->grid
.colour
);
77 ddisplay_transform_coords(ddisp
, update
->left
, pos
, &x
, &y
);
82 grid_draw_vertical_lines(DDisplay
*ddisp
, Rectangle
*update
, real length
)
87 guint major_lines
= ddisp
->diagram
->data
->grid
.major_lines
;
88 DiaRenderer
*renderer
= ddisp
->renderer
;
89 DiaInteractiveRendererInterface
*irenderer
;
92 irenderer
= DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer
);
94 pos
= ceil( update
->left
/ length
) * length
;
95 ddisplay_transform_coords(ddisp
, update
->right
, update
->bottom
, &width
, &height
);
98 major_count
= pos
/length
;
99 major_count
%= major_lines
;
103 ddisplay_transform_coords(ddisp
, pos
, update
->top
, &x
, &y
);
105 if (major_count
== 0)
106 DIA_RENDERER_GET_CLASS(renderer
)->set_linestyle(renderer
, LINESTYLE_SOLID
);
108 DIA_RENDERER_GET_CLASS(renderer
)->set_linestyle(renderer
, LINESTYLE_DOTTED
);
109 major_count
= (major_count
+1)%major_lines
;
111 irenderer
->draw_pixel_line(renderer
, x
, y
, x
, height
,
112 &ddisp
->diagram
->data
->grid
.colour
);
118 grid_draw_hex(DDisplay
*ddisp
, Rectangle
*update
, real length
)
120 real horiz_pos
, vert_pos
;
121 int to_x
, to_y
, x
, y
;
122 DiaRenderer
*renderer
= ddisp
->renderer
;
123 DiaInteractiveRendererInterface
*irenderer
;
125 irenderer
= DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer
);
127 /* First horizontal lines: */
128 vert_pos
= ceil( update
->top
/ (length
* sqrt(3)) ) * length
* sqrt(3);
129 while (vert_pos
<= update
->bottom
) {
130 horiz_pos
= ceil( (update
->left
) / (3 * length
) ) * length
* 3 - length
* 2.5;
131 while (horiz_pos
<= update
->right
) {
132 ddisplay_transform_coords(ddisp
, horiz_pos
, vert_pos
, &x
, &y
);
133 ddisplay_transform_coords(ddisp
, horiz_pos
+ length
, vert_pos
, &to_x
, &y
);
135 irenderer
->draw_pixel_line(renderer
,
137 &ddisp
->diagram
->data
->grid
.colour
);
138 horiz_pos
+= 3 * length
;
141 vert_pos
+= sqrt(3) * length
;
144 /* Second horizontal lines: */
145 vert_pos
= ceil( update
->top
/ (length
* sqrt(3)) ) * length
* sqrt(3) - 0.5 * sqrt(3) * length
;
146 while (vert_pos
<= update
->bottom
) {
147 horiz_pos
= ceil( (update
->left
) / (3 * length
) ) * length
* 3 - length
;
148 while (horiz_pos
<= update
->right
) {
149 ddisplay_transform_coords(ddisp
, horiz_pos
, vert_pos
, &x
, &y
);
150 ddisplay_transform_coords(ddisp
, horiz_pos
+length
, vert_pos
, &to_x
, &y
);
152 irenderer
->draw_pixel_line(renderer
,
154 &ddisp
->diagram
->data
->grid
.colour
);
155 horiz_pos
+= 3 * length
;
158 vert_pos
+= sqrt(3) * length
;
161 /* First \'s and /'s */
162 vert_pos
= ceil( update
->top
/ (length
* sqrt(3)) ) * length
* sqrt(3) - length
* sqrt(3);
163 while (vert_pos
<= update
->bottom
) {
164 horiz_pos
= ceil( (update
->left
) / (3 * length
) ) * length
* 3 - length
* 2.5;
165 while (horiz_pos
<= update
->right
) {
166 ddisplay_transform_coords(ddisp
, horiz_pos
+ length
, vert_pos
, &x
, &y
);
167 ddisplay_transform_coords(ddisp
, horiz_pos
+ 1.5 * length
, vert_pos
+ length
* sqrt(3) * 0.5, &to_x
, &to_y
);
169 irenderer
->draw_pixel_line(renderer
,
171 &ddisp
->diagram
->data
->grid
.colour
);
173 ddisplay_transform_coords(ddisp
, horiz_pos
, vert_pos
, &x
, &y
);
174 ddisplay_transform_coords(ddisp
, horiz_pos
- 0.5 * length
, vert_pos
+ length
* sqrt(3) * 0.5, &to_x
, &to_y
);
176 irenderer
->draw_pixel_line(renderer
,
178 &ddisp
->diagram
->data
->grid
.colour
);
179 horiz_pos
+= 3 * length
;
182 vert_pos
+= sqrt(3) * length
;
185 /* Second \'s and /'s */
186 vert_pos
= ceil( update
->top
/ (length
* sqrt(3)) ) * length
* sqrt(3) - 0.5 * sqrt(3) * length
;
187 while (vert_pos
<= update
->bottom
) {
188 horiz_pos
= ceil( (update
->left
) / (3 * length
) ) * length
* 3 - length
;
189 while (horiz_pos
<= update
->right
) {
190 ddisplay_transform_coords(ddisp
, horiz_pos
, vert_pos
, &x
, &y
);
191 ddisplay_transform_coords(ddisp
, horiz_pos
- 0.5 * length
, vert_pos
+ 0.5 * sqrt(3) * length
, &to_x
, &to_y
);
193 irenderer
->draw_pixel_line(renderer
,
195 &ddisp
->diagram
->data
->grid
.colour
);
197 ddisplay_transform_coords(ddisp
, horiz_pos
+ length
, vert_pos
, &x
, &y
);
198 ddisplay_transform_coords(ddisp
, horiz_pos
+ 1.5 * length
, vert_pos
+ 0.5 * sqrt(3) * length
, &to_x
, &to_y
);
200 irenderer
->draw_pixel_line(renderer
,
202 &ddisp
->diagram
->data
->grid
.colour
);
203 horiz_pos
+= 3 * length
;
206 vert_pos
+= sqrt(3) * length
;
212 grid_draw(DDisplay
*ddisp
, Rectangle
*update
)
214 Grid
*grid
= &ddisp
->grid
;
215 DiaRenderer
*renderer
= ddisp
->renderer
;
219 int width
= dia_renderer_get_width_pixels(ddisp
->renderer
);
220 int height
= dia_renderer_get_height_pixels(ddisp
->renderer
);
221 /* distance between visible grid lines */
222 real width_x
= ddisp
->diagram
->data
->grid
.width_x
;
223 real width_y
= ddisp
->diagram
->data
->grid
.width_y
;
224 real width_w
= ddisp
->diagram
->data
->grid
.width_w
;
225 if (ddisp
->diagram
->data
->grid
.dynamic
) {
226 width_x
= width_y
= calculate_dynamic_grid(ddisp
, &width_x
, &width_y
);
228 width_x
= ddisp
->diagram
->data
->grid
.width_x
*
229 ddisp
->diagram
->data
->grid
.visible_x
;
230 width_y
= ddisp
->diagram
->data
->grid
.width_y
*
231 ddisp
->diagram
->data
->grid
.visible_y
;
234 DIA_RENDERER_GET_CLASS(renderer
)->set_linewidth(renderer
, 0.0);
235 DIA_RENDERER_GET_CLASS(renderer
)->set_dashlength(renderer
,
236 ddisplay_untransform_length(ddisp
, 31));
238 if (ddisp
->diagram
->data
->grid
.hex
) {
239 grid_draw_hex(ddisp
, update
, width_w
);
241 if (ddisplay_transform_length(ddisp
, width_y
) >= 2.0 &&
242 ddisplay_transform_length(ddisp
, width_x
) >= 2.0) {
243 /* Vertical lines: */
244 grid_draw_vertical_lines(ddisp
, update
, width_x
);
245 /* Horizontal lines: */
246 grid_draw_horizontal_lines(ddisp
, update
, width_y
);
253 pagebreak_draw(DDisplay
*ddisp
, Rectangle
*update
)
255 DiaRenderer
*renderer
= ddisp
->renderer
;
256 DiaInteractiveRendererInterface
*irenderer
;
258 int width
= dia_renderer_get_width_pixels(ddisp
->renderer
);
259 int height
= dia_renderer_get_height_pixels(ddisp
->renderer
);
261 irenderer
= DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer
);
262 if (prefs
.pagebreak
.visible
) {
263 Diagram
*dia
= ddisp
->diagram
;
264 real origx
= 0, origy
= 0, pos
;
265 real pwidth
= dia
->data
->paper
.width
;
266 real pheight
= dia
->data
->paper
.height
;
269 DIA_RENDERER_GET_CLASS(renderer
)->set_linewidth(renderer
, 0.0);
270 DIA_RENDERER_GET_CLASS(renderer
)->set_dashlength(renderer
,
271 ddisplay_untransform_length(ddisp
, 31));
272 if (prefs
.pagebreak
.solid
)
273 DIA_RENDERER_GET_CLASS(renderer
)->set_linestyle(renderer
, LINESTYLE_SOLID
);
275 DIA_RENDERER_GET_CLASS(renderer
)->set_linestyle(renderer
, LINESTYLE_DOTTED
);
277 if (dia
->data
->paper
.fitto
) {
278 origx
= dia
->data
->extents
.left
;
279 origy
= dia
->data
->extents
.top
;
282 /* vertical lines ... */
283 pos
= origx
+ ceil((update
->left
- origx
) / pwidth
) * pwidth
;
284 while (pos
<= update
->right
) {
285 ddisplay_transform_coords(ddisp
, pos
,0,&x
,&y
);
286 irenderer
->draw_pixel_line(renderer
,
288 &dia
->data
->pagebreak_color
);
291 /* Horizontal lines: */
292 pos
= origy
+ ceil((update
->top
- origy
) / pheight
) * pheight
;
293 while (pos
<= update
->bottom
) {
294 ddisplay_transform_coords(ddisp
, 0,pos
,&x
,&y
);
295 irenderer
->draw_pixel_line(renderer
,
297 &dia
->data
->pagebreak_color
);
304 snap_to_grid(DDisplay
*ddisp
, coord
*x
, coord
*y
)
306 if (ddisp
->grid
.snap
) {
307 if (prefs
.grid
.hex
) {
308 real width_x
= ddisp
->diagram
->data
->grid
.width_w
;
309 real x_mod
= (*x
- 1*width_x
) - floor((*x
- 1*width_x
) / (3*width_x
)) * 3 * width_x
;
310 real y_mod
= (*y
- 0.25*sqrt(3) * width_x
) -
311 floor((*y
- 0.25 * sqrt(3) * width_x
) / (sqrt(3)*width_x
)) * sqrt(3) * width_x
;
313 if ( x_mod
< (1.5 * width_x
) ) {
314 if ( y_mod
< 0.5 * sqrt(3) * width_x
) {
315 *x
= floor((*x
+ 0.5*width_x
) / (3*width_x
)) * 3 * width_x
+ 2 * width_x
;
316 *y
= floor((*y
- 0.25 * sqrt(3) * width_x
) / (sqrt(3)*width_x
)) * sqrt(3) * width_x
+ 0.5 * sqrt(3) * width_x
;
318 *x
= floor((*x
+ 0.5*width_x
) / (3*width_x
)) * 3 * width_x
+ 1.5 * width_x
;
319 *y
= floor((*y
- 0.25 * sqrt(3) * width_x
) / (sqrt(3)*width_x
)) * sqrt(3) * width_x
+ sqrt(3) * width_x
;
322 if ( y_mod
< 0.5 * sqrt(3) * width_x
) {
323 *x
= floor((*x
+ 0.5*width_x
) / (3*width_x
)) * 3 * width_x
;
324 *y
= floor((*y
- 0.25 * sqrt(3) * width_x
) / (sqrt(3)*width_x
)) * sqrt(3) * width_x
+ 0.5 * sqrt(3) * width_x
;
326 *x
= floor((*x
+ 0.5*width_x
) / (3*width_x
)) * 3 * width_x
+ 0.5 * width_x
;
327 *y
= floor((*y
- 0.25 * sqrt(3) * width_x
) / (sqrt(3)*width_x
)) * sqrt(3) * width_x
+ sqrt(3) * width_x
;
331 real width_x
= ddisp
->diagram
->data
->grid
.width_x
;
332 real width_y
= ddisp
->diagram
->data
->grid
.width_y
;
333 if (prefs
.grid
.dynamic
) {
334 calculate_dynamic_grid(ddisp
, &width_x
, &width_y
);
336 *x
= ROUND((*x
) / width_x
) * width_x
;
337 *y
= ROUND((*y
) / width_y
) * width_y
;