Index: src/Fl_Copy_Surface.cxx
===================================================================
--- src/Fl_Copy_Surface.cxx	(revision 0)
+++ src/Fl_Copy_Surface.cxx	(revision 0)
@@ -0,0 +1,227 @@
+
+#if defined(__APPLE__) || defined(WIN32) || defined(FL_DOXYGEN)
+#include <FL/Fl_Copy_Surface.H>
+
+const char *Fl_Copy_Surface::class_id = "Fl_Copy_Surface";
+
+/** Constructor. 
+ \param w and \param h are the width and height of the clipboard surface
+ in points where drawing will occur.
+ */
+Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) : Fl_System_Printer()
+{
+  width = w;
+  height = h;
+  scale_x = 1;
+  scale_y = 1;
+#ifdef __APPLE__
+  prepare_copy_pdf_and_tiff(w, h);
+  oldgc = fl_gc;
+#elif defined(WIN32)
+  oldgc = fl_gc;
+  // exact computation of factor from screen units to EnhMetaFile units (0.01 mm)
+  HDC hdc = GetDC(NULL);
+  int hmm = GetDeviceCaps(hdc, HORZSIZE);
+  int hdots = GetDeviceCaps(hdc, HORZRES);
+  int vmm = GetDeviceCaps(hdc, VERTSIZE);
+  int vdots = GetDeviceCaps(hdc, VERTRES);
+  ReleaseDC(NULL, hdc);
+  float factorw =  (100. * hmm) / hdots;
+  float factorh =  (100. * vmm) / vdots + 0.5;
+  
+  RECT rect; rect.left = 0; rect.top = 0; rect.right = w * factorw; rect.bottom = h * factorh;
+  gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL);
+  if (gc != NULL) {
+    SetGraphicsMode(gc, GM_ADVANCED); // needed for ModifyWorldTransform()
+    SetTextAlign(gc, TA_BASELINE|TA_LEFT);
+    SetBkMode(gc, TRANSPARENT);
+  } 
+  Fl_Graphics_Driver* d = driver();
+  delete d;
+  driver(new Fl_GDI_Graphics_Driver); // don't use the printer driver
+#endif
+}
+
+/** Destructor.
+ */
+Fl_Copy_Surface::~Fl_Copy_Surface()
+{
+#ifdef __APPLE__
+  complete_copy_pdf_and_tiff();
+#elif defined(WIN32)
+  if(oldgc == fl_gc) oldgc = NULL;
+  HENHMETAFILE hmf = CloseEnhMetaFile (gc);
+  if ( hmf != NULL ) {
+    if ( OpenClipboard (NULL) ){
+      EmptyClipboard ();
+      SetClipboardData (CF_ENHMETAFILE, hmf);
+      CloseClipboard ();
+    }
+    DeleteEnhMetaFile(hmf);
+  }
+  DeleteDC(gc);
+#endif
+  fl_gc = oldgc;
+}
+
+void Fl_Copy_Surface::set_current()
+{
+  fl_gc = gc;
+  fl_window = (Window)1;
+  Fl_Surface_Device::set_current();
+}
+
+
+int Fl_Copy_Surface::printable_rect(int *w, int *h)
+{
+  *w = width * scale_x;
+  *h = height * scale_y;
+  return 0;
+}
+
+
+void Fl_Copy_Surface::margins(int *left, int *top, int *right, int *bottom)
+{
+  *left = *top = *right = *bottom = 0;
+}
+
+#ifdef WIN32
+void Fl_Copy_Surface::scale (float scalex, float scaley)
+{
+  if (scaley == 0.) scaley = scalex;
+  scale_x = scalex;
+  scale_y = scaley;
+  XFORM mat;
+  mat.eM11 = scalex;
+  mat.eM12 = 0;
+  mat.eM21 = 0;
+  mat.eM22 = scaley;
+  mat.eDx = mat.eDy = 0;
+  SetWorldTransform(gc, &mat);
+}
+#endif
+
+#ifdef __APPLE__
+
+size_t Fl_Copy_Surface::MyPutBytes(void* info, const void* buffer, size_t count)
+{
+  CFDataAppendBytes ((CFMutableDataRef) info, (const UInt8 *)buffer, count);
+  return count;
+}
+
+void Fl_Copy_Surface::init_PDF_context(int w, int h)
+{
+  CGRect bounds = CGRectMake(0, 0, w, h );	
+  pdfdata = CFDataCreateMutable(NULL, 0);
+  CGDataConsumerRef myconsumer;
+  if(CGDataConsumerCreateWithCFData != NULL) { // true from 10.4
+    myconsumer = CGDataConsumerCreateWithCFData (pdfdata);
+  }
+  else {
+    static CGDataConsumerCallbacks callbacks = { MyPutBytes, NULL };
+    myconsumer = CGDataConsumerCreate ((void*) pdfdata, &callbacks);
+  }
+  gc = CGPDFContextCreate (myconsumer, &bounds, NULL);
+  CGDataConsumerRelease (myconsumer);
+}
+
+void Fl_Copy_Surface::prepare_copy_pdf_and_tiff(int w, int h)
+{
+  init_PDF_context(w, h);
+  if (gc == NULL) return;
+  CGContextBeginPage (gc, NULL);
+  CGContextTranslateCTM(gc, 0, h);
+  CGContextScaleCTM(gc, 1.0f, -1.0f);
+  CGContextSaveGState(gc);
+}
+
+
+static void bitmap_to_tiff_clipboard(CGContextRef c, PasteboardRef clipboard)
+{
+  CFStringRef tiff = CFSTR("public.tiff");
+#ifdef __OBJC__
+  //objective-c version that does not require OS X 10.4
+  unsigned char *mem = (unsigned char *)CGBitmapContextGetData(c);
+  NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&mem
+								  pixelsWide:CGBitmapContextGetWidth(c)
+								  pixelsHigh:CGBitmapContextGetHeight(c)
+							       bitsPerSample:8
+							     samplesPerPixel:3
+								    hasAlpha:NO
+								    isPlanar:NO
+							      colorSpaceName:NSDeviceRGBColorSpace
+								 bytesPerRow:CGBitmapContextGetBytesPerRow(c)
+								bitsPerPixel:CGBitmapContextGetBitsPerPixel(c)];
+  CFDataRef data = (CFDataRef)[rep TIFFRepresentation];
+  [rep release];
+  PasteboardPutItemFlavor(clipboard, (PasteboardItemID)1, tiff, data, kPasteboardFlavorNoFlags );
+  
+#else // __OBJC__
+  
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 // c++ version that requires 10.4
+  CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
+  if(fl_mac_os_version >= 100400) {
+    CGImageRef image = CGBitmapContextCreateImage(c); // 10.4
+    CGImageDestinationRef dest = CGImageDestinationCreateWithData(data,tiff, 1, NULL); // 10.4
+    CGImageDestinationAddImage(dest, image, NULL); // 10.4
+    CGImageDestinationFinalize(dest); // 10.4
+    CGImageRelease(image);
+    CFRelease(dest);
+    }
+  PasteboardPutItemFlavor(clipboard, (PasteboardItemID)1, tiff, data, kPasteboardFlavorNoFlags );
+  CFRelease(data);
+#endif
+  
+#endif // __OBJC__
+}
+
+
+void Fl_Copy_Surface::complete_copy_pdf_and_tiff()
+{
+  int w, h;
+  CGContextEndPage(gc);
+  CGContextRelease(gc);
+  PasteboardRef clipboard = NULL;
+  PasteboardCreate(kPasteboardClipboard, &clipboard);
+  PasteboardClear(clipboard); //	first, copy PDF to clipboard 
+  PasteboardPutItemFlavor (clipboard, (PasteboardItemID)1, 
+			   CFSTR("com.adobe.pdf"), // kUTTypePDF
+			   pdfdata, kPasteboardFlavorNoFlags);
+  //second, transform this PDF to a bitmap image and put it as tiff in clipboard
+  CGDataProviderRef prov;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+  if(fl_mac_os_version >= 100400)
+    prov = CGDataProviderCreateWithCFData(pdfdata); // 10.4
+  else 
+#endif
+    prov = CGDataProviderCreateWithData(NULL, CFDataGetBytePtr(pdfdata), CFDataGetLength(pdfdata), NULL);
+  CGPDFDocumentRef pdfdoc = CGPDFDocumentCreateWithProvider(prov);
+  CGPDFPageRef pdfpage = CGPDFDocumentGetPage(pdfdoc, 1);
+  CGRect clip = CGPDFPageGetBoxRect(pdfpage, kCGPDFCropBox);
+  w = (int)(clip.size.width + 0.5);
+  h = (int)(clip.size.height + 0.5);
+  CGDataProviderRelease(prov);
+  CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+  const int scale = 2;
+  w *= scale; h *= scale;
+  void *mem = ( fl_mac_os_version >= 100600 ? NULL : malloc(w * h * 4) );
+  gc = CGBitmapContextCreate(mem, w, h, 8, w * 4, space, kCGImageAlphaNoneSkipLast);
+  CFRelease(space);
+  if (gc == NULL) { if (mem) free(mem); return; }
+  CGRect rect = CGRectMake(0, 0, w, h);
+  CGContextSetRGBFillColor(gc,  1,1,1,1);//need to clear background
+  CGContextFillRect(gc, rect);
+  CGContextConcatCTM(gc, CGAffineTransformMakeScale(scale, scale));
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+  CGContextDrawPDFPage(gc, pdfpage);  // requires 10.3
+#endif
+  CGPDFDocumentRelease(pdfdoc);
+  CFRelease(pdfdata);
+  bitmap_to_tiff_clipboard(gc, clipboard);
+  CFRelease(clipboard);    
+  CGContextRelease(gc);
+  if (mem) free(mem);
+}
+#endif //__APPLE__
+
+#endif // defined(__APPLE__) || defined(WIN32)
Index: src/Makefile
===================================================================
--- src/Makefile	(revision 10113)
+++ src/Makefile	(working copy)
@@ -31,6 +31,7 @@
 	Fl_Choice.cxx \
 	Fl_Clock.cxx \
 	Fl_Color_Chooser.cxx \
+	Fl_Copy_Surface.cxx \
 	Fl_Counter.cxx \
 	Fl_Dial.cxx \
 	Fl_Device.cxx \
Index: FL/Fl_Copy_Surface.H
===================================================================
--- FL/Fl_Copy_Surface.H	(revision 0)
+++ FL/Fl_Copy_Surface.H	(revision 0)
@@ -0,0 +1,68 @@
+#include <FL/Fl_Paged_Device.H>
+#include <FL/Fl_Printer.H>
+
+#if defined(__APPLE__) || defined(WIN32) || defined(FL_DOXYGEN)
+
+
+#if defined(__APPLE__)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+/** A class that supports copying of graphical data to the clipboard (MSWindows and Mac OS only).
+ 
+ This class is implemented only on the MSWindows and Mac OS platforms.
+ <br> After creation of an Fl_Copy_Surface object, call set_current() on it, and all subsequent graphics requests
+ will be recorded in the clipboard. It's possible to draw widgets (using Fl_Copy_Surface::print_widget()
+ or Fl_Copy_Surface::print_window()) or to use any of the \ref fl_drawings or the \ref fl_attributes.
+ Finally, delete the Fl_Copy_Surface object to load the clipboard with the graphical data.
+ <br> Fl_GL_Window's can be copied to the clipboard as well. 
+ <br> Usage example:
+ \code
+ Fl_Widget *g = ...; // a widget you want to copy to the clipboard
+ Fl_Copy_Surface *copy_surf = new Fl_Copy_Surface(g->w(), g->h()); // create an Fl_Copy_Surface object
+ copy_surf->set_current(); // direct graphics requests to the clipboard
+ copy_surf->print_widget(g); // draw the g widget in the clipboard
+ delete copy_surf; // after this, the clipboard is loaded
+ Fl_Display_Device::display_device()->set_current();  // direct graphics requests back to the display
+ \endcode
+ Platform details:
+ \li MSWindows: Transparent RGB images copy without transparency.
+ The graphical data is copied to the clipboard as an 'enhanced metafile'.
+ \li Mac OS: Mac OS X 10.4 or higher is necessary. The graphical data is copied to the 
+ clipboard (a.k.a. pasteboard) in 2 'flavors': 
+ 1) in vectorial form as PDF data; 2) in bitmap form as a TIFF image. Applications to which the 
+ clipboard content is pasted can use the flavor that suits them best.
+ 
+ */
+class Fl_Copy_Surface : public Fl_System_Printer {
+private:
+  int width;
+  int height;
+  float scale_x;
+  float scale_y;
+#ifdef __APPLE__
+  CFMutableDataRef pdfdata;
+  CGContextRef oldgc;
+  CGContextRef gc;
+  void prepare_copy_pdf_and_tiff(int w, int h);
+  void complete_copy_pdf_and_tiff();
+  void init_PDF_context(int w, int h);
+  static size_t MyPutBytes(void* info, const void* buffer, size_t count);
+#elif defined(WIN32)
+  HDC oldgc;
+  HDC           gc;
+#endif
+public:
+  static const char *class_id;
+  const char *class_name() {return class_id;};
+  Fl_Copy_Surface(int w, int h);
+  ~Fl_Copy_Surface();
+  int printable_rect(int *w, int *h);
+  void margins(int *left, int *top, int *right, int *bottom);
+  void set_current();
+#ifdef WIN32
+  void scale (float scale_x, float scale_y = 0.);
+#endif
+};
+
+#endif
Index: test/device.cxx
===================================================================
--- test/device.cxx	(revision 10113)
+++ test/device.cxx	(working copy)
@@ -564,6 +564,21 @@
   delete p;
 }
 
+#if defined(__APPLE__) || defined(WIN32)
+#include <FL/Fl_Copy_Surface.H>
+#endif
+
+void copy(Fl_Widget *, Fl_Widget *w) {
+#if defined(__APPLE__) || defined(WIN32)
+  Fl_Window* g =  w->window();
+  Fl_Copy_Surface *copy_surf = new Fl_Copy_Surface(g->w(), g->h());
+  copy_surf->set_current();
+  copy_surf->print_widget(g);
+  delete copy_surf;
+  Fl_Display_Device::display_device()->set_current();  
+#endif
+}
+
 /*void print2(Fl_Widget *, void *w) {
  Fl_Widget * g = (Fl_Widget *)w;
  Fl_Printer * p = fl_printer_chooser();
@@ -675,6 +690,8 @@
   c2->end();
   Fl_Button *b4 = new Fl_Button(10,5, 150, 25, "Print");
   b4->callback(print,c2);
+  Fl_Button *b6 = new Fl_Button(170,5, 150, 25, "Copy");
+  b6->callback((Fl_Callback*)copy,c2);
   /*Fl_Button *b5 = new Fl_Button(165,5, 90, 25, "Print");
    b5->tooltip("This is a tooltip");
    b5->callback(print2,c2);*/
