#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GPBitmap.h"
#include "GPView.h"
#include "constants.h"
#include <Region.h>
#include <ScrollBar.h>
#define LineSolid 1
/*******************************************************************/
// GPBitmap
GPBitmap::GPBitmap(float width, float height)
{
m_bitmap = new BBitmap(BRect(0,0,width-1,height-1),B_RGB_32_BIT,TRUE);
BRect r(0,0,width-1,height-1);
m_view = new BView(r,"BitmapDrawer",B_FOLLOW_ALL,0);
m_bitmap->AddChild(m_view);
max_commands = 7;
ncommands = 0;
m_needRedraw = false;
m_redrawing = false;
commands = (char **) malloc(max_commands * sizeof(char *));
this->width = nwidth = width;
this->height = nheight = height;
for(int i=1 ; i<16 ; i++) {
colors[i].red = i*16;
colors[i].green = i*16;
colors[i].blue = i*16;
colors[i].alpha = 255;
}
};
GPBitmap::GPBitmap(float width, float height, char **cmds)
{
}
GPBitmap::~GPBitmap()
{
if (m_bitmap)
delete m_bitmap;
if(m_view)
delete m_view;
if(ncommands)
clearCommands();
if(commands) {
free(commands);
commands = NULL;
}
}
void GPBitmap::SetDirty(BRegion *r)
{
BMessage msg(bmsgBitmapDirty);
m_needRedraw = true;
}
void GPBitmap::clearCommands()
{
int32 ncmds = atomic_add(&ncommands,-ncommands);
if(ncmds > 0) {
for( --ncmds ; ncmds >= 0 ; ncmds--) {
if(commands[ncmds])
free(commands[ncmds]);
commands[ncmds] = NULL;
}
}
}
#if 1
void GPBitmap::addCommands(BMessage *msg, int32 numCmds)
{
char *p, **cmd = NULL;
if (numCmds+ncommands >= max_commands) {
max_commands = max_commands + numCmds + 2;
commands = (commands)
? (char **) realloc(commands, max_commands * sizeof(char *))
: (char **) malloc(sizeof(char *));
}
if (!commands) {
fputs("gnuplot: can't get memory. aborted.\n", stderr);
// exit(1);
} else {
msg->FindPointer("cmds", (void **)&cmd);
// printf("got : %X at %X\n",cmd[0], cmd);
for(int i=0; i< numCmds; i++) {
// cmd = msg->FindString("cmd", i);
// p = (char *) malloc((unsigned) strlen(cmd[i]) + 1);
// if (!p) {
// fputs("gnuplot: can't get memory. aborted.\n", stderr);
// exit(1);
// } else
// commands[ncommands++] = strcpy(p, cmd[i]);
commands[ncommands++] = strdup(cmd[i]);
// commands[ncommands++] = cmd[i];
m_needRedraw = true;
}
}
}
#else
void GPBitmap::addCommands(BMessage *msg, int32 numCmds)
{
char *cmd = NULL;
if (numCmds+ncommands >= max_commands) {
max_commands = max_commands + numCmds + 2;
commands = (commands)
? (char **) realloc(commands, max_commands * sizeof(char *))
: (char **) malloc(sizeof(char *));
}
if (!commands) {
fputs("gnuplot: can't get memory. aborted.\n", stderr);
// exit(1);
} else {
for(int i=0; i< numCmds; i++) {
cmd = msg->FindString("cmd", i);
commands[ncommands++] = strdup(cmd);
m_needRedraw = true;
}
}
}
#endif
void GPBitmap::addCommand(char *cmd)
{
// printf("adding a cmd : %s\n",cmd);
if(!cmd)
return;
if (ncommands >= max_commands) {
max_commands = max_commands * 2 + 1;
commands = (commands)
? (char **) realloc(commands, max_commands * sizeof(char *))
: (char **) malloc(sizeof(char *));
}
if (!commands) {
fputs("gnuplot: can't get memory. X11 aborted.\n", stderr);
return; // exit(1);
} else {
commands[ncommands++] = strdup(cmd);
m_needRedraw = true;
}
}
void GPBitmap::ResizeTo(float width, float height, uint32 btns)
{
if(btns) {
nwidth = width;
nheight = height;
// m_needRedraw = true;
return;
}
BRect r(0,0,width-1,height-1);
if (m_bitmap)
m_bitmap->Lock();
if(m_view) {
m_bitmap->RemoveChild(m_view);
m_view->ResizeTo(nwidth, nheight);
} else
m_view = new BView(r,"BitmapDrawer",B_FOLLOW_ALL,0);
// drawing_thread = spawn_thread(&drawing_loop, "gnuplot io_loop", B_LOW_PRIORITY, this);
// resume_thread(drawing_thread);
// kill_thread(drawing_thread);
if (m_bitmap) {
m_bitmap->Unlock();
delete m_bitmap;
}
m_bitmap = new BBitmap(r,B_RGB_32_BIT,TRUE);
m_bitmap->Lock();
m_bitmap->AddChild(m_view);
this->width = nwidth = width;
this->height = nheight = height;
m_needRedraw = true;
}
int32 GPBitmap::drawing_loop(void* data)
{
int32 res = 1;
GPBitmap * bmp = (GPBitmap *)data;
return res;
}
/*-----------------------------------------------------------------------------
* display - display a stored plot
*---------------------------------------------------------------------------*/
void GPBitmap::display(float v_width, float v_height)
{
int n, x, y, jmode, sl, lt = 0, type, point, px, py;
int uwidth, user_width = 1; /* as specified by plot...linewidth */
char *buffer, *str;
float sw, vchar;
uint32 buttons;
BPoint cursor;
m_view->GetMouse(&cursor, &buttons);
if(buttons == 0) {
if ((width != v_width ) || (height != v_height))
ResizeTo(v_width, v_height, 0);
}
if (ncommands == 0 || m_needRedraw == false)
return;
vchar = 11.0;
m_view->SetFontSize(vchar);
/* set scaling factor between internal driver & window geometry */
xscale = width / 4096.0;
yscale = height / 4096.0;
/* initial point sizes, until overridden with P7xxxxyyyy */
px = (int) (xscale * pointsize);
py = (int) (yscale * pointsize);
/* set pixmap background */
m_view->SetHighColor(255,255,255);
m_view->FillRect(BRect(0,0,width,height));
m_view->SetViewColor(colors[2]);
/* loop over accumulated commands from inboard driver */
for (n = 0; n < ncommands; n++) {
buffer = commands[n];
/* X11_vector(x,y) - draw vector */
if (*buffer == 'V') {
sscanf(buffer, "V%4d%4d", &x, &y);
m_view->StrokeLine( BPoint(X(cx), Y(cy)),BPoint(X(x), Y(y)));
cx = x;
cy = y;
}
/* X11_move(x,y) - move */
else if (*buffer == 'M') {
sscanf(buffer, "M%4d%4d", &cx, &cy);
m_view->MovePenTo(BPoint(X(cx), Y(cy)));
}
/* X11_put_text(x,y,str) - draw text */
else if (*buffer == 'T') {
sscanf(buffer, "T%4d%4d", &x, &y);
str = buffer + 9;
sl = strlen(str) - 1;
sw = m_view->StringWidth(str, sl);
switch (jmode) {
case CENTRE: sw = -sw / 2; break;
case RIGHT: sw = -sw; break;
case LEFT: sw = 0; break;
}
m_view->SetHighColor(colors[2]);
m_view->DrawString(str, sl, BPoint(X(x) + sw, Y(y) + vchar / 3 ));
m_view->SetHighColor(colors[lt + 3]);
}
else if (*buffer == 'F') { /* fill box */
int style, xtmp, ytmp, w, h;
if (sscanf(buffer + 1, "%4d%4d%4d%4d%4d", &style, &xtmp, &ytmp, &w, &h) == 5) {
/* gnuplot has origin at bottom left, but X uses top left
* There may be an off-by-one (or more) error here.
* style ignored here for the moment
*/
/* ULIG: the style parameter is now used for the fillboxes style
* (not implemented here), see the documentation */
m_view->SetHighColor(colors[0]);
m_view->FillRect(BRect(X(xtmp), Y(ytmp + h), w * xscale, h * yscale));
m_view->SetHighColor(colors[lt + 3]);
}
}
/* X11_justify_text(mode) - set text justification mode */
else if (*buffer == 'J')
sscanf(buffer, "J%4d", (int *) &jmode);
/* X11_linewidth(width) - set line width */
else if (*buffer == 'W')
sscanf(buffer + 1, "%4d", &user_width);
/* X11_linetype(type) - set line type */
else if (*buffer == 'L') {
sscanf(buffer, "L%4d", <);
lt = (lt % 8) + 2;
/* default width is 0 {which X treats as 1} */
uwidth = user_width; // widths[lt] ? user_width * widths[lt] : user_width;
// if (dashes[lt][0]) {
// type = LineOnOffDash;
// XSetDashes(dpy, gc, 0, dashes[lt], strlen(dashes[lt]));
// } else {
type = LineSolid;
// }
m_view->SetHighColor(colors[lt + 3]);
m_view->SetPenSize(uwidth);
m_view->SetLineMode(B_ROUND_CAP,B_BEVEL_JOIN);
// XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
}
/* X11_point(number) - draw a point */
else if (*buffer == 'P') {
/* linux sscanf does not like %1d%4d%4d" with Oxxxxyyyy */
/* sscanf(buffer, "P%1d%4d%4d", &point, &x, &y); */
point = buffer[1] - '0';
sscanf(buffer + 2, "%4d%4d", &x, &y);
if (point == 7) {
/* set point size */
px = (int) (x * xscale * pointsize);
py = (int) (y * yscale * pointsize);
} else {
if (type != LineSolid || uwidth != 0) { /* select solid line */
m_view->SetPenSize(1.0);
m_view->SetLineMode(B_ROUND_CAP,B_BEVEL_JOIN);
// XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinBevel);
}
switch (point) {
case 0: /* dot */ doDot(x,y); break;
case 1: /* do diamond */ doDiamond(x,y,px,py); break;
case 2: /* do plus */ doPlus(x,y,px,py); break;
case 3: /* do box */ doBox(x,y,px,py); break;
case 4: /* do X */ doCross(x,y,px,py); break;
case 5: /* do triangle */ doTriangle(x,y,px,py); break;
case 6: /* do star */ doStar(x,y,px,py); break;
}
if (type != LineSolid || uwidth != 0) { /* select solid line */
m_view->SetPenSize(uwidth);
// canview->SetLineMode(B_ROUND_CAP,B_ROUND_JOIN);
// XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
}
}
} /* end X11_point(number) - draw a point */
} /* end loop over accumulated commands from inboard driver */
m_view->Sync();
m_needRedraw = false;
}
void GPBitmap::doDiamond(int x, int y, int px, int py) {
m_view->StrokeLine(BPoint(X(x) - px, Y(y)),BPoint(X(x), Y(y) - py));
m_view->StrokeLine(BPoint(X(x) + px, Y(y)));
m_view->StrokeLine(BPoint(X(x), Y(y) + py));
m_view->StrokeLine(BPoint(X(x) - px, Y(y)));
m_view->StrokeLine(BPoint(X(x), Y(y)),BPoint(X(x), Y(y)));
}
void GPBitmap::doPlus(int x, int y, int px, int py) {
m_view->StrokeLine(BPoint(X(x) - px, Y(y)),BPoint(X(x) + px, Y(y)));
m_view->StrokeLine(BPoint(X(x), Y(y) - py),BPoint(X(x), Y(y) + py));
}
void GPBitmap::doBox(int x, int y, int px, int py) {
m_view->StrokeRect(BRect(X(x) - px, Y(y) - py, (px + px), (py + py)));
m_view->StrokeLine(BPoint(X(x), Y(y)),BPoint(X(x), Y(y)));
}
void GPBitmap::doCross(int x, int y, int px, int py) {
m_view->StrokeLine(BPoint(X(x) - px, Y(y) - py),BPoint(X(x) + px, Y(y) + py));
m_view->StrokeLine(BPoint(X(x) - px, Y(y) + py),BPoint(X(x) + px, Y(y) - py));
}
void GPBitmap::doTriangle(int x, int y, int px, int py) {
short temp_x, temp_y;
temp_x = (short) (1.33 * (double) px + 0.5);
temp_y = (short) (1.33 * (double) py + 0.5);
m_view->StrokeLine(BPoint(X(x), Y(y) - temp_y), BPoint(X(x) + temp_x, Y(y) - temp_y + 2 * py));
m_view->StrokeLine(BPoint(X(x) - temp_x, Y(y) - temp_y + 2 * py));
m_view->StrokeLine(BPoint(X(x), Y(y) - temp_y));
m_view->StrokeLine(BPoint(X(x), Y(y)),BPoint(X(x), Y(y)));
}
void GPBitmap::doStar(int x, int y, int px, int py) {
m_view->StrokeLine(BPoint(X(x)-px, Y(y)), BPoint(X(x) + px, Y(y)));
m_view->StrokeLine(BPoint(X(x), Y(y)-py), BPoint(X(x), Y(y)+py));
m_view->StrokeLine(BPoint(X(x)-px, Y(y)-py), BPoint(X(x)+px, Y(y)+py));
m_view->StrokeLine(BPoint(X(x)-px, Y(y)+py), BPoint(X(x)+px, Y(y)-py));
}
void GPBitmap::doDot(int x, int y) {
m_view->StrokeLine(BPoint(X(x), Y(y)),BPoint(X(x), Y(y)));
}