summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2024-03-31 16:55:49 +0200
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2024-04-30 10:22:47 +0200
commit9472ff546cc0b4150d4dec89b48b3e4814b421f6 (patch)
treebd4bd14b59b13a41decf50a207c7e1770bcabd6e
parentb402b6a8397f9fc13157813d39d505ea9ead00f0 (diff)
Implement and document new class Fl_PDF_File_Surface
-rw-r--r--CHANGES.txt4
-rw-r--r--FL/Fl_Device.H10
-rw-r--r--FL/Fl_PDF_File_Surface.H89
-rw-r--r--src/Fl_Device.cxx32
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm140
-rw-r--r--src/drivers/PostScript/Fl_PostScript.cxx261
-rw-r--r--src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H3
-rw-r--r--src/drivers/PostScript/Fl_PostScript_image.cxx2
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx190
-rw-r--r--test/device.cxx61
10 files changed, 733 insertions, 59 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 1348c2aed..c2ee9e889 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -56,8 +56,8 @@ Changes in FLTK 1.4.0 Released: Feb ?? 2024
- New Fl_SVG_Image class: gives support of scalable vector graphics images
to FLTK using the nanosvg software.
- New Fl_ICO_Image class to read Windows .ico icon files.
- - New classes Fl_SVG_File_Surface and Fl_EPS_File_Surface to save any FLTK
- graphics to SVG or EPS files, respectively.
+ - New classes Fl_PDF_File_Surface, Fl_SVG_File_Surface and Fl_EPS_File_Surface
+ to save any FLTK graphics to PDF, SVG or EPS files, respectively.
- New member functions Fl_Window::maximize(), Fl_Window::un_maximize() and
Fl_Window::maximize_active() to programmatically manage window maximization.
- Fl_Button now supports a compact flag that visually groups closely set
diff --git a/FL/Fl_Device.H b/FL/Fl_Device.H
index 93de0b4f9..ab216a0e0 100644
--- a/FL/Fl_Device.H
+++ b/FL/Fl_Device.H
@@ -52,16 +52,6 @@ class Fl_Image_Surface;
</ol>
For back-compatibility, it is also possible to use the Fl_Surface_Device::set_current() member function
to change the current drawing surface, once to the new surface, once to the previous one.
-
- Class Fl_Surface_Device can also be derived to define new kinds of graphical output
- usable with FLTK drawing functions.
- An example would be to draw to a PDF file. This would require to create a new class,
- say PDF_File_Surface, derived from class Fl_Surface_Device, and another new class,
- say PDF_Graphics_Driver, derived from class Fl_Graphics_Driver.
- Class PDF_Graphics_Driver should implement all virtual methods of the Fl_Graphics_Driver class
- to support all FLTK drawing functions and have them draw into PDF files. Alternatively,
- class PDF_Graphics_Driver could implement only some virtual methods, and only part of
- the FLTK drawing API would be usable when drawing to PDF files.
*/
class FL_EXPORT Fl_Surface_Device {
/** The graphics driver in use by this surface. */
diff --git a/FL/Fl_PDF_File_Surface.H b/FL/Fl_PDF_File_Surface.H
new file mode 100644
index 000000000..7fd2ed507
--- /dev/null
+++ b/FL/Fl_PDF_File_Surface.H
@@ -0,0 +1,89 @@
+//
+// Declaration of class Fl_PDF_File_Surface for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2024 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// https://www.fltk.org/COPYING.php
+//
+// Please see the following page on how to report bugs and issues:
+//
+// https://www.fltk.org/bugs.php
+//
+
+#ifndef PDF_FILE_SURFACE_H
+#define PDF_FILE_SURFACE_H
+
+#include <FL/Fl_Paged_Device.H>
+
+/**
+ To send graphical output to a PDF file.
+ Class Fl_PDF_File_Surface is used exactly as the Fl_Printer class except for its 2 member functions begin_job() and begin_document().
+ <p><b>Platform notes:</b>
+ - Windows: requires "Microsoft Print to PDF" available in Windows 10 and later.
+ - Wayland/X11: requires the FLTK library was built with FLTK_USE_PANGO=1.
+ - macOS: requires macOS 10.9 or later.
+ <p>If the running platform doesn't fulfill the requirement above, the program runs but doesn't output any PDF.
+*/
+class FL_EXPORT Fl_PDF_File_Surface : public Fl_Paged_Device {
+private:
+ const char **out_filename_;
+ Fl_Paged_Device *platform_surface_;
+ static Fl_Paged_Device *new_platform_pdf_surface_(const char ***);
+public:
+ /** \name These attributes are useful for the Wayland/X11 platform only.
+ \{
+ */
+ static const char * format_dialog_title;
+ static const char * format_dialog_page_size;
+ static const char * format_dialog_orientation;
+ static const char * format_dialog_default;
+ /** \} */
+ Fl_PDF_File_Surface();
+ ~Fl_PDF_File_Surface();
+ /** Prepare to draw to a PDF document identified with a file chooser.
+ A dialog opens to select the location and name of the output PDF document
+ as well as its page format and orientation.
+ \param defaultfilename Default name for the PDF document
+ \param perr NULL or address of a string that receives a message in case of error.
+ To be deleted[] after use.
+ \return 0 for success, 1 when the user cancelled the operation, 2 when an error occurred.
+ */
+ int begin_job(const char* defaultfilename, char **perr = NULL);
+ /** Don't use for this class */
+ int begin_job(int, int *, int *, char **) FL_OVERRIDE {return 1;}
+ /** Prepare to draw to a PDF document identified by its pathname.
+ \param pathname Path name for the PDF document
+ \param format The paper format for the PDF document
+ \param layout The orientation for the PDF document
+ \param perr NULL or address of a string that receives a message in case of error.
+ To be deleted[] after use.
+ \return 0 for success, 2 when an error occurred.
+ */
+ int begin_document(const char* pathname,
+ enum Fl_Paged_Device::Page_Format format = Fl_Paged_Device::A4,
+ enum Fl_Paged_Device::Page_Layout layout = Fl_Paged_Device::PORTRAIT,
+ char **perr = NULL);
+ int printable_rect(int *w, int *h) FL_OVERRIDE { return platform_surface_->printable_rect(w,h); }
+ void margins(int *left, int *top, int *right, int *bottom) FL_OVERRIDE {
+ platform_surface_->margins(left,top,right,bottom);
+ }
+ void origin(int x, int y) FL_OVERRIDE {platform_surface_->origin(x, y);}
+ void origin(int *x, int *y) FL_OVERRIDE {platform_surface_->origin(x, y);}
+ void scale(float s_x, float s_y = 0) FL_OVERRIDE {platform_surface_->scale(s_x, s_y);}
+ void rotate(float angle) FL_OVERRIDE {platform_surface_->rotate(angle);}
+ void translate(int x, int y) FL_OVERRIDE {platform_surface_->translate(x, y);}
+ void untranslate() FL_OVERRIDE {platform_surface_->untranslate();};
+ int begin_page(void) FL_OVERRIDE {return platform_surface_->begin_page();}
+ int end_page(void) FL_OVERRIDE {return platform_surface_->end_page();}
+ void end_job(void) FL_OVERRIDE {return platform_surface_->end_job();}
+ /** Returns the name of the PDF document */
+ inline const char *pdf_filename() { return *out_filename_; }
+ void set_current() FL_OVERRIDE { if (platform_surface_) platform_surface_->set_current(); }
+ bool is_current() FL_OVERRIDE { return surface() == platform_surface_; }
+};
+
+#endif // PDF_FILE_SURFACE_H
diff --git a/src/Fl_Device.cxx b/src/Fl_Device.cxx
index b6c3f4da0..16a9045bd 100644
--- a/src/Fl_Device.cxx
+++ b/src/Fl_Device.cxx
@@ -1,7 +1,7 @@
//
// implementation of classes Fl_Surface_Device and Fl_Display_Device for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2023 by Bill Spitzak and others.
+// Copyright 2010-2024 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -46,6 +46,11 @@
|
+- Fl_Posix_Printer_Driver: Fl_Printer uses that under Posix platforms
+- Fl_GTK_Printer_Driver: Fl_Printer uses that under Posix+GTK platforms
+ +- Fl_PDF_File_Surface: draw into a PDF file
+ +- Fl_PDF_GDI_File_Surface: Windows-specific helper class interfacing FLTK with PDF operations
+ +- Fl_PDF_Pango_File_Surface: Linux/Unix-specific helper class interfacing FLTK with PDF operations
+ +- Fl_PDF_Cocoa_File_Surface: macOS-specific helper class interfacing FLTK with PDF operations
+
+- Fl_Graphics_Driver -> directed to an Fl_Surface_Device object
|
@@ -154,3 +159,28 @@ Fl_Device_Plugin *Fl_Device_Plugin::opengl_plugin() {
}
return pi;
}
+
+#if !defined(FL_NO_PRINT_SUPPORT)
+
+#include <FL/Fl_PDF_File_Surface.H>
+
+Fl_PDF_File_Surface::Fl_PDF_File_Surface() {
+ platform_surface_ = new_platform_pdf_surface_(&out_filename_);
+ driver(platform_surface_->driver());
+}
+
+
+Fl_PDF_File_Surface::~Fl_PDF_File_Surface() {
+ delete platform_surface_;
+}
+
+#endif // !defined(FL_NO_PRINT_SUPPORT)
+
+/** Localizable text of the "PDF document settings" dialog */
+const char * Fl_PDF_File_Surface::format_dialog_title = "PDF document settings";
+/** Localizable text of the "PDF document settings" dialog */
+const char * Fl_PDF_File_Surface::format_dialog_page_size = "Page Size:";
+/** Localizable text of the "PDF document settings" dialog */
+const char * Fl_PDF_File_Surface::format_dialog_default = "Set as default";
+/** Localizable text of the "PDF document settings" dialog */
+const char * Fl_PDF_File_Surface::format_dialog_orientation = "Orientation:";
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm b/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
index 3163f01b3..0df98af7e 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
+++ b/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
@@ -1,7 +1,7 @@
//
// Mac OS X-specific printing support (objective-c++) for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2018 by Bill Spitzak and others.
+// Copyright 2010-2024 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -20,6 +20,7 @@
#include "../../Fl_Screen_Driver.H"
#include "../Quartz/Fl_Quartz_Graphics_Driver.H"
#include "../Darwin/Fl_Darwin_System_Driver.H"
+#include <FL/Fl_PDF_File_Surface.H>
#include "Fl_Cocoa_Window_Driver.H"
#include <FL/Fl.H>
@@ -48,7 +49,7 @@ typedef OSStatus
/** Support for printing on the Apple OS X platform */
class Fl_Cocoa_Printer_Driver : public Fl_Paged_Device {
friend class Fl_Printer;
-private:
+protected:
float scale_x;
float scale_y;
float angle; // rotation angle in radians
@@ -391,3 +392,138 @@ void Fl_Cocoa_Printer_Driver::origin(int *x, int *y)
{
Fl_Paged_Device::origin(x, y);
}
+
+
+class Fl_PDF_Cocoa_File_Surface : public Fl_Cocoa_Printer_Driver
+{
+public:
+ char *doc_fname;
+ Fl_PDF_Cocoa_File_Surface();
+ ~Fl_PDF_Cocoa_File_Surface() { if (doc_fname) free(doc_fname); }
+ int begin_job(const char *defaultname,
+ char **perr_message = NULL);
+ int begin_job(int, int*, int *, char **) FL_OVERRIDE {return 1;} // don't use
+ int begin_document(const char* outname,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message);
+};
+
+
+Fl_PDF_Cocoa_File_Surface::Fl_PDF_Cocoa_File_Surface() {
+ driver(new Fl_Quartz_Graphics_Driver());
+ doc_fname = NULL;
+}
+
+
+int Fl_PDF_Cocoa_File_Surface::begin_job(const char* defaultfilename,
+ char **perr_message) {
+ OSStatus status = 0;
+ if (fl_mac_os_version < 100900) return 1;
+ Fl_Window *top = Fl::first_window();
+ NSWindow *main = (top ? (NSWindow*)fl_xid(top->top_window()) : nil);
+ if (!main) return 1;
+ Fl_Cocoa_Window_Driver::q_release_context();
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 && defined(__BLOCKS__)
+ NSPDFInfo *pdf_info = [[NSPDFInfo alloc] init]; // 10.9
+ NSPDFPanel *pdf_panel = [NSPDFPanel panel]; // 10.9
+ char buf[FL_PATH_MAX];
+ strcpy(buf, defaultfilename);
+ fl_filename_setext(buf, sizeof(buf), NULL);
+ [pdf_panel setDefaultFileName:[NSString stringWithUTF8String:buf]];
+ [pdf_panel setOptions: NSPrintPanelShowsOrientation | NSPrintPanelShowsPaperSize];
+ NSInteger retval = -1;
+ __block NSInteger complete = -1;
+ [pdf_panel beginSheetWithPDFInfo:pdf_info
+ modalForWindow:main
+ completionHandler:^(NSInteger returnCode) {
+ // this block runs after OK or Cancel was triggered in file dialog
+ complete = returnCode;
+ }
+ ];
+ while (complete == -1) Fl::wait(100); // loop until end of file dialog
+ retval = complete;
+ [main makeKeyAndOrderFront:nil];
+ if (retval != NSModalResponseOK) return 1;
+ NSURL *url = [pdf_info URL];
+ doc_fname = fl_strdup([url fileSystemRepresentation]);
+ NSPrintInfo *pr_info = [NSPrintInfo sharedPrintInfo];
+ [pr_info takeSettingsFromPDFInfo:pdf_info];
+ [pdf_info release];
+ printSession = (PMPrintSession)[pr_info PMPrintSession];
+ printSettings = (PMPrintSettings)[pr_info PMPrintSettings];
+ pageFormat = (PMPageFormat)[pr_info PMPageFormat];
+ status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4
+#endif
+ if (status != noErr) {
+ if (perr_message) {
+ NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil];
+ NSString *s = [nserr localizedDescription];
+ if (s) *perr_message = fl_strdup([s UTF8String]);
+ }
+ free(doc_fname);
+ doc_fname = NULL;
+ return 2;
+ }
+ y_offset = x_offset = 0;
+ return 0;
+}
+
+
+int Fl_PDF_Cocoa_File_Surface::begin_document(const char* outfname,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message) {
+ OSStatus status = 0;
+ fl_open_display();
+ if (fl_mac_os_version < 100900) return 1;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
+ NSPDFInfo *pdf_info = [[NSPDFInfo alloc] init]; // 10.9
+ doc_fname = fl_strdup(outfname);
+ NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:doc_fname]];
+ [pdf_info setURL:url];
+ NSSize psize = {(CGFloat)Fl_Paged_Device::page_formats[format].width, (CGFloat)Fl_Paged_Device::page_formats[format].height};
+ [pdf_info setPaperSize:psize];
+ [pdf_info setOrientation:(layout == PORTRAIT ? NSPaperOrientationPortrait : NSPaperOrientationLandscape)];
+ NSPrintInfo *pr_info = [NSPrintInfo sharedPrintInfo];
+ [pr_info takeSettingsFromPDFInfo:pdf_info];
+ [pdf_info release];
+ printSession = (PMPrintSession)[pr_info PMPrintSession];
+ printSettings = (PMPrintSettings)[pr_info PMPrintSettings];
+ pageFormat = (PMPageFormat)[pr_info PMPageFormat];
+ status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4
+#endif
+ if (status != noErr) {
+ if (perr_message) {
+ NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil];
+ NSString *s = [nserr localizedDescription];
+ if (s) *perr_message = fl_strdup([s UTF8String]);
+ }
+ free(doc_fname);
+ doc_fname = NULL;
+ return 2;
+ }
+ y_offset = x_offset = 0;
+ return 0;
+}
+
+
+Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) {
+ Fl_PDF_Cocoa_File_Surface *surf = new Fl_PDF_Cocoa_File_Surface();
+ *pfname = (const char**)&surf->doc_fname;
+ return surf;
+}
+
+
+int Fl_PDF_File_Surface::begin_job(const char* defaultfilename,
+ char **perr_message) {
+ return ((Fl_PDF_Cocoa_File_Surface*)platform_surface_)->begin_job(defaultfilename, perr_message);
+}
+
+
+int Fl_PDF_File_Surface::begin_document(const char* defaultfilename,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message) {
+ return ((Fl_PDF_Cocoa_File_Surface*)platform_surface_)->begin_document(defaultfilename, format, layout, perr_message);
+}
diff --git a/src/drivers/PostScript/Fl_PostScript.cxx b/src/drivers/PostScript/Fl_PostScript.cxx
index bee34703d..3b81789d0 100644
--- a/src/drivers/PostScript/Fl_PostScript.cxx
+++ b/src/drivers/PostScript/Fl_PostScript.cxx
@@ -1,7 +1,7 @@
//
// Classes Fl_PostScript_File_Device and Fl_PostScript_Graphics_Driver for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2022 by Bill Spitzak and others.
+// Copyright 2010-2024 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -21,11 +21,17 @@
#include <FL/fl_draw.H>
#include <stdio.h>
#include "Fl_PostScript_Graphics_Driver.H"
+#include <FL/Fl_PDF_File_Surface.H>
#include <FL/Fl_PostScript.H>
#include <FL/Fl_Image_Surface.H>
#include <FL/Fl_Native_File_Chooser.H>
#include "../../Fl_System_Driver.H"
+#include <FL/Fl_Choice.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Check_Button.H>
+#include <FL/Fl_Return_Button.H>
#include <FL/fl_string_functions.h>
+#include <FL/fl_callback_macros.H>
#include <FL/platform.H>
#include <stdarg.h>
#include <time.h>
@@ -33,6 +39,8 @@
#include <FL/math.h> // for M_PI
#include <pango/pangocairo.h>
#include <cairo/cairo-ps.h>
+#include <cairo/cairo-pdf.h>
+#include <FL/Fl_Preferences.H>
# if ! PANGO_VERSION_CHECK(1,10,0)
# error "Requires Pango 1.10 or higher"
# endif
@@ -150,6 +158,7 @@ Fl_PostScript_Graphics_Driver::Fl_PostScript_Graphics_Driver(void)
scale_x = scale_y = 1.;
#endif
ps_filename_ = NULL;
+ nPages = 0;
}
/** \brief The destructor. */
@@ -1461,6 +1470,30 @@ void Fl_PostScript_Graphics_Driver::ps_untranslate(void)
fprintf(output, "GR GR\n");
}
+#if defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND)
+
+Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) {
+ *pfname = NULL;
+ return new Fl_PostScript_File_Device;
+}
+
+int Fl_PDF_File_Surface::begin_job(const char* defaultfilename,
+ char **perr_message) {
+ if (perr_message) {
+ *perr_message = strdup("Class Fl_PDF_File_Surface requires PANGO to be usable.");
+ }
+ return 2;
+}
+
+int Fl_PDF_File_Surface::begin_document(const char* defaultfilename,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message) {
+ return begin_job(NULL, perr_message);
+}
+
+#endif // defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND)
+
# else // USE_PANGO
/* Cairo-based implementation of the PostScript graphics driver */
@@ -1552,6 +1585,232 @@ void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, dou
check_status();
}
+
+// =======================================================
+
+
+class Fl_PDF_Pango_File_Surface : public Fl_PostScript_File_Device
+{
+public:
+ char *doc_fname;
+ Fl_PDF_Pango_File_Surface();
+ ~Fl_PDF_Pango_File_Surface() { if (doc_fname) free(doc_fname); }
+ int begin_job(const char *defaultname,
+ char **perr_message = NULL);
+ int begin_job(int, int*, int *, char **) FL_OVERRIDE {return 1;} // don't use
+ int begin_document(const char* outname,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message);
+ int begin_page() FL_OVERRIDE;
+ void end_job() FL_OVERRIDE;
+};
+
+
+Fl_PDF_Pango_File_Surface::Fl_PDF_Pango_File_Surface() {
+ doc_fname = NULL;
+ driver()->output = NULL;
+}
+
+
+static Fl_Paged_Device::Page_Format menu_to_size[] = {Fl_Paged_Device::A3, Fl_Paged_Device::A4,
+ Fl_Paged_Device::A5, Fl_Paged_Device::B4, Fl_Paged_Device::B5, Fl_Paged_Device::EXECUTIVE,
+ Fl_Paged_Device::LEGAL, Fl_Paged_Device::LETTER, Fl_Paged_Device::TABLOID
+};
+static int size_count = sizeof(menu_to_size) / sizeof(menu_to_size[0]);
+
+
+static int update_format_layout(int rank, Fl_Paged_Device::Page_Layout layout,
+ bool &need_set_default_psize) {
+ int status = -1;
+ Fl_Window *modal = new Fl_Window(510, 90, Fl_PDF_File_Surface::format_dialog_title);
+ modal->begin();
+ Fl_Choice *psize = new Fl_Choice(140, 10, 110, 30, Fl_PDF_File_Surface::format_dialog_page_size);
+ psize->when(FL_WHEN_CHANGED);
+ for (int i = 0; i < size_count; i++) {
+ psize->add(Fl_Paged_Device::page_formats[menu_to_size[i]].name);
+ }
+ psize->value(rank);
+ Fl_Check_Button *default_size = new Fl_Check_Button(psize->x(), psize->y() + psize->h(),
+ psize->w(), psize->h(), Fl_PDF_File_Surface::format_dialog_default);
+ default_size->value(1);
+ default_size->user_data(&need_set_default_psize);
+ FL_INLINE_CALLBACK_2(psize, Fl_Choice*, choice, psize,
+ Fl_Check_Button*, check_but, default_size,
+ {
+ if (check_but->value() && choice->mvalue() && choice->prev_mvalue() &&
+ choice->prev_mvalue() != choice->mvalue()) {
+ check_but->value(0);
+ }
+ });
+ FL_INLINE_CALLBACK_2( modal, Fl_Window*, win, modal,
+ Fl_Check_Button*, check_but, default_size,
+ {
+ *((bool*)check_but->user_data()) = check_but->value();
+ win->hide();
+ } );
+ Fl_Choice *orientation = new Fl_Choice(psize->x() + psize->w() + 120, psize->y(), 130, psize->h(),
+ Fl_PDF_File_Surface::format_dialog_orientation);
+ orientation->add("PORTRAIT|LANDSCAPE");
+ orientation->value(layout == Fl_Paged_Device::PORTRAIT ? 0 : 1);
+ Fl_Return_Button *ok = new Fl_Return_Button(orientation->x() + orientation->w() - 55,
+ psize->y() + psize->h() + 10, 55, 30, fl_ok);
+ FL_INLINE_CALLBACK_4( ok, Fl_Widget*, b, ok,
+ int*, pstatus, &status,
+ Fl_Choice*, psize, psize,
+ Fl_Choice*, orientation, orientation,
+ {
+ *pstatus = menu_to_size[psize->value()] + 0x100 * orientation->value();
+ b->window()->do_callback();
+ } );
+ Fl_Button *cancel = new Fl_Button(ok->x() - 90, psize->y() + psize->h() + 10, 70, 30, fl_cancel);
+ FL_INLINE_CALLBACK_1( cancel, Fl_Widget*, wid, cancel, { wid->window()->do_callback(); } );
+ modal->end();
+ modal->set_modal();
+ modal->show();
+ while (modal->shown()) Fl::wait();
+ delete modal;
+ return status;
+}
+
+
+int Fl_PDF_Pango_File_Surface::begin_job(const char *defaultname, char **perr_message) {
+ static Page_Layout layout = PORTRAIT;
+
+ Fl_Preferences print_prefs(Fl_Preferences::CORE_USER, "fltk.org", "printers");
+ char *pref_format;
+ print_prefs.get("PDF/page_size", pref_format, "A4");
+ int rank = 1; // corresponds to A4
+ for (int i = 0; i < size_count; i++) {
+ if (strcmp(pref_format, Fl_Paged_Device::page_formats[menu_to_size[i]].name) == 0) {
+ rank = i;
+ break;
+ }
+ }
+ bool need_set_default_psize;
+ int status = update_format_layout(rank, layout, need_set_default_psize);
+ if (status == -1) return 1;
+ Page_Format format = (Page_Format)(status & 0xFF);
+ if (need_set_default_psize) print_prefs.set("PDF/page_size", Fl_Paged_Device::page_formats[format].name);
+
+ Fl_Native_File_Chooser ch(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
+ ch.preset_file(defaultname);
+ ch.filter("*.pdf");
+ ch.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM);
+ int retval = ch.show();
+ if (retval) return (retval == -1 ? 2 : 1);
+
+ layout = (Page_Layout)(status & 0x100);
+ return begin_document(ch.filename(), format, layout, perr_message);
+}
+
+
+int Fl_PDF_Pango_File_Surface::begin_document(const char* outfname,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message) {
+ int w = page_formats[format].width;
+ int h = page_formats[format].height;
+ if (layout == LANDSCAPE) {
+ int tmp = w;
+ w = h;
+ h = tmp;
+ }
+ Fl_PostScript_Graphics_Driver *dr = driver();
+ dr->output = fopen(outfname, "w");
+ cairo_status_t status = CAIRO_STATUS_WRITE_ERROR;
+ cairo_surface_t* cs = NULL;
+ if (dr->output) {
+ cs = cairo_pdf_surface_create_for_stream ( (cairo_write_func_t)write_to_cairo_stream,
+ dr->output, w, h);
+ status = cairo_surface_status(cs);
+ }
+ if (status != CAIRO_STATUS_SUCCESS) {
+ if (perr_message) {
+ const char *mess = cairo_status_to_string(status);
+ size_t l = strlen(mess) + strlen(outfname) + 100;
+ *perr_message = new char[l];
+ snprintf(*perr_message, l, "Error '%s' while attempting to create %s.", mess, outfname);
+ }
+ if (cs) cairo_surface_destroy(cs);
+ return 2;
+ }
+ cairo_pdf_surface_restrict_to_version(cs, CAIRO_PDF_VERSION_1_4);
+ cairo_t *cr = cairo_create(cs);
+ cairo_surface_destroy(cs);
+ dr->set_cairo(cr);
+ dr->pw_ = w;
+ dr->ph_ = h;
+ if (format == Fl_Paged_Device::A4) {
+ dr->left_margin = 18;
+ dr->top_margin = 18;
+ }
+ else {
+ dr->left_margin = 12;
+ dr->top_margin = 12;
+ }
+ doc_fname = strdup(outfname);
+ return 0;
+}
+
+
+int Fl_PDF_Pango_File_Surface::begin_page(void)
+{
+ Fl_PostScript_Graphics_Driver *ps = driver();
+ Fl_Surface_Device::push_current(this);
+ cairo_save(ps->cr());
+ cairo_translate(ps->cr(), ps->left_margin, ps->top_margin);
+ cairo_set_line_width(ps->cr(), 1);
+ cairo_set_source_rgb(ps->cr(), 1.0, 1.0, 1.0); // white background
+ cairo_save(ps->cr());
+ cairo_save(ps->cr());
+ ps->check_status();
+ x_offset = 0;
+ y_offset = 0;
+ ps->scale_x = ps->scale_y = 1.;
+ ps->angle = 0;
+ return 0;
+}
+
+
+void Fl_PDF_Pango_File_Surface::end_job() {
+ Fl_PostScript_Graphics_Driver *ps = driver();
+ int error = 0;
+ cairo_surface_t *s = cairo_get_target(ps->cr());
+ cairo_surface_finish(s);
+ error = cairo_surface_status(s);
+ int err2 = fclose(ps->output);
+ ps->output = NULL;
+ if (!error) error = err2;
+ cairo_destroy(ps->cr());
+ while (ps->clip_){
+ Fl_PostScript_Graphics_Driver::Clip * c= ps->clip_;
+ ps->clip_= ps->clip_->prev;
+ delete c;
+ }
+ if (error) fl_alert ("Error during PostScript data output.");
+}
+
+
+Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) {
+ Fl_PDF_Pango_File_Surface *surf = new Fl_PDF_Pango_File_Surface();
+ *pfname = (const char**)&surf->doc_fname;
+ return surf;
+}
+
+int Fl_PDF_File_Surface::begin_job(const char* defaultfilename,
+ char **perr_message) {
+ return ((Fl_PDF_Pango_File_Surface*)platform_surface_)->begin_job(defaultfilename, perr_message);
+}
+
+
+int Fl_PDF_File_Surface::begin_document(const char* defaultfilename,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message) {
+ return ((Fl_PDF_Pango_File_Surface*)platform_surface_)->begin_document(defaultfilename, format, layout, perr_message);
+}
+
#endif // USE_PANGO
/**
diff --git a/src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H b/src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H
index 904644f42..11258e8e4 100644
--- a/src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H
+++ b/src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H
@@ -54,6 +54,7 @@ public:
~Fl_PostScript_Graphics_Driver();
void close_command(Fl_PostScript_Close_Command cmd){close_cmd_=cmd;}
FILE * file() {return output;}
+ inline void set_cairo(cairo_t *cr) { cairo_ = cr; }
void page(double pw, double ph, int media = 0);
void page(int format);
int start_postscript (int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout);
@@ -79,13 +80,11 @@ public:
int not_clipped(int x, int y, int w, int h) FL_OVERRIDE;
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE;
virtual int has_feature(driver_feature feature_mask) FL_OVERRIDE { return feature_mask & PRINTER; }
-#if !FLTK_USE_CAIRO
// draw image classes without caching them
void draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy);
void draw_pixmap(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
void draw_bitmap(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
void draw_rgb(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
-#endif // !FLTK_USE_CAIRO
};
#else // ! USE_PANGO
diff --git a/src/drivers/PostScript/Fl_PostScript_image.cxx b/src/drivers/PostScript/Fl_PostScript_image.cxx
index c78627727..9b5fe1668 100644
--- a/src/drivers/PostScript/Fl_PostScript_image.cxx
+++ b/src/drivers/PostScript/Fl_PostScript_image.cxx
@@ -70,7 +70,6 @@ void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy
#if USE_PANGO
-#if !FLTK_USE_CAIRO
static void destroy_BGRA(void *data) {
delete[] (uchar*)data;
@@ -182,7 +181,6 @@ void Fl_PostScript_Graphics_Driver::draw_rgb_bitmap_(Fl_Image *img,int XP, int Y
}
}
-#endif // !FLTK_USE_CAIRO
#else // ! USE_PANGO
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx
index 2e59f124c..21eb509bd 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx
@@ -1,7 +1,7 @@
//
// Printing support for Windows for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2020 by Bill Spitzak and others.
+// Copyright 2010-2024 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -15,19 +15,24 @@
//
#include "../GDI/Fl_GDI_Graphics_Driver.H"
+#include <FL/Fl_PDF_File_Surface.H>
#include <FL/Fl_Paged_Device.H>
#include <FL/Fl_Printer.H>
+#include <FL/Fl_Native_File_Chooser.H>
#include <FL/fl_ask.H>
#include <FL/math.h>
#include <FL/fl_draw.H>
+#include <FL/platform.H> // for fl_win32_xid()
+#include <FL/fl_string_functions.h> // fl_strdup()
#include <commdlg.h>
+#include <winspool.h> // DocumentProperties(), OpenPrinter(), ClosePrinter()
extern HWND fl_window;
/** Support for printing on the Windows platform */
class Fl_WinAPI_Printer_Driver : public Fl_Paged_Device {
friend class Fl_Printer;
-private:
+protected:
int abortPrint;
PRINTDLG pd;
HDC hPr;
@@ -83,6 +88,171 @@ static void WIN_SetupPrinterDeviceContext(HDC prHDC)
}
+class Fl_PDF_GDI_File_Surface : public Fl_WinAPI_Printer_Driver
+{
+private:
+ static LPSTR pdf_printer_name_;
+public:
+ char *doc_fname;
+ Fl_PDF_GDI_File_Surface();
+ ~Fl_PDF_GDI_File_Surface() { if (doc_fname) free(doc_fname); }
+ int begin_job(const char *defaultname,
+ char **perr_message = NULL);
+ int begin_job(int, int*, int *, char **) FL_OVERRIDE {return 1;} // don't use
+ int begin_document(const char* outname,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message);
+ void end_job() FL_OVERRIDE;
+};
+
+LPSTR Fl_PDF_GDI_File_Surface::pdf_printer_name_ = _strdup("Microsoft Print to PDF");
+
+Fl_PDF_GDI_File_Surface::Fl_PDF_GDI_File_Surface() {
+ driver(new Fl_GDI_Graphics_Driver());
+ doc_fname = NULL;
+}
+
+Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) {
+ Fl_PDF_GDI_File_Surface *surf = new Fl_PDF_GDI_File_Surface();
+ *pfname = (const char**)&surf->doc_fname;
+ return surf;
+}
+
+int Fl_PDF_File_Surface::begin_job(const char* defaultfilename,
+ char **perr_message) {
+ return ((Fl_PDF_GDI_File_Surface*)platform_surface_)->begin_job(defaultfilename, perr_message);
+}
+
+int Fl_PDF_File_Surface::begin_document(const char* defaultfilename,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message) {
+ return ((Fl_PDF_GDI_File_Surface*)platform_surface_)->begin_document(defaultfilename, format, layout, perr_message);
+}
+
+
+int Fl_PDF_GDI_File_Surface::begin_job(const char *defaultfname, char **perr_message) {
+ int err = 0;
+ abortPrint = FALSE;
+
+ HANDLE hPr2;
+ err = OpenPrinterA(pdf_printer_name_, &hPr2, NULL);
+ if (err == 0) {
+ if (perr_message) {
+ int l = 240;
+ *perr_message = new char[l];
+ snprintf(*perr_message, l,
+ "Class Fl_PDF_File_Surface requires printer '%s' available in Windows 10+.",
+ pdf_printer_name_);
+ }
+ return 1;
+ }
+ HWND hwndOwner = fl_win32_xid(Fl::first_window());
+ LONG count = DocumentPropertiesA(hwndOwner, hPr2, pdf_printer_name_, NULL, NULL, 0);
+ if (count <= 0) { ClosePrinter(hPr2); return 1; }
+ char *buffer = new char[count];
+ DEVMODEA *pDevMode = (DEVMODEA*)buffer;
+ memset(buffer, 0, count);
+ pDevMode->dmSize = count;
+ count = DocumentPropertiesA(hwndOwner, hPr2, pdf_printer_name_, pDevMode, NULL, DM_OUT_BUFFER | DM_IN_PROMPT);
+ ClosePrinter(hPr2);
+ if (count == IDCANCEL || count < 0) { delete[] buffer; return 1; }
+
+ Fl_Native_File_Chooser fnfc;
+ fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
+ fnfc.filter("PDF\t*.pdf\n");
+ if (defaultfname && strlen(defaultfname) > 0) fnfc.preset_file(defaultfname);
+ fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM);
+ if (fnfc.show() == 0) this->hPr = CreateDCA(NULL, pdf_printer_name_, NULL, pDevMode);
+ delete[] buffer;
+ if (!this->hPr) return 1;
+ DOCINFOW di;
+ wchar_t docName [256];
+ wchar_t outName [256];
+ fl_utf8towc("FLTK", 4, docName, 256);
+ fl_utf8towc(fnfc.filename(), strlen(fnfc.filename()), outName, 256);
+ memset(&di, 0, sizeof(DOCINFOW));
+ di.cbSize = sizeof(DOCINFOW);
+ di.lpszDocName = (LPCWSTR)docName;
+ di.lpszOutput = (LPCWSTR)outName;
+ err = StartDocW(this->hPr, &di);
+ if (err <= 0) {
+ DWORD dw = GetLastError();
+ DeleteDC(this->hPr);
+ this->hPr = NULL;
+ if (dw != ERROR_CANCELLED) {
+ if (perr_message) {
+ int l = 40;
+ *perr_message = new char[l];
+ snprintf(*perr_message, l, "Error %lu in StartDoc() call", dw);
+ }
+ return 2;
+ }
+ return 1;
+ }
+ x_offset = 0;
+ y_offset = 0;
+ WIN_SetupPrinterDeviceContext(this->hPr);
+ driver()->gc(this->hPr);
+ doc_fname = fl_strdup(fnfc.filename());
+ return 0;
+}
+
+
+int Fl_PDF_GDI_File_Surface::begin_document(const char* outfname,
+ enum Fl_Paged_Device::Page_Format format,
+ enum Fl_Paged_Device::Page_Layout layout,
+ char **perr_message) {
+ int err = 0;
+ abortPrint = FALSE;
+
+ DEVMODEA inDevMode;
+ memset(&inDevMode, 0, sizeof(DEVMODEA)); inDevMode.dmSize = sizeof(DEVMODEA);
+ inDevMode.dmOrientation = (layout == PORTRAIT ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE);
+ inDevMode.dmPaperSize = (format == A4 ? DMPAPER_A4 : DMPAPER_LETTER);
+ inDevMode.dmFields = DM_ORIENTATION | DM_PAPERSIZE ;
+
+ this->hPr = CreateDCA(NULL, pdf_printer_name_, NULL, &inDevMode);
+ if (!this->hPr) {
+ if (perr_message) {
+ int l = 150;
+ *perr_message = new char[l];
+ snprintf(*perr_message, l, "Class Fl_PDF_File_Surface requires printer '%s'.",
+ pdf_printer_name_);
+ }
+ return 2;
+ }
+ DOCINFOW di;
+ wchar_t docName[256];
+ wchar_t outName[256];
+ fl_utf8towc("FLTK", 4, docName, 256);
+ memset(&di, 0, sizeof(DOCINFOW));
+ di.cbSize = sizeof(DOCINFOW);
+ di.lpszDocName = (LPCWSTR)docName;
+ di.lpszOutput = (LPCWSTR)outName;
+ fl_utf8towc(outfname, strlen(outfname), outName, 256);
+ err = StartDocW(hPr, &di);
+ if (err <= 0) {
+ DWORD dw = GetLastError();
+ DeleteDC(this->hPr);
+ this->hPr = NULL;
+ if (perr_message) {
+ int l = 50;
+ *perr_message = new char[l];
+ snprintf(*perr_message, l, "Error %lu in StartDoc() call", dw);
+ }
+ return 2;
+ }
+ x_offset = 0;
+ y_offset = 0;
+ WIN_SetupPrinterDeviceContext(this->hPr);
+ driver()->gc(this->hPr);
+ doc_fname = fl_strdup(outfname);
+ return 0;
+}
+
+
int Fl_WinAPI_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage, char **perr_message)
// returns 0 iff OK
{
@@ -156,6 +326,19 @@ int Fl_WinAPI_Printer_Driver::begin_job (int pagecount, int *frompage, int *topa
return err;
}
+void Fl_PDF_GDI_File_Surface::end_job(void)
+{
+ if (hPr != NULL) {
+ if (! abortPrint) {
+ if (EndDoc (hPr) <= 0) {
+ fl_message ("Error in EndDoc() call");
+ }
+ int err = DeleteDC (hPr);
+ }
+ hPr = NULL;
+ }
+}
+
void Fl_WinAPI_Printer_Driver::end_job (void)
{
if (hPr != NULL) {
@@ -234,6 +417,7 @@ int Fl_WinAPI_Printer_Driver::begin_page (void)
WIN_SetupPrinterDeviceContext (hPr);
prerr = StartPage (hPr);
if (prerr < 0) {
+ Fl_Surface_Device::pop_current();
fl_alert ("StartPage error %d", prerr);
rsult = 1;
}
@@ -330,3 +514,5 @@ void Fl_WinAPI_Printer_Driver::origin(int *x, int *y)
{
Fl_Paged_Device::origin(x, y);
}
+
+
diff --git a/test/device.cxx b/test/device.cxx
index e039397b6..67e29d239 100644
--- a/test/device.cxx
+++ b/test/device.cxx
@@ -30,6 +30,7 @@
#include <FL/Fl_Image_Surface.H>
#include <FL/Fl_Native_File_Chooser.H>
#include <FL/Fl_SVG_File_Surface.H>
+#include <FL/Fl_PDF_File_Surface.H>
#include "pixmaps/porsche.xpm"
#include "pixmaps/sorceress.xbm"
@@ -523,59 +524,45 @@ void copy(Fl_Widget *, void *data) {
Fl_Surface_Device::pop_current();
}
- if (strcmp(operation, "Fl_Printer") == 0 || strcmp(operation, "Fl_PostScript_File_Device") == 0) {
+ if (strcmp(operation, "Fl_Printer") == 0 || strcmp(operation, "Fl_PostScript_File_Device") == 0
+ || strcmp(operation, "Fl_PDF_File_Surface") == 0) {
Fl_Paged_Device *p;
int err;
char *err_message = NULL;
if (strcmp(operation, "Fl_Printer") == 0) {
p = new Fl_Printer();
err = p->begin_job(1, NULL, NULL, &err_message);
- }
- else {
+ } else if (strcmp(operation, "Fl_PDF_File_Surface") == 0) {
+ p = new Fl_PDF_File_Surface();
+ err = ((Fl_PDF_File_Surface*)p)->begin_job("FLTK.pdf", &err_message);
+ } else {
p = new Fl_PostScript_File_Device();
err = ((Fl_PostScript_File_Device*)p)->start_job(1);
}
if (!err) {
p->begin_page();
- if (target->as_window()) {
- int w, h;
- p->printable_rect(&w, &h);
- p->origin(w/2, h/2);
- p->print_window(target->as_window(), -target->w()/2, -target->h()/2);
- }
- else p->print_widget(target);
+ Fl_Window *win = target->as_window();
+ int target_w = win ? win->decorated_w() : target->w();
+ int target_h = win ? win->decorated_h() : target->h();
+ int w, h;
+ p->printable_rect(&w, &h);
+ float s = 1, s_aux = 1;
+ if (target_w > w)
+ s_aux = float(w) / target_w;
+ if (target_h > h)
+ s = float(h) / target_h;
+ if (s_aux < s) s = s_aux;
+ p->scale(s);
+ p->printable_rect(&w, &h);
+ p->origin(w/2, h/2);
+ if (win) p->draw_decorated_window(win, - target_w/2, - target_h/2);
+ else p->draw(target, - target_w/2, - target_h/2);
p->end_page();
p->end_job();
} else if (err > 1 && err_message) {fl_alert("%s", err_message); delete[] err_message;}
delete p;
}
- if (strcmp(operation, "Fl_EPS_File_Surface") == 0) {
- Fl_Native_File_Chooser fnfc;
- fnfc.title("Save a .eps file");
- fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
- fnfc.filter("EPS\t*.eps\n");
- fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT);
- if (!fnfc.show() ) {
- FILE *eps = fl_fopen(fnfc.filename(), "w");
- if (eps) {
- int ww, wh;
- if (target->as_window()) {
- ww = target->as_window()->decorated_w();
- wh = target->as_window()->decorated_h();
- } else {
- ww = target->w();
- wh = target->h();
- }
- Fl_EPS_File_Surface p(ww, wh, eps);
- if (p.file()) {
- if (target->as_window()) p.draw_decorated_window(target->as_window());
- else p.draw(target);
- }
- }
- }
- }
-
if (strcmp(operation, "Fl_SVG_File_Surface") == 0) {
Fl_Native_File_Chooser fnfc;
fnfc.title("Save a .svg file");
@@ -763,7 +750,7 @@ int main(int argc, char ** argv) {
rb = new Fl_Radio_Round_Button(170,4,150,12, "Fl_Copy_Surface"); rb->callback(operation_cb, NULL); rb->labelsize(12);
rb = new Fl_Radio_Round_Button(5,17,150,12, "Fl_Printer"); rb->callback(operation_cb, NULL); rb->labelsize(12);
rb = new Fl_Radio_Round_Button(170,17,150,12, "Fl_PostScript_File_Device"); rb->callback(operation_cb, NULL); rb->labelsize(12);
- rb = new Fl_Radio_Round_Button(5,30,150,12, "Fl_EPS_File_Surface"); rb->callback(operation_cb, NULL); rb->labelsize(12);
+ rb = new Fl_Radio_Round_Button(5,30,150,12, "Fl_PDF_File_Surface"); rb->callback(operation_cb, NULL); rb->labelsize(12);
rb = new Fl_Radio_Round_Button(170,30,150,12, "Fl_SVG_File_Surface"); rb->callback(operation_cb, NULL); rb->labelsize(12);
rb = new Fl_Radio_Round_Button(5,43,150,12, "fl_capture_window()"); rb->callback(operation_cb, NULL); rb->labelsize(12);
rb = new Fl_Radio_Round_Button(170,43,150,12, "Fl_Image_Surface::mask()"); rb->callback(operation_cb, NULL); rb->labelsize(12);