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