Albrecht Schlosser wrote:

To the x/y translations: You must be aware that the offscreen works
like a full window, and that the child draw() methods add their
x/y coordinates to draw at the correct positions. However, the
scroll mechanism can add *negative* offsets to the widgets, so that
they are positioned more to the left and top. That's why I suggested
to resize() the Fl_Canvas to (0,0) temporary, and to set the scrollbars
to their initial position (0,0) as well.

see appended file capture_v2.cxx ;-)

Enjoy !

Albrecht
/*
  This demo program captures the contents of an Fl_Scroll in an
  Fl_RGB_Image. The image is then shown in another window.
  
  This version works independent of current scrollbar positions.

  Warning: There's NO CLEANUP, don't use this for production code !

  Compile and link with (use FLTK 1.3.x):

    fltk-config --compile capture.cxx
*/

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#include <FL/Fl.H>
#include <FL/x.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_RGB_Image.H>
#include <FL/fl_draw.h>

class Fl_Canvas : public Fl_Scroll {

  public:
    Fl_Canvas(int X, int Y, int W, int H, const char *L=0);
    Fl_RGB_Image *capture();
};

Fl_Canvas::Fl_Canvas (int X, int Y, int W, int H, const char *L)
   : Fl_Scroll (X,Y,W,H,L) {}

Fl_RGB_Image* Fl_Canvas::capture()
{
   if(children() <= 2)
      return NULL;

   // save original position, size, and scrollbar positions

   int xx = x(), yy = y(), ww = w(), hh = h();
   int xp = scrollbar.value(), yp = hscrollbar.value();

   // Determine the full (unscrolled) size of the canvas area
   int xdim = w();
   int ydim = h();

   if(hscrollbar.visible())
      xdim += (int)hscrollbar.maximum();

   if(scrollbar.visible())
      ydim += (int)scrollbar.maximum();

   window()->make_current();

   // setup the offscreen buffer
   Fl_Offscreen offscr = fl_create_offscreen(xdim, ydim);

   // force children to draw into the offscreen buffer
   fl_begin_offscreen(offscr);

      fl_color(color());
      fl_rectf(0,0,xdim,ydim);  // draw background

      resize(0,0,xdim,ydim);    // fix relative position
      scroll_to (0,0);          // fix child positions

      redraw();                 // make it really draw

      // Note: resize() also fixes the scrollbar positions,
      // i.e. the last 2 children are the scrollbars now.
      // (You could also test for &scrollbar and &hscrollbar !)

      for (int i=0; i<children()-2; i++) { // without scrollbars

        Fl_Widget *o = child(i);
        o->draw();
      }

      // Annotate the image...write on the image
      fl_rectf(100, 100, 150, 100, FL_BLACK);
      fl_color(FL_WHITE);
      fl_font(FL_TIMES, 15);
      fl_draw("Hello, World!", 125, 125);

      // read the image back...
      uchar *offscreenImage = 
        fl_read_image(0, 0, 0, xdim, ydim);

   fl_end_offscreen();

   // Pack a Fl_RGB_Image and force its dtor to do the cleanup
   Fl_RGB_Image *rgb_img = new Fl_RGB_Image(offscreenImage,xdim-x(),ydim-y(),3);
   rgb_img->alloc_array = 1;

   // restore position, size, and scrollbars
   resize(xx,yy,ww,hh);
   scroll_to(xp,yp);
   redraw(); // just to be sure

   return rgb_img;
}

static Fl_Canvas *canvas = 0;

static void button_cb (Fl_Widget *, void *) {

    Fl_RGB_Image *img = canvas->capture();
    
    if (img && img->w()>0 && img->h()>0 && img->d()>0) {

      Fl_Window *tw = new Fl_Window (img->w(),img->h(),"captured image");
      Fl_Box *b = new Fl_Box(0,0,img->w(),img->h());
      b->box(FL_FLAT_BOX);
      b->image(img);
      tw->end();
      tw->show();
    }
}

int main (int argc, char **argv)
{
   Fl_Window *win = new Fl_Window (800,600,"capture test");
   
   canvas = new Fl_Canvas (100,100,600,400);
   canvas->box(FL_DOWN_BOX);
   
   Fl_Box *box1 = new Fl_Box (100,100,100,100,"Box 1");
   box1->color(FL_RED);
   box1->box(FL_FLAT_BOX);
   box1->align(FL_ALIGN_INSIDE|FL_ALIGN_CENTER);
   
   Fl_Box *box2 = new Fl_Box (650,450,100,100,"Box 2");
   box2->color(FL_YELLOW);
   box2->box(FL_FLAT_BOX);
   box2->align(FL_ALIGN_INSIDE|FL_ALIGN_CENTER);

   canvas->end();
   
   Fl_Button *button = new Fl_Button (20,520,60,30,"capture");
   button->callback(button_cb);
   
   win->end();
   
   win->show(argc,argv);
   
   return Fl::run();
   
}
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to