1 /****************************************************************************
2 * Copyright (C) 2008 by Matteo Franchin *
3 * *
4 * This file is part of Box. *
5 * *
6 * Box is free software: you can redistribute it and/or modify it *
7 * under the terms of the GNU Lesser General Public License as published *
8 * by the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * Box is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU Lesser General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with Box. If not, see <http://www.gnu.org/licenses/>. *
18 ****************************************************************************/
19
20 /* Interface for Line */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <math.h>
26 #include <assert.h>
27
28 #include "types.h"
29 #include <box/vm_priv.h>
30 #include "graphic.h"
31 #include "g.h"
32 #include "i_window.h"
33 #include "i_style.h"
34 #include "pointlist.h"
35 #include "i_pointlist.h"
36 #include "i_gradient.h"
37 #include "i_line.h"
38
39 #include "error.h"
40 #include "buffer.h"
41 #include "fig.h"
42 #include "autoput.h"
43
44 #include "linetracer.h"
45
46 /*#define DEBUG*/
47
line_window_init(Window * w)48 BoxTask line_window_init(Window *w) {
49 w->line.lt = lt_new();
50 if (w->line.lt == (LineTracer *) NULL) {
51 g_error("Cannot create the LineTracer object\n");
52 return BOXTASK_FAILURE;
53 }
54
55 /* We want these settings to be global:
56 * for all lines of this window
57 */
58 LineJoinStyle *ls = & w->line.this_piece.style;
59 ls->ti = ls->te = ls->ni = ls->ne = 0.0;
60
61 /* Mando le impostazioni alla libreria grafica */
62 lt_join_style_set(w->line.lt, ls);
63
64 w->line.this_piece.width1 = w->line.this_piece.width2 = 1.0;
65 w->line.this_piece.arrow = (void *) NULL;
66 w->line.this_piece.arrow_scale = 1.0;
67 return BOXTASK_OK;
68 }
69
line_color(BoxVMX * vmp)70 BoxTask line_color(BoxVMX *vmp) {
71 SUBTYPE_OF_WINDOW(vmp, w);
72 w->line.color = BOX_VM_ARG1(vmp, Color);
73 w->line.got.color = 1;
74 return BOXTASK_OK;
75 }
76
line_gradient(BoxVMX * vmp)77 BoxTask line_gradient(BoxVMX *vmp) {
78 return x_gradient(vmp);
79 }
80
line_window_destroy(Window * w)81 void line_window_destroy(Window *w) {
82 lt_destroy(w->line.lt);
83 }
84
line_begin(BoxVMX * vmp)85 BoxTask line_begin(BoxVMX *vmp) {
86 Window *w = BOX_VM_SUB_PARENT(vmp, WindowPtr);
87 IPointListPtr *ipl_ptr = BOX_VM_SUB_CHILD_PTR(vmp, IPointListPtr);
88
89 BOXTASK( ipl_create(ipl_ptr) );
90
91 w->line.state = GOT_NOTHING;
92
93 lt_clear(w->line.lt);
94 w->line.num_points = 0;
95 w->line.close = 0;
96 w->line.got.color = 0;
97 w->line.this_piece.arrow_scale = 1.0;
98
99 g_style_new(& w->line.style, & w->style);
100 return BOXTASK_OK;
101 }
102
line_end(BoxVMX * vmp)103 BoxTask line_end(BoxVMX *vmp) {
104 SUBTYPE_OF_WINDOW(vmp, w);
105 if (lt_num_pieces(w->line.lt) >= 1) {
106 if (w->line.got.color)
107 BoxGWin_Set_Fg_Color(w->window, & w->line.color);
108
109 lt_draw(w->window, w->line.lt, w->line.close);
110 (void) BoxGWin_Draw_With_Style(w->window, & w->line.style,
111 & w->line.default_style, DRAW_WHEN_END);
112 }
113
114 g_style_clear(& w->line.style);
115 return BOXTASK_OK;
116 }
117
line_real(BoxVMX * vmp)118 BoxTask line_real(BoxVMX *vmp) {
119 SUBTYPE_OF_WINDOW(vmp, w);
120 BoxReal width = 0.5*BOX_VM_ARG1(vmp, BoxReal);
121
122 switch(w->line.state) {
123 case GOT_NOTHING:
124 w->line.this_piece.width2 = w->line.this_piece.width1 = width;
125 w->line.state = GOT_2ND_FLOAT;
126 break;
127
128 case GOT_POINT:
129 w->line.this_piece.width2 = w->line.this_piece.width1 = width;
130 w->line.state = GOT_1ST_FLOAT;
131 break;
132
133 case GOT_1ST_FLOAT:
134 w->line.this_piece.width2 = width;
135 w->line.state = GOT_2ND_FLOAT;
136 break;
137
138 case GOT_2ND_FLOAT:
139 g_error("Too many width specificators.");
140 return BOXTASK_FAILURE;
141
142 default:
143 g_error("line_real: unknown line state.");
144 break;
145 }
146 return BOXTASK_OK;
147 }
148
line_point(BoxVMX * vmp)149 BoxTask line_point(BoxVMX *vmp) {
150 Window *w = BOX_VM_SUB_PARENT(vmp, WindowPtr);
151 IPointList *ipl = BOX_VM_SUB_CHILD(vmp, IPointListPtr);
152 BoxPoint *p = BOX_VM_ARG1_PTR(vmp, BoxPoint);
153 PointList *pl = IPL_POINTLIST(ipl);
154
155 w->line.state = GOT_POINT;
156 w->line.this_piece.point = *p;
157 lt_add_piece(w->line.lt, & w->line.this_piece);
158
159 ++w->line.num_points;
160 w->line.this_piece.width1 = w->line.this_piece.width2;
161 w->line.this_piece.arrow = (void *) NULL;
162 return pointlist_add(pl, p, (char *) NULL);
163 }
164
line_pause(BoxVMX * vmp)165 BoxTask line_pause(BoxVMX *vmp) {
166 SUBTYPE_OF_WINDOW(vmp, w);
167 if (w->line.got.color) {
168 BoxGWin_Set_Fg_Color(w->window, & w->line.color);
169 w->line.got.color = 0;
170 }
171 (void) lt_draw(w->window, w->line.lt, w->line.close);
172 (void) BoxGWin_Draw_With_Style(w->window, & w->line.style,
173 & w->line.default_style, DRAW_WHEN_PAUSE);
174
175 w->line.state = GOT_NOTHING;
176 w->line.num_points = 0;
177 w->line.close = 0;
178 lt_clear(w->line.lt);
179 return BOXTASK_OK;
180 }
181
line_window(BoxVMX * vmp)182 BoxTask line_window(BoxVMX *vmp) {
183 SUBTYPE_OF_WINDOW(vmp, w);
184 WindowPtr *wp = BOX_VM_ARG1_PTR(vmp, WindowPtr);
185
186 w->line.this_piece.arrow = (void *) *wp;
187 return BOXTASK_OK;
188 }
189
line_linestyle(BoxVMX * vmp)190 BoxTask line_linestyle(BoxVMX *vmp) {
191 SUBTYPE_OF_WINDOW(vmp, w);
192 BoxReal *ls = BOX_VM_ARG1_PTR(vmp, BoxReal);
193 lt_join_style_from_array(& w->line.this_piece.style,
194 ls[0], ls[1], ls[2], ls[3]);
195 return BOXTASK_OK;
196 }
197
198
line_style(BoxVMX * vmp)199 BoxTask line_style(BoxVMX *vmp) {
200 IStyle *s = BOX_VM_ARG(vmp, IStylePtr);
201 SUBTYPE_OF_WINDOW(vmp, w);
202 g_style_copy_selected(& w->line.style, & s->style, s->have);
203 return BOXTASK_OK;
204 }
205
window_line_close_begin(BoxVMX * vmp)206 BoxTask window_line_close_begin(BoxVMX *vmp) {
207 SUBTYPE2_OF_WINDOW(vmp, w);
208 w->line.close = 1;
209 return BOXTASK_OK;
210 }
211
window_line_close_int(BoxVMX * vmp)212 BoxTask window_line_close_int(BoxVMX *vmp) {
213 SUBTYPE2_OF_WINDOW(vmp, w);
214 w->line.close = BOX_VM_ARG1(vmp, BoxInt);
215 return BOXTASK_OK;
216 }
217
window_line_arrowscale(BoxVMX * vmp)218 BoxTask window_line_arrowscale(BoxVMX *vmp) {
219 SUBTYPE2_OF_WINDOW(vmp, w);
220 w->line.this_piece.arrow_scale = BOX_VM_ARG1(vmp, BoxReal);
221 return BOXTASK_OK;
222 }
223