Initial release of Maemo 5 port of gnuplot
[gnuplot] / src / beos / GPBitmap.cpp
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "GPBitmap.h"
7 #include "GPView.h"
8 #include "constants.h"
9 #include <Region.h>
10 #include <ScrollBar.h>
11
12 #define LineSolid 1
13
14
15 /*******************************************************************/
16 // GPBitmap
17 GPBitmap::GPBitmap(float width, float height)
18 {
19         m_bitmap = new BBitmap(BRect(0,0,width-1,height-1),B_RGB_32_BIT,TRUE);
20         BRect r(0,0,width-1,height-1);
21         m_view = new BView(r,"BitmapDrawer",B_FOLLOW_ALL,0);
22         m_bitmap->AddChild(m_view);
23         max_commands    = 7;
24         ncommands               = 0;
25         m_needRedraw    = false;
26         m_redrawing     = false;
27         commands                = (char **) malloc(max_commands * sizeof(char *));
28         this->width             = nwidth = width;
29         this->height    = nheight = height;
30
31         for(int i=1 ; i<16 ; i++) {
32                 colors[i].red   = i*16;
33                 colors[i].green = i*16;
34                 colors[i].blue  = i*16;
35                 colors[i].alpha = 255;
36         }
37 };
38
39 GPBitmap::GPBitmap(float width, float height, char **cmds)
40 {
41
42 }
43
44 GPBitmap::~GPBitmap()
45 {
46         if (m_bitmap)
47                 delete m_bitmap;
48         if(m_view)
49                 delete m_view;
50         if(ncommands)
51                 clearCommands();
52         if(commands) {
53                 free(commands);
54                 commands = NULL;
55         }
56 }
57
58 void GPBitmap::SetDirty(BRegion *r)
59 {
60         BMessage msg(bmsgBitmapDirty);
61         m_needRedraw = true;
62 }
63
64 void GPBitmap::clearCommands()
65 {
66         int32 ncmds = atomic_add(&ncommands,-ncommands);
67         if(ncmds > 0) {
68                 for( --ncmds ; ncmds >= 0 ; ncmds--) {
69                         if(commands[ncmds])
70                                 free(commands[ncmds]);
71                         commands[ncmds] = NULL;
72                 }
73         }
74 }
75
76 #if 1
77 void GPBitmap::addCommands(BMessage *msg, int32 numCmds)
78 {
79         char *p, **cmd = NULL;
80
81         if (numCmds+ncommands >= max_commands) {
82                 max_commands = max_commands + numCmds + 2;
83                 commands = (commands)
84                         ? (char **) realloc(commands, max_commands * sizeof(char *))
85                         : (char **) malloc(sizeof(char *));
86         }
87         if (!commands) {
88                 fputs("gnuplot: can't get memory. aborted.\n", stderr);
89 //              exit(1);
90         } else {
91                 msg->FindPointer("cmds", (void **)&cmd);
92 //              printf("got : %X at %X\n",cmd[0], cmd);
93                 for(int i=0; i< numCmds; i++) {
94 //                      cmd = msg->FindString("cmd", i);
95 //                      p = (char *) malloc((unsigned) strlen(cmd[i]) + 1);
96 //                      if (!p) {
97 //                              fputs("gnuplot: can't get memory. aborted.\n", stderr);
98 //                              exit(1);
99 //                      } else
100 //                              commands[ncommands++] = strcpy(p, cmd[i]);
101                         commands[ncommands++] = strdup(cmd[i]);
102 //                      commands[ncommands++] = cmd[i];
103                         m_needRedraw = true;
104                 }
105         }
106 }
107 #else
108 void GPBitmap::addCommands(BMessage *msg, int32 numCmds)
109 {
110         char *cmd = NULL;
111
112         if (numCmds+ncommands >= max_commands) {
113                 max_commands = max_commands + numCmds + 2;
114                 commands = (commands)
115                         ? (char **) realloc(commands, max_commands * sizeof(char *))
116                         : (char **) malloc(sizeof(char *));
117         }
118         if (!commands) {
119                 fputs("gnuplot: can't get memory. aborted.\n", stderr);
120 //              exit(1);
121         } else {
122                 for(int i=0; i< numCmds; i++) {
123                         cmd = msg->FindString("cmd", i);
124                         commands[ncommands++] = strdup(cmd);
125                         m_needRedraw = true;
126                 }
127         }
128 }
129 #endif
130
131 void GPBitmap::addCommand(char *cmd)
132 {
133 //      printf("adding a cmd : %s\n",cmd);
134         if(!cmd)
135                 return;
136         if (ncommands >= max_commands) {
137                 max_commands = max_commands * 2 + 1;
138                 commands = (commands)
139                         ? (char **) realloc(commands, max_commands * sizeof(char *))
140                         : (char **) malloc(sizeof(char *));
141         }
142         if (!commands) {
143                 fputs("gnuplot: can't get memory. X11 aborted.\n", stderr);
144                 return; // exit(1);
145         } else {
146                 commands[ncommands++] = strdup(cmd);
147                 m_needRedraw = true;
148         }
149 }
150
151 void GPBitmap::ResizeTo(float width, float height, uint32 btns)
152 {
153         if(btns) {
154                 nwidth  = width;
155                 nheight = height;
156 //              m_needRedraw = true;
157                 return;
158         }
159         BRect r(0,0,width-1,height-1);
160         if (m_bitmap)
161                 m_bitmap->Lock();
162         if(m_view) {
163                 m_bitmap->RemoveChild(m_view);
164                 m_view->ResizeTo(nwidth, nheight);
165         } else
166                 m_view = new BView(r,"BitmapDrawer",B_FOLLOW_ALL,0);
167
168 //    drawing_thread = spawn_thread(&drawing_loop, "gnuplot io_loop", B_LOW_PRIORITY, this); 
169 //    resume_thread(drawing_thread);
170 //      kill_thread(drawing_thread);
171
172         if (m_bitmap) {
173                 m_bitmap->Unlock();
174                 delete m_bitmap;
175         }
176
177         m_bitmap = new BBitmap(r,B_RGB_32_BIT,TRUE);
178         m_bitmap->Lock();
179         m_bitmap->AddChild(m_view);
180         this->width = nwidth = width;
181         this->height = nheight = height;
182         m_needRedraw = true;
183 }
184
185 int32 GPBitmap::drawing_loop(void* data)
186 {
187         int32 res = 1;
188         GPBitmap * bmp = (GPBitmap *)data;
189
190         return res;
191 }
192
193 /*-----------------------------------------------------------------------------
194  *   display - display a stored plot
195  *---------------------------------------------------------------------------*/
196
197 void GPBitmap::display(float v_width, float v_height)
198 {
199         int n, x, y, jmode, sl, lt = 0, type, point, px, py;
200         int uwidth, user_width = 1;             /* as specified by plot...linewidth */
201         char *buffer, *str;
202         float sw, vchar;
203
204         uint32 buttons;
205         BPoint cursor;
206         m_view->GetMouse(&cursor, &buttons);
207
208         if(buttons == 0) {
209                 if ((width != v_width ) || (height != v_height))
210                         ResizeTo(v_width, v_height, 0);
211         }
212
213         if (ncommands == 0 || m_needRedraw == false)
214                 return;
215
216         vchar = 11.0;
217         m_view->SetFontSize(vchar);
218
219         /* set scaling factor between internal driver & window geometry */
220         xscale = width / 4096.0;
221         yscale = height / 4096.0;
222
223         /* initial point sizes, until overridden with P7xxxxyyyy */
224         px = (int) (xscale * pointsize);
225         py = (int) (yscale * pointsize);
226
227         /* set pixmap background */
228         m_view->SetHighColor(255,255,255);
229         m_view->FillRect(BRect(0,0,width,height));
230         m_view->SetViewColor(colors[2]);
231
232         /* loop over accumulated commands from inboard driver */
233         for (n = 0; n < ncommands; n++) {
234                 buffer = commands[n];
235
236                 /*   X11_vector(x,y) - draw vector  */
237                 if (*buffer == 'V') {
238                         sscanf(buffer, "V%4d%4d", &x, &y);
239                         m_view->StrokeLine( BPoint(X(cx), Y(cy)),BPoint(X(x), Y(y)));
240                         cx = x;
241                         cy = y;
242                 }
243                 /*   X11_move(x,y) - move  */
244                 else if (*buffer == 'M') {
245                         sscanf(buffer, "M%4d%4d", &cx, &cy);
246                         m_view->MovePenTo(BPoint(X(cx), Y(cy)));
247                 }
248                 /*   X11_put_text(x,y,str) - draw text   */
249                 else if (*buffer == 'T') {
250
251                         sscanf(buffer, "T%4d%4d", &x, &y);
252                         str = buffer + 9;
253                         sl = strlen(str) - 1;
254                         sw = m_view->StringWidth(str, sl);
255
256                         switch (jmode) {
257                                 case CENTRE:                            sw = -sw / 2;   break;
258                                 case RIGHT:                                     sw = -sw;               break;
259                                 case LEFT:                                      sw = 0;                 break;
260                         }
261
262                         m_view->SetHighColor(colors[2]);
263                         m_view->DrawString(str, sl, BPoint(X(x) + sw, Y(y) + vchar / 3 ));
264                         m_view->SetHighColor(colors[lt + 3]);
265                 }
266                 else if (*buffer == 'F') {      /* fill box */
267                         int style, xtmp, ytmp, w, h;
268
269                         if (sscanf(buffer + 1, "%4d%4d%4d%4d%4d", &style, &xtmp, &ytmp, &w, &h) == 5) {
270                                 /* gnuplot has origin at bottom left, but X uses top left
271                                  * There may be an off-by-one (or more) error here.
272                                  * style ignored here for the moment
273                                  */
274                                 /* ULIG: the style parameter is now used for the fillboxes style
275                                  * (not implemented here), see the documentation */
276                                 m_view->SetHighColor(colors[0]);
277                                 m_view->FillRect(BRect(X(xtmp), Y(ytmp + h), w * xscale, h * yscale));
278                                 m_view->SetHighColor(colors[lt + 3]);
279                         }
280                 }
281                 /*   X11_justify_text(mode) - set text justification mode  */
282                 else if (*buffer == 'J')
283                         sscanf(buffer, "J%4d", (int *) &jmode);
284
285                 /*  X11_linewidth(width) - set line width */
286                 else if (*buffer == 'W')
287                         sscanf(buffer + 1, "%4d", &user_width);
288
289                 /*   X11_linetype(type) - set line type  */
290                 else if (*buffer == 'L') {
291                         sscanf(buffer, "L%4d", &lt);
292                         lt = (lt % 8) + 2;
293                         /* default width is 0 {which X treats as 1} */
294                         uwidth = user_width; // widths[lt] ? user_width * widths[lt] : user_width;
295 //                      if (dashes[lt][0]) {
296 //                              type = LineOnOffDash;
297 //                              XSetDashes(dpy, gc, 0, dashes[lt], strlen(dashes[lt]));
298 //                      } else {
299                                 type = LineSolid;
300 //                      }
301                         m_view->SetHighColor(colors[lt + 3]);
302                         m_view->SetPenSize(uwidth);
303                         m_view->SetLineMode(B_ROUND_CAP,B_BEVEL_JOIN);
304 //                      XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
305                 }
306                 /*   X11_point(number) - draw a point */
307                 else if (*buffer == 'P') {
308                         /* linux sscanf does not like %1d%4d%4d" with Oxxxxyyyy */
309                         /* sscanf(buffer, "P%1d%4d%4d", &point, &x, &y); */
310                         point = buffer[1] - '0';
311                         sscanf(buffer + 2, "%4d%4d", &x, &y);
312                         if (point == 7) {
313                                 /* set point size */
314                                 px = (int) (x * xscale * pointsize);
315                                 py = (int) (y * yscale * pointsize);
316                         } else {
317                                 if (type != LineSolid || uwidth != 0) { /* select solid line */
318                                         m_view->SetPenSize(1.0);
319                                         m_view->SetLineMode(B_ROUND_CAP,B_BEVEL_JOIN);
320 //                                      XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinBevel);
321                                 }
322                                 switch (point) {
323                                         case 0: /* dot */                       doDot(x,y);                             break;
324                                         case 1: /* do diamond */        doDiamond(x,y,px,py);   break;
325                                         case 2: /* do plus */           doPlus(x,y,px,py);              break;
326                                         case 3: /* do box */            doBox(x,y,px,py);               break;
327                                         case 4: /* do X */                      doCross(x,y,px,py);             break;
328                                         case 5: /* do triangle */       doTriangle(x,y,px,py);  break;
329                                         case 6: /* do star */           doStar(x,y,px,py);              break;
330                                 }
331                                 if (type != LineSolid || uwidth != 0) { /* select solid line */
332                                         m_view->SetPenSize(uwidth);
333 //                                      canview->SetLineMode(B_ROUND_CAP,B_ROUND_JOIN);
334 //                                  XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
335                                 }
336                         }
337                 } /* end  X11_point(number) - draw a point */
338         } /* end loop over accumulated commands from inboard driver */ 
339         m_view->Sync();
340         m_needRedraw = false;
341 }
342
343 void GPBitmap::doDiamond(int x, int y, int px, int py) {
344         m_view->StrokeLine(BPoint(X(x) - px, Y(y)),BPoint(X(x), Y(y) - py));
345         m_view->StrokeLine(BPoint(X(x) + px, Y(y)));
346         m_view->StrokeLine(BPoint(X(x), Y(y) + py));
347         m_view->StrokeLine(BPoint(X(x) - px, Y(y)));
348         m_view->StrokeLine(BPoint(X(x), Y(y)),BPoint(X(x), Y(y)));
349 }
350
351 void GPBitmap::doPlus(int x, int y, int px, int py) {
352         m_view->StrokeLine(BPoint(X(x) - px, Y(y)),BPoint(X(x) + px, Y(y)));
353         m_view->StrokeLine(BPoint(X(x), Y(y) - py),BPoint(X(x), Y(y) + py));
354 }
355
356 void GPBitmap::doBox(int x, int y, int px, int py) {
357         m_view->StrokeRect(BRect(X(x) - px, Y(y) - py, (px + px), (py + py)));
358         m_view->StrokeLine(BPoint(X(x), Y(y)),BPoint(X(x), Y(y)));
359 }
360
361 void GPBitmap::doCross(int x, int y, int px, int py) {
362         m_view->StrokeLine(BPoint(X(x) - px, Y(y) - py),BPoint(X(x) + px, Y(y) + py));
363         m_view->StrokeLine(BPoint(X(x) - px, Y(y) + py),BPoint(X(x) + px, Y(y) - py));
364 }
365
366 void GPBitmap::doTriangle(int x, int y, int px, int py) {
367         short temp_x, temp_y;
368
369         temp_x = (short) (1.33 * (double) px + 0.5);
370         temp_y = (short) (1.33 * (double) py + 0.5);
371
372         m_view->StrokeLine(BPoint(X(x), Y(y) - temp_y), BPoint(X(x) + temp_x, Y(y) - temp_y + 2 * py));
373         m_view->StrokeLine(BPoint(X(x) - temp_x, Y(y) - temp_y + 2 * py));
374         m_view->StrokeLine(BPoint(X(x), Y(y) - temp_y));
375         m_view->StrokeLine(BPoint(X(x), Y(y)),BPoint(X(x), Y(y)));
376 }
377
378 void GPBitmap::doStar(int x, int y, int px, int py) {
379         m_view->StrokeLine(BPoint(X(x)-px, Y(y)), BPoint(X(x) + px, Y(y)));
380         m_view->StrokeLine(BPoint(X(x), Y(y)-py), BPoint(X(x), Y(y)+py));
381         m_view->StrokeLine(BPoint(X(x)-px, Y(y)-py), BPoint(X(x)+px, Y(y)+py));
382         m_view->StrokeLine(BPoint(X(x)-px, Y(y)+py), BPoint(X(x)+px, Y(y)-py));
383 }
384
385 void GPBitmap::doDot(int x, int y) {
386         m_view->StrokeLine(BPoint(X(x), Y(y)),BPoint(X(x), Y(y)));
387 }
388