If the intent is to do "incremental" drawing then using an Fl_Offscreen is the 
best way to go (IMHO of course...)

This (below) is the example I usually post at this point when this topic comes 
up... 
Note that this does not actually use threads but simply uses a timer to 
simulate the background thread - converting to really use threads should be 
trivial.

Hope this code helps - it is perhaps longer and more verbose that would be 
ideal for true clarity!

---------- 

/*****************************************************************************/
//   fltk-config --compile offscreen-demo.cxx

/* Standard headers */
#include <stdlib.h>
#include <time.h> // use time() in random code below

/* Fltk headers */
#include <Fl/Fl.h>
#include <FL/Fl_Double_Window.H>
#include <FL/x.H>
#include <Fl/Fl_Box.H>
#include <Fl/fl_draw.h>

// The main window for the demo
static Fl_Double_Window *main_window = 0;

// The offscreen surface
static Fl_Offscreen oscr = 0;  // the surface
static int os_w = 0, os_h = 0; // the surface's dimensions

/*****************************************************************************/
/* This class provides a view into the offscreen surface */
class oscr_box : public Fl_Box {
        void draw();
        int handle(int event);
protected:
        int x_old, y_old;   /* previous x,y during a drag operation */
        int drag_state;     /* non-zero if a drag is in progress */
        int page_x, page_y; /* current view position */
public:
        oscr_box(int x, int y, int w, int h);
};

/*****************************************************************************/
/* Constructor */
oscr_box::oscr_box(int x, int y, int w, int h) : Fl_Box(x,y,w,h){
        x_old = y_old = 0;
        drag_state = 0;
        page_x = page_y = 750;
} // Constructor

/*****************************************************************************/
void oscr_box::draw() {
        int wd = w();
        int ht = h();
        int xo = x();
        int yo = y();

        // first clear out the view to a flat grey - this is
        // redundant if we know the offscreen will fill the view
        fl_color(fl_gray_ramp(19));
        fl_rectf(xo, yo, wd, ht);

        // now draw the view
        if(oscr) { // offscreen exists
                // blit the required view from the offscreen onto the box
                fl_copy_offscreen(xo, yo, wd, ht, oscr, page_x, page_y);
        }
        else { // create the offscreen
                // some platforms seem to need a context to base the offscreen
                // on, so make the main window current here...
                main_window->make_current();

                // set the dimensions for the offscreen surface
                os_w = 2000; os_h = 2000;
                oscr = fl_create_offscreen(os_w, os_h);
                // did the create fail?
                if(!oscr) {
                        // Fail - clear the dimensions out again
                        os_w = os_h = 0;
                }
        }
} // draw method

/*****************************************************************************/
int oscr_box::handle(int ev) {
        // call the base class event handler
        int ret = Fl_Box::handle(ev);

        // if there is no offscreen surface, we can return now
        if(!oscr) return ret;

        // Handle dragging of visible area - if a valid context exists.
        // All sorts of editor stuff could be added here... later...
        switch(ev) {
        case FL_ENTER:
                main_window->cursor(FL_CURSOR_MOVE);
                ret = 1;
                break;

        case FL_LEAVE:
                main_window->cursor(FL_CURSOR_DEFAULT);
                ret = 1;
                break;

        case FL_PUSH:
                x_old = Fl::event_x_root();
                y_old = Fl::event_y_root();
                drag_state = 1; // drag
                ret = 1;
                break;

        case FL_DRAG:
                if(drag_state == 1) { // dragging is active
                        // how far did we drag since last event?
                        int x_new = Fl::event_x_root();
                        int y_new = Fl::event_y_root();
                        int xoff = x_old - x_new;
                        int yoff = y_old - y_new;
                        x_old = x_new;
                        y_old = y_new;
                        // update the view position by the drag amount
                        page_x += xoff;
                        page_y += yoff;
                        // check the page bounds and clamp at edges
                        if(page_x < -w()) page_x = -w();
                        else if(page_x > os_w) page_x = os_w;

                        if(page_y < -h()) page_y = -h();
                        else if(page_y > os_h) page_y = os_h;
                        // trigger a redraw of the view because we moved
                        redraw();
                }
                ret = 1;
                break;

        case FL_RELEASE:
                drag_state = 0; // not dragging any more
                ret = 1;
                break;

        default:
                break;
        }
        return ret;
} // handle

/*****************************************************************************/
static oscr_box *os_box = 0; // a widget to view the offscreen with

/*****************************************************************************/
static void oscr_drawing (void) {
        Fl_Color col;
        static int icol = 56; // a random colour on the ramp
        static int ox = 1000, oy = 1000; // somewhere in the offscreen area
        static int iters = 3456; // more than 1024...

        if(!oscr) return; // nothing to do here...

        fl_begin_offscreen(oscr); /* Open the offscreen context for drawing */

        // for the demo, we "reset" the offscreen periodically
        if(iters > 1024) {
                fl_color(FL_WHITE);
                fl_rectf(0, 0, os_w, os_h);
                iters = 0;
        }
        iters++;

        // pick a random colour to draw with
        icol++; if(icol > 255) icol = 56;
        col = (Fl_Color)icol;
        fl_color(col); // set the colour

        // pick a random position
        int rnd = rand();
        double drx = (double)os_w * (double)rnd / (double)RAND_MAX;
        rnd = rand();
        double dry = (double)os_h * (double)rnd / (double)RAND_MAX;

        // pick a random line thickness
        rnd = rand();
        double drt = 4.0 * (double)rnd / (double)RAND_MAX;

        // draw a line from the old point to the new end point
        int ex = (int)drx;
        int ey = (int)dry;
        // draws a solid line of thickness drt
        fl_line_style(FL_SOLID, (int)drt);
        fl_line(ox, oy, ex, ey);
        // old point moved to new end point
        ox = ex; oy = ey;

        fl_end_offscreen(); // close the offscreen context
} // oscr_drawing

/*****************************************************************************/
static void oscr_anim(void *) {
        if(oscr) { // offscreen exists, draw something
                oscr_drawing();
        }
        // request a redraw of the view box
        os_box->redraw();
        // repeat the animation delay
        Fl::repeat_timeout(0.1, oscr_anim);
} // oscr_anim

/*****************************************************************************/
int main (int argc, char **argv) {
        int win_size = 600;

        // create the main window
        main_window = new Fl_Double_Window(win_size, win_size, "Offscreen 
Demo");
        main_window->begin();

        // a view of the offscreen, inside the main window
        os_box = new oscr_box(5, 5, (win_size - 10), (win_size - 10));

        main_window->end();
        main_window->resizable(os_box);

        // show the app
        main_window->show(argc, argv);

        // seed the random number sequence
        srand(time(NULL));

        // add a timer to animate the view updates
        Fl::add_timeout(0.1, oscr_anim);

        // start the fltk loop
        return Fl::run();
} // main

/* end of file */



SELEX Galileo Ltd
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14 
3EL
A company registered in England & Wales.  Company no. 02426132
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************

_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to