Just wanted to update my post from yesterday with a small change. I found out
later that when using the cairo window within a parent fltk::Window along with
other widgets (in my case the plplot cairo window is part of a fltk::TabGroup),
the call that passes the fltk cairo context to the plplot library for
initialization ( mPLS->cmd(PLESC_DEVINIT, fltk::cr) ) will affect the layout of
the rest of the widgets in the fltk application. So to fix that the cmd call
must be wrapped in cairo_save/restore calls. This unexpectedly inverted the
plot when it was drawn, so that the chart was drawn reflected about its x axis.
To correct this behavior inside CairoWindow::draw() apply a translation and a
scaling to the cairo context before making any plplot calls. See below.
-Marco
// This example was compiled using the following commands:
//
// c++ -g3 -O0 -I/devel/UFM/fltk-2.0.x-alpha-r9204 -I/usr/include/freetype2
-I/usr/include/cairo -I/usr/include/freetype2 -I/usr/include/libpng12
-Wno-non-virtual-dtor
`PKG_CONFIG_PATH=/usr/local/depot/plplot-5.9.7/plplot-5.9.7/lib/pkgconfig
pkg-config --cflags plplotd plplotd-c++` -c -o cairo.o cairo.cxx
// c++ -g3 -O0 -Wl,-rpath
-Wl,/usr/local/depot/plplot-5.9.7/plplot-5.9.7/lib:/usr/local/depot/qt-4.7.4/qt-4.7.4/lib:/usr/local/plplot-5.9.7/lib
-o cairo cairo.o -L/devel/UFM/fltk-2.0.x-alpha-r9204/lib -lfltk2_gl -lGLU -lGL
-lfltk2 -lX11 -lXi -lXinerama -lXft -lpthread -lm -lXext -lcairo -lsupc++
`PKG_CONFIG_PATH=/usr/local/depot/plplot-5.9.7/plplot-5.9.7/lib/pkgconfig
pkg-config --libs plplotd plplotd-c++ cairo`
//
// Adjust the path to your plplot and fltk libraries as necessary. Also, fltk
was configured with -enable-cairo=yes
#include <config.h>
#include <fltk/run.h>
//#include <fltk/x.h>
#include <fltk/fltk_cairo.h>
#include <fltk/DoubleBufferWindow.h>
#include <fltk/draw.h>
#include <fltk/math.h>
#include <fltk/Group.h>
#include <fltk/TabGroup.h>
#include <iostream>
#include <plplot.h>
#include <plstream.h>
using namespace fltk;
int nsteps = 1000;
class CairoWindow : public Window
{
public:
CairoWindow(int argc, const char *argv[])
: Window(720,540), firstPass(true), ArgC(argc), ArgV(argv)
{
n = 0;
resizable(this); // comment this out for
fixed-size
color(fltk::WHITE); // desired background color
}
CairoWindow(int x, int y, int w, int h, int argc, const char *argv[])
: Window(x, y, w, h), firstPass(true), ArgC(argc), ArgV(argv)
{
n = 0;
resizable(this); // comment this out for
fixed-size
color(fltk::WHITE); // desired background color
}
bool firstPass;
int ArgC;
const char **ArgV;
void Init()
{
// Make sure the cairo context exists before attempting
// to pass the pointer to plplot.
if(fltk::cr != NULL)
{
// Perform the plplot initialization required by your
// task.
pls = new plstream();
pls->parseopts(&ArgC, ArgV, PL_PARSE_FULL);
ymin = -0.1;
ymax = 0.1;
tmin = 0.;
tmax = 110.;
tjump = 0.3;
colbox = 1;
collab = 3;
styline[0] = colline[0] = 2; // pens color and line style
styline[1] = colline[1] = 3;
styline[2] = colline[2] = 4;
styline[3] = colline[3] = 5;
legline[0] = "sum"; // pens legend
legline[1] = "sin";
legline[2] = "sin*noi";
legline[3] = "sin+noi";
xlab = 0.; ylab = 0.25; // legend position
autoy = true; // autoscale y
acc = true;
pls->sdev("extcairo");
pls->init();
// Need to save the cairo context or else the rest of
// the fltk drawing calls get out of whack...
cairo_save(cr);
pls->cmd(PLESC_DEVINIT, fltk::cr);
cairo_restore(cr);
pls->adv(0);
pls->vsta();
pls->sError(&pl_errcode, errmsg);
pls->stripc( &id1, "bcnst", "bcnstv",
tmin, tmax, tjump, ymin, ymax,
xlab, ylab,
autoy, acc,
colbox, collab,
colline, styline, legline,
"t", "", "Strip chart demo" );
if ( pl_errcode )
{
std::cout << errmsg << std::endl;
delete pls;
exit( 1 );
}
pls->sError(NULL, NULL);
autoy = false; // autoscale y
acc = true; // accumulate/
y1 = y2 = y3 = y4 = 0.0;
dt = 0.1;
// Only after successfully calling this we can flip the
// flag to false.
firstPass = false;
}
}
static void TimeOutCB(void *data)
{
CairoWindow *w = (CairoWindow *) data;
// We check if we should run the real-time data
// capture and computation, otherwise do not
// reset the timeout and "stop" the real-time.
if(w->n < nsteps)
{
// If this is the first time we called in here
// then initialize the class and the plplot interface.
if(w->firstPass == true)
{
w->Init();
}
else
{
// Otherwise, perform the real-time computation
// and request a re-draw of the screen from the
// fltk main loop.
w->Compute();
fltk::redraw();
}
fltk::repeat_timeout(0.01, w->TimeOutCB, data);
}
}
void Compute()
{
// Compute values for each time-step
t = (double) n * dt;
//noise = (1.0 * (rand() / (RAND_MAX + 1.0))) - 0.5;
noise = pls->randd() - 0.5;
y1 = y1 + noise;
y2 = sin( t * M_PI / 18. );
y3 = y2 * noise;
y4 = y2 + noise / 3.;
++n;
}
void draw()
{
// So we wait to see if this is the first time we called into here
// and if it is, then we set timeout. Now go to TimeOutCB to follow
// the sequence of events.
if(firstPass == false)
{
cairo_save(cr);
// For a reason I don't understand, adding the
// cairo_save/restore calls in Init() when passing
// the cairo context in pls->cmd(PLESC_DEVINIT, fltk::cr)
// causes the plot to draw up-side-down, so we reflect
// it back to right-side-up.
cairo_translate(cr, 0.0, h());
cairo_scale(cr, 1.0, -1.0);
if ( n % 2 )
pls->stripa( id1, 0, t, y1 );
if ( n % 3 )
pls->stripa( id1, 1, t, y2 );
if ( n % 4 )
pls->stripa( id1, 2, t, y3 );
if ( n % 5 )
pls->stripa( id1, 3, t, y4 );
cairo_restore(cr);
}
else
{
fltk::add_timeout(0.01, this->TimeOutCB, this);
}
}
static PLINT pl_errcode;
static char errmsg[160];
PLINT n;
private:
plstream *pls;
PLINT id1;
bool autoy, acc;
PLFLT y1, y2, y3, y4, ymin, ymax, xlab, ylab;
PLFLT t, tmin, tmax, tjump, dt, noise;
PLINT colbox, collab, colline[4], styline[4];
const char *legline[4];
};
PLINT CairoWindow::pl_errcode = 0;
char CairoWindow:: errmsg[160] = "";
int main(int argc, char** argv)
{
fltk::Window *w = new fltk::Window(720, 540);
w->begin();
{
fltk::TabGroup *t = new fltk::TabGroup(0, 0, w->w(), w->h());
t->begin();
{
//fltk::Group *g = new fltk::Group(0, 0, t->w(), t->h() - 24, " Plot
");
//g->box(fltk::EMBOSSED_BOX);
//g->begin();
{
const char *constArgv[argc];
for(int i = 0; i < argc; ++i)
{
constArgv[i] = "\0"; //argv[i];
}
// Create the window
//CairoWindow *plotWin = new CairoWindow(0, 0, g->w(), g->h(),
argc, constArgv);
CairoWindow *plotWin = new CairoWindow(0, 0, t->w(), t->h() - 24,
argc, constArgv);
}
//g->end();
}
t->end();
}
w->end();
w->show();
// The plplot library expects argv as const pointers
// but fltk does not, so we create a const copy to pass
// to plplot.
//const char *constArgv[argc];
//for(int i = 0; i < argc; ++i)
//{
// constArgv[i] = argv[i];
//}
//// Create the window
//CairoWindow window(argc, constArgv);
//window.show(argc,argv);
// In fltk, ONLY after calling the main loop in run() will the
// fltk cairo context be created and the surface initialized.
// Trying to operate on the fltk cairo context before calling run()
// will result in the use of a null pointer. From here go to draw() call
// in CairoWindow() for more comments on these steps.
return fltk::run();
}
------------------------------------------------------------------------------
Virtualization & Cloud Management Using Capacity Planning
Cloud computing makes use of virtualization - but cloud computing
also focuses on allowing computing to be delivered as a service.
http://www.accelacomm.com/jaw/sfnl/114/51521223/
_______________________________________________
Plplot-devel mailing list
Plplot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-devel