FLTK logo

Re: Drawing rectangles etc - demo of incremental offscreen drawing

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.general  ]
 
Previous Message ]New Message | Reply ]Next Message ]

Re: Drawing rectangles etc - demo of incremental offscreen drawing "MacArthur, Ian (SELEX GALILEO, UK)" Jun 08, 2011  
 
> The individual 'incremental method you mentioned would be of 
> interest to me for insight also, if you would like to post it, thanks.

OK, see below.
Sorry to everyone who's seen this before, I am sure I have posted it but
could not find it in the forums...

It incrementally renders random coloured lines to an offscreen surface
and then displays a view of that in a window.
The rendered "canvas" can be dragged around the view window, and the
view is resizable.

Enjoy...

-----------------
/***********************************************************************
******/
//   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.
********************************************************************
Direct Link to Message ]
 
     
Previous Message ]New Message | Reply ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.