mirror of https://github.com/fltk/fltk
Implement and document new class Fl_PDF_File_Surface
This commit is contained in:
parent
b402b6a839
commit
9472ff546c
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
|
@ -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:";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue