summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2016-03-19 21:15:34 +0000
committerManolo Gouy <Manolo>2016-03-19 21:15:34 +0000
commit8273b5435460d065ae5ab43ef602e8826bcda8d9 (patch)
treed6ddfe7fd10d7b5e12d9a6fd4477b091de7536af /src/drivers
parente65d66e8852579acdfce9775dd8fd486e8c615dd (diff)
Rename print support files to src/drivers/XXX/Fl_XXX_Printer_Driver.xxx
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11381 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm477
-rw-r--r--src/drivers/Posix/Fl_Posix_Printer_Driver.cxx141
-rw-r--r--src/drivers/PostScript/Fl_PostScript.cxx122
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx327
4 files changed, 947 insertions, 120 deletions
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm b/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
new file mode 100644
index 000000000..525e545c0
--- /dev/null
+++ b/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
@@ -0,0 +1,477 @@
+//
+// "$Id$"
+//
+// Mac OS X-specific printing support (objective-c++) for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2010-2016 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:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems to:
+//
+// http://www.fltk.org/str.php
+//
+
+#include <FL/Fl_Printer.H>
+#include <FL/Fl_Shared_Image.H>
+#include <FL/Fl_Window_Driver.H>
+#include "../Quartz/Fl_Quartz_Printer_Graphics_Driver.H"
+
+#include <FL/Fl.H>
+#include <FL/fl_ask.H>
+#include <FL/fl_draw.H>
+#import <Cocoa/Cocoa.h>
+
+typedef OSStatus (*PMSessionSetDocumentFormatGeneration_type)(
+ PMPrintSession printSession,
+ CFStringRef docFormat,
+ CFArrayRef graphicsContextTypes,
+ CFTypeRef options);
+typedef OSStatus (*PMSessionBeginDocumentNoDialog_type)(
+ PMPrintSession printSession,
+ PMPrintSettings printSettings,
+ PMPageFormat pageFormat);
+typedef OSStatus
+(*PMSessionGetGraphicsContext_type)(
+ PMPrintSession printSession,
+ CFStringRef graphicsContextType,
+ void ** graphicsContext);
+
+extern void fl_quartz_restore_line_style_(CGContextRef gc);
+
+
+/** Support for printing on the Apple OS X platform */
+class Fl_Cocoa_Printer_Driver : public Fl_Paged_Device {
+ friend class Fl_Paged_Device;
+private:
+ float scale_x;
+ float scale_y;
+ float angle; // rotation angle in radians
+ PMPrintSession printSession;
+ PMPageFormat pageFormat;
+ PMPrintSettings printSettings;
+ Fl_Cocoa_Printer_Driver(void);
+ int start_job(int pagecount, int *frompage = NULL, int *topage = NULL);
+ int start_page (void);
+ int printable_rect(int *w, int *h);
+ void margins(int *left, int *top, int *right, int *bottom);
+ void origin(int *x, int *y);
+ void origin(int x, int y);
+ void scale (float scale_x, float scale_y = 0.);
+ void rotate(float angle);
+ void translate(int x, int y);
+ void untranslate(void);
+ int end_page (void);
+ void end_job (void);
+ void draw_decorated_window(Fl_Window *win, int x_offset, int y_offset);
+ void print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x, int delta_y);
+ ~Fl_Cocoa_Printer_Driver(void);
+};
+
+
+Fl_Cocoa_Printer_Driver::Fl_Cocoa_Printer_Driver(void)
+{
+ x_offset = 0;
+ y_offset = 0;
+ scale_x = scale_y = 1.;
+ driver(new Fl_Quartz_Printer_Graphics_Driver);
+}
+
+Fl_Paged_Device* Fl_Paged_Device::newPrinterDriver(void)
+{
+ return new Fl_Cocoa_Printer_Driver();
+}
+
+Fl_Cocoa_Printer_Driver::~Fl_Cocoa_Printer_Driver(void) {
+ delete driver();
+}
+
+
+int Fl_Cocoa_Printer_Driver::start_job (int pagecount, int *frompage, int *topage)
+//printing using a Quartz graphics context
+//returns 0 iff OK
+{
+ OSStatus status = 0;
+ fl_open_display();
+ Fl_X::q_release_context();
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if (fl_mac_os_version >= 100500) {
+ NSPrintInfo *info = [NSPrintInfo sharedPrintInfo];
+ NSPrintPanel *panel = [NSPrintPanel printPanel];
+ //from 10.5
+ [panel setOptions:NSPrintPanelShowsCopies | NSPrintPanelShowsPageRange | NSPrintPanelShowsPageSetupAccessory];
+ NSInteger retval = [panel runModalWithPrintInfo:info];//from 10.5
+ if(retval != NSOKButton) {
+ Fl_Window *w = Fl::first_window();
+ if (w) w->show();
+ return 1;
+ }
+ printSession = (PMPrintSession)[info PMPrintSession];//from 10.5
+ pageFormat = (PMPageFormat)[info PMPageFormat];//from 10.5
+ printSettings = (PMPrintSettings)[info PMPrintSettings];//from 10.5
+ UInt32 from32, to32;
+ PMGetFirstPage(printSettings, &from32);
+ if (frompage) *frompage = (int)from32;
+ PMGetLastPage(printSettings, &to32);
+ if (topage) {
+ *topage = (int)to32;
+ if (*topage > pagecount && pagecount > 0) *topage = pagecount;
+ }
+ status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4
+ }
+ else
+#endif
+ {
+#if !__LP64__
+ Boolean accepted;
+ status = PMCreateSession(&printSession);
+ if (status != noErr) return 1;
+ status = PMCreatePageFormat(&pageFormat);
+ status = PMSessionDefaultPageFormat(printSession, pageFormat);
+ if (status != noErr) return 1;
+ // get pointer to the PMSessionPageSetupDialog Carbon function
+ typedef OSStatus (*dialog_f)(PMPrintSession, PMPageFormat, Boolean *);
+ static dialog_f f = NULL;
+ if (!f) f = (dialog_f)Fl_X::get_carbon_function("PMSessionPageSetupDialog");
+ status = (*f)(printSession, pageFormat, &accepted);
+ if (status != noErr || !accepted) {
+ Fl::first_window()->show();
+ return 1;
+ }
+ status = PMCreatePrintSettings(&printSettings);
+ if (status != noErr || printSettings == kPMNoPrintSettings) return 1;
+ status = PMSessionDefaultPrintSettings (printSession, printSettings);
+ if (status != noErr) return 1;
+ PMSetPageRange(printSettings, 1, (UInt32)kPMPrintAllPages);
+ // get pointer to the PMSessionPrintDialog Carbon function
+ typedef OSStatus (*dialog_f2)(PMPrintSession, PMPrintSettings, PMPageFormat, Boolean *);
+ static dialog_f2 f2 = NULL;
+ if (!f2) f2 = (dialog_f2)Fl_X::get_carbon_function("PMSessionPrintDialog");
+ status = (*f2)(printSession, printSettings, pageFormat, &accepted);
+ if (!accepted) status = kPMCancel;
+ if (status != noErr) {
+ Fl::first_window()->show();
+ return 1;
+ }
+ UInt32 from32, to32;
+ PMGetFirstPage(printSettings, &from32);
+ if (frompage) *frompage = (int)from32;
+ PMGetLastPage(printSettings, &to32);
+ if (topage) *topage = (int)to32;
+ if(topage && *topage > pagecount) *topage = pagecount;
+ CFStringRef mystring[1];
+ mystring[0] = kPMGraphicsContextCoreGraphics;
+ CFArrayRef array = CFArrayCreate(NULL, (const void **)mystring, 1, &kCFTypeArrayCallBacks);
+ PMSessionSetDocumentFormatGeneration_type PMSessionSetDocumentFormatGeneration =
+ (PMSessionSetDocumentFormatGeneration_type)Fl_X::get_carbon_function("PMSessionSetDocumentFormatGeneration");
+ status = PMSessionSetDocumentFormatGeneration(printSession, kPMDocumentFormatDefault, array, NULL);
+ CFRelease(array);
+ PMSessionBeginDocumentNoDialog_type PMSessionBeginDocumentNoDialog =
+ (PMSessionBeginDocumentNoDialog_type)Fl_X::get_carbon_function("PMSessionBeginDocumentNoDialog");
+ status = PMSessionBeginDocumentNoDialog(printSession, printSettings, pageFormat);
+#endif //__LP64__
+ }
+
+ if (status != noErr) return 1;
+ y_offset = x_offset = 0;
+ this->set_current();
+ return 0;
+}
+
+void Fl_Cocoa_Printer_Driver::margins(int *left, int *top, int *right, int *bottom)
+{
+ PMPaper paper;
+ PMGetPageFormatPaper(pageFormat, &paper);
+ PMOrientation orientation;
+ PMGetOrientation(pageFormat, &orientation);
+ PMPaperMargins margins;
+ PMPaperGetMargins(paper, &margins);
+ if(orientation == kPMPortrait) {
+ if (left) *left = (int)(margins.left / scale_x + 0.5);
+ if (top) *top = (int)(margins.top / scale_y + 0.5);
+ if (right) *right = (int)(margins.right / scale_x + 0.5);
+ if (bottom) *bottom = (int)(margins.bottom / scale_y + 0.5);
+ }
+ else {
+ if (left) *left = (int)(margins.top / scale_x + 0.5);
+ if (top) *top = (int)(margins.left / scale_y + 0.5);
+ if (right) *right = (int)(margins.bottom / scale_x + 0.5);
+ if (bottom) *bottom = (int)(margins.right / scale_y + 0.5);
+ }
+}
+
+int Fl_Cocoa_Printer_Driver::printable_rect(int *w, int *h)
+//returns 0 iff OK
+{
+ OSStatus status;
+ PMRect pmRect;
+ int x, y;
+
+ status = PMGetAdjustedPageRect(pageFormat, &pmRect);
+ if (status != noErr) return 1;
+
+ x = (int)pmRect.left;
+ y = (int)pmRect.top;
+ *w = int((int)(pmRect.right - x) / scale_x + 1);
+ *h = int((int)(pmRect.bottom - y) / scale_y + 1);
+ return 0;
+}
+
+void Fl_Cocoa_Printer_Driver::origin(int x, int y)
+{
+ x_offset = x;
+ y_offset = y;
+ CGContextRef gc = (CGContextRef)driver()->gc();
+ CGContextRestoreGState(gc);
+ CGContextRestoreGState(gc);
+ CGContextSaveGState(gc);
+ CGContextScaleCTM(gc, scale_x, scale_y);
+ CGContextTranslateCTM(gc, x, y);
+ CGContextRotateCTM(gc, angle);
+ CGContextSaveGState(gc);
+}
+
+void Fl_Cocoa_Printer_Driver::scale (float s_x, float s_y)
+{
+ if (s_y == 0.) s_y = s_x;
+ scale_x = s_x;
+ scale_y = s_y;
+ CGContextRef gc = (CGContextRef)driver()->gc();
+ CGContextRestoreGState(gc);
+ CGContextRestoreGState(gc);
+ CGContextSaveGState(gc);
+ CGContextScaleCTM(gc, scale_x, scale_y);
+ CGContextRotateCTM(gc, angle);
+ x_offset = y_offset = 0;
+ CGContextSaveGState(gc);
+}
+
+void Fl_Cocoa_Printer_Driver::rotate (float rot_angle)
+{
+ angle = - rot_angle * M_PI / 180.;
+ CGContextRef gc = (CGContextRef)driver()->gc();
+ CGContextRestoreGState(gc);
+ CGContextRestoreGState(gc);
+ CGContextSaveGState(gc);
+ CGContextScaleCTM(gc, scale_x, scale_y);
+ CGContextTranslateCTM(gc, x_offset, y_offset);
+ CGContextRotateCTM(gc, angle);
+ CGContextSaveGState(gc);
+}
+
+void Fl_Cocoa_Printer_Driver::translate(int x, int y)
+{
+ CGContextRef gc = (CGContextRef)driver()->gc();
+ CGContextSaveGState(gc);
+ CGContextTranslateCTM(gc, x, y );
+ CGContextSaveGState(gc);
+}
+
+void Fl_Cocoa_Printer_Driver::untranslate(void)
+{
+ CGContextRef gc = (CGContextRef)driver()->gc();
+ CGContextRestoreGState(gc);
+ CGContextRestoreGState(gc);
+}
+
+int Fl_Cocoa_Printer_Driver::start_page (void)
+{
+ OSStatus status = PMSessionBeginPageNoDialog(printSession, pageFormat, NULL);
+ CGContextRef gc;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if ( &PMSessionGetCGGraphicsContext != NULL ) {
+ status = PMSessionGetCGGraphicsContext(printSession, &gc);
+ }
+ else
+#endif
+ {
+#if ! __LP64_
+ PMSessionGetGraphicsContext_type PMSessionGetGraphicsContext =
+ (PMSessionGetGraphicsContext_type)Fl_X::get_carbon_function("PMSessionGetGraphicsContext");
+ status = PMSessionGetGraphicsContext(printSession, NULL, (void **)&gc);
+#endif
+ }
+ driver()->gc(gc);
+ set_current();
+ PMRect pmRect;
+ float win_scale_x, win_scale_y;
+
+ PMPaper paper;
+ PMGetPageFormatPaper(pageFormat, &paper);
+ PMPaperMargins margins;
+ PMPaperGetMargins(paper, &margins);
+ PMOrientation orientation;
+ PMGetOrientation(pageFormat, &orientation);
+
+ status = PMGetAdjustedPageRect(pageFormat, &pmRect);
+ double h = pmRect.bottom - pmRect.top;
+ x_offset = 0;
+ y_offset = 0;
+ angle = 0;
+ scale_x = scale_y = 1;
+ win_scale_x = win_scale_y = 1;
+ if(orientation == kPMPortrait)
+ CGContextTranslateCTM(gc, margins.left, margins.bottom + h);
+ else
+ CGContextTranslateCTM(gc, margins.top, margins.right + h);
+ CGContextScaleCTM(gc, win_scale_x, - win_scale_y);
+ fl_quartz_restore_line_style_(gc);
+ CGContextSetShouldAntialias(gc, false);
+ CGContextSaveGState(gc);
+ CGContextSaveGState(gc);
+ fl_line_style(FL_SOLID);
+ fl_window = (Window)1; // TODO: something better
+ fl_clip_region(0);
+ return status != noErr;
+}
+
+int Fl_Cocoa_Printer_Driver::end_page (void)
+{
+ CGContextRef gc = (CGContextRef)driver()->gc();
+ CGContextFlush(gc);
+ CGContextRestoreGState(gc);
+ CGContextRestoreGState(gc);
+ OSStatus status = PMSessionEndPageNoDialog(printSession);
+ gc = NULL;
+ return status != noErr;
+}
+
+void Fl_Cocoa_Printer_Driver::end_job (void)
+{
+ OSStatus status;
+
+ status = PMSessionError(printSession);
+ if (status != noErr) {
+ fl_alert ("PM Session error %d", (int)status);
+ }
+ PMSessionEndDocumentNoDialog(printSession);
+#if !__LP64__
+ if (fl_mac_os_version < 100500) {
+ PMRelease(printSettings);
+ PMRelease(pageFormat);
+ PMRelease(printSession);
+ }
+#endif
+ Fl_Display_Device::display_device()->set_current();
+ driver()->gc(0);
+ Fl_Window *w = Fl::first_window();
+ if (w) w->show();
+}
+
+// version that prints at high res if using a retina display
+void Fl_Cocoa_Printer_Driver::print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x, int delta_y)
+{
+ Fl_Surface_Device *current = Fl_Surface_Device::surface();
+ Fl_Display_Device::display_device()->set_current();
+ Fl_Window *save_front = Fl::first_window();
+ win->show();
+ Fl::check();
+ CGImageRef img = Fl_X::CGImage_from_window_rect(win, x, y, w, h);
+ if (save_front != win) save_front->show();
+ current->set_current();
+ ((Fl_Quartz_Graphics_Driver*)driver())->draw_CGImage(img,delta_x, delta_y, w, h, 0,0,w,h);
+ CFRelease(img);
+}
+
+void Fl_Cocoa_Printer_Driver::origin(int *x, int *y)
+{
+ Fl_Paged_Device::origin(x, y);
+}
+
+void Fl_Cocoa_Printer_Driver::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset)
+{
+ if (!win->shown() || win->parent() || !win->border() || !win->visible()) {
+ this->print_widget(win, x_offset, y_offset);
+ return;
+ }
+ int bt = win->decorated_h() - win->h();
+ BOOL to_quartz = (this->driver()->has_feature(Fl_Graphics_Driver::NATIVE));
+ CALayer *layer = nil;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ if (fl_mac_os_version >= 101000) layer = [[[fl_xid(win) standardWindowButton:NSWindowCloseButton] superview] layer];
+#endif
+
+ if (layer) { // if title bar uses a layer
+ if (to_quartz) { // to Quartz printer
+ CGContextRef gc = (CGContextRef)driver()->gc();
+ CGContextSaveGState(gc);
+ CGContextTranslateCTM(gc, x_offset - 0.5, y_offset + bt - 0.5);
+ CGContextScaleCTM(gc, 1, -1);
+ Fl_X::draw_layer_to_context(layer, gc, win->w(), bt);
+ CGContextRestoreGState(gc);
+ }
+ else {
+ CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB ();
+ CGContextRef gc = CGBitmapContextCreate(NULL, 2*win->w(), 2*bt, 8, 0, cspace, kCGImageAlphaPremultipliedLast);
+ CGColorSpaceRelease(cspace);
+ CGContextScaleCTM(gc, 2, 2);
+ Fl_X::draw_layer_to_context(layer, gc, win->w(), bt);
+ Fl_RGB_Image *image = new Fl_RGB_Image((const uchar*)CGBitmapContextGetData(gc), 2*win->w(), 2*bt, 4,
+ CGBitmapContextGetBytesPerRow(gc)); // 10.2
+ int ori_x, ori_y;
+ origin(&ori_x, &ori_y);
+ scale(0.5);
+ origin(2*ori_x, 2*ori_y);
+ image->draw(2*x_offset, 2*y_offset); // draw title bar as double resolution image
+ scale(1);
+ origin(ori_x, ori_y);
+ delete image;
+ CGContextRelease(gc);
+ }
+ this->print_widget(win, x_offset, y_offset + bt);
+ return;
+ }
+ Fl_Display_Device::display_device()->set_current(); // send win to front and make it current
+ NSString *title = [fl_xid(win) title];
+ [title retain];
+ [fl_xid(win) setTitle:@""]; // temporarily set a void window title
+ win->show();
+ Fl::check();
+ // capture the window title bar with no title
+ Fl_Shared_Image *top, *left, *bottom, *right;
+ win->driver()->capture_titlebar_and_borders(top, left, bottom, right);
+ [fl_xid(win) setTitle:title]; // put back the window title
+ this->set_current(); // back to the Fl_Paged_Device
+ top->draw(x_offset, y_offset); // print the title bar
+ top->release();
+ if (win->label()) { // print the window title
+ const int skip = 65; // approx width of the zone of the 3 window control buttons
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (fl_mac_os_version >= 100400 && to_quartz) { // use Cocoa string drawing with exact title bar font
+ // the exact font is LucidaGrande 13 pts (and HelveticaNeueDeskInterface-Regular with 10.10)
+ NSGraphicsContext *current = [NSGraphicsContext currentContext];
+ [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:driver()->gc() flipped:YES]];//10.4
+ NSDictionary *attr = [NSDictionary dictionaryWithObject:[NSFont titleBarFontOfSize:0]
+ forKey:NSFontAttributeName];
+ NSSize size = [title sizeWithAttributes:attr];
+ int x = x_offset + win->w()/2 - size.width/2;
+ if (x < x_offset+skip) x = x_offset+skip;
+ NSRect r = NSMakeRect(x, y_offset+bt/2+4, win->w() - skip, bt);
+ [[NSGraphicsContext currentContext] setShouldAntialias:YES];
+ [title drawWithRect:r options:(NSStringDrawingOptions)0 attributes:attr]; // 10.4
+ [[NSGraphicsContext currentContext] setShouldAntialias:NO];
+ [NSGraphicsContext setCurrentContext:current];
+ }
+ else
+#endif
+ {
+ fl_font(FL_HELVETICA, 14);
+ fl_color(FL_BLACK);
+ int x = x_offset + win->w()/2 - fl_width(win->label())/2;
+ if (x < x_offset+skip) x = x_offset+skip;
+ fl_push_clip(x_offset, y_offset, win->w(), bt);
+ fl_draw(win->label(), x, y_offset+bt/2+4);
+ fl_pop_clip();
+ }
+ }
+ [title release];
+ this->print_widget(win, x_offset, y_offset + bt); // print the window inner part
+}
+
+//
+// End of "$Id$".
+//
diff --git a/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx b/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx
new file mode 100644
index 000000000..f06bef7f9
--- /dev/null
+++ b/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx
@@ -0,0 +1,141 @@
+//
+// "$Id: Fl_Posix_Printer_Driver.cxx 11364 2016-03-18 18:20:11Z manolo $"
+//
+// PostScript priting support for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2010-2016 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:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems to:
+//
+// http://www.fltk.org/str.php
+//
+
+#include "../../src/config_lib.h"
+
+#if defined(FL_CFG_PRN_PS)
+
+#include <FL/Fl_PostScript.H>
+#include <FL/Fl_Printer.H>
+#include <FL/fl_ask.H>
+
+#include <src/print_panel.cxx>
+
+/** Support for printing on the Unix/Linux platform */
+class Fl_Posix_Printer_Driver : public Fl_PostScript_File_Device {
+ virtual int start_job(int pagecount, int *frompage = NULL, int *topage = NULL);
+};
+
+Fl_Paged_Device* Fl_Paged_Device::newPrinterDriver(void)
+{
+ return new Fl_Posix_Printer_Driver();
+}
+
+/** Starts a print job. */
+int Fl_Posix_Printer_Driver::start_job(int pages, int *firstpage, int *lastpage) {
+ enum Fl_Paged_Device::Page_Format format;
+ enum Fl_Paged_Device::Page_Layout layout;
+
+ // first test version for print dialog
+ if (!print_panel) make_print_panel();
+ printing_style style = print_load();
+ print_selection->deactivate();
+ print_all->setonly();
+ print_all->do_callback();
+ print_from->value("1");
+ { char tmp[10]; snprintf(tmp, sizeof(tmp), "%d", pages); print_to->value(tmp); }
+ print_panel->show(); // this is modal
+ while (print_panel->shown()) Fl::wait();
+
+ if (!print_start) // user clicked cancel
+ return 1;
+
+ // get options
+
+ switch (print_page_size->value()) {
+ case 0:
+ format = Fl_Paged_Device::LETTER;
+ break;
+ case 2:
+ format = Fl_Paged_Device::LEGAL;
+ break;
+ case 3:
+ format = Fl_Paged_Device::EXECUTIVE;
+ break;
+ case 4:
+ format = Fl_Paged_Device::A3;
+ break;
+ case 5:
+ format = Fl_Paged_Device::A5;
+ break;
+ case 6:
+ format = Fl_Paged_Device::B5;
+ break;
+ case 7:
+ format = Fl_Paged_Device::ENVELOPE;
+ break;
+ case 8:
+ format = Fl_Paged_Device::DLE;
+ break;
+ default:
+ format = Fl_Paged_Device::A4;
+ }
+
+ { // page range choice
+ int from = 1, to = pages;
+ if (print_pages->value()) {
+ sscanf(print_from->value(), "%d", &from);
+ sscanf(print_to->value(), "%d", &to);
+ }
+ if (from < 1) from = 1;
+ if (to > pages) to = pages;
+ if (to < from) to = from;
+ if (firstpage) *firstpage = from;
+ if (lastpage) *lastpage = to;
+ if (pages > 0) pages = to - from + 1;
+ }
+
+ if (print_output_mode[0]->value()) layout = Fl_Paged_Device::PORTRAIT;
+ else if (print_output_mode[1]->value()) layout = Fl_Paged_Device::LANDSCAPE;
+ else if (print_output_mode[2]->value()) layout = Fl_Paged_Device::PORTRAIT;
+ else layout = Fl_Paged_Device::LANDSCAPE;
+
+ int print_pipe = print_choice->value(); // 0 = print to file, >0 = printer (pipe)
+
+ const char *media = print_page_size->text(print_page_size->value());
+ const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data();
+ if (!print_pipe) printer = "<File>";
+
+ if (!print_pipe) // fall back to file printing
+ return Fl_PostScript_File_Device::start_job (pages, format, layout);
+
+ // Print: pipe the output into the lp command...
+
+ char command[1024];
+ if (style == SystemV) snprintf(command, sizeof(command), "lp -s -d %s -n %d -t '%s' -o media=%s",
+ printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5), "FLTK", media);
+ else snprintf(command, sizeof(command), "lpr -h -P%s -#%d -T FLTK ",
+ printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5));
+
+ Fl_PostScript_Graphics_Driver *ps = driver();
+ ps->output = popen(command, "w");
+ if (!ps->output) {
+ fl_alert("could not run command: %s\n",command);
+ return 1;
+ }
+ ps->close_command(pclose);
+ this->set_current();
+ return ps->start_postscript(pages, format, layout); // start printing
+}
+
+#endif // defined(FL_CFG_PRN_PS)
+
+
+//
+// End of "$Id: Fl_Posix_Printer_Driver.cxx 11364 2016-03-18 18:20:11Z manolo $".
+//
diff --git a/src/drivers/PostScript/Fl_PostScript.cxx b/src/drivers/PostScript/Fl_PostScript.cxx
index b3e7d214d..7de93e48c 100644
--- a/src/drivers/PostScript/Fl_PostScript.cxx
+++ b/src/drivers/PostScript/Fl_PostScript.cxx
@@ -1,7 +1,7 @@
//
// "$Id$"
//
-// PostScript device support for the Fast Light Tool Kit (FLTK).
+// Classes Fl_PostScript_File_Device and Fl_PostScript_Graphics_Driver for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-2016 by Bill Spitzak and others.
//
@@ -16,8 +16,7 @@
// http://www.fltk.org/str.php
//
-#include <FL/Fl_Printer.H>
-#include <src/config_lib.h>
+#include <config.h>
#include <FL/Fl.H>
#include <FL/fl_ask.H>
#include <FL/fl_draw.H>
@@ -171,10 +170,6 @@ int Fl_PostScript_Graphics_Driver::clocale_printf(const char *format, ...)
#ifndef FL_DOXYGEN
-#if ! (defined(__APPLE__) || defined(WIN32) ) // PORTME: Fl_Surface_Driver - platform PostScript
-# include <src/print_panel.cxx>
-#endif
-
// Prolog string
static const char * prolog =
@@ -1557,119 +1552,6 @@ void Fl_PostScript_File_Device::end_job (void)
#endif // FL_DOXYGEN
-
-#if defined(FL_CFG_PRN_PS)
-
-/** Support for printing on the Unix/Linux platform */
-class Fl_Posix_Printer_Driver : public Fl_PostScript_File_Device {
- virtual int start_job(int pagecount, int *frompage = NULL, int *topage = NULL);
-};
-
-Fl_Paged_Device* Fl_Paged_Device::newPrinterDriver(void)
-{
- return new Fl_Posix_Printer_Driver();
-}
-
-/** Starts a print job. */
-int Fl_Posix_Printer_Driver::start_job(int pages, int *firstpage, int *lastpage) {
- enum Fl_Paged_Device::Page_Format format;
- enum Fl_Paged_Device::Page_Layout layout;
-
- // first test version for print dialog
- if (!print_panel) make_print_panel();
- printing_style style = print_load();
- print_selection->deactivate();
- print_all->setonly();
- print_all->do_callback();
- print_from->value("1");
- { char tmp[10]; snprintf(tmp, sizeof(tmp), "%d", pages); print_to->value(tmp); }
- print_panel->show(); // this is modal
- while (print_panel->shown()) Fl::wait();
-
- if (!print_start) // user clicked cancel
- return 1;
-
- // get options
-
- switch (print_page_size->value()) {
- case 0:
- format = Fl_Paged_Device::LETTER;
- break;
- case 2:
- format = Fl_Paged_Device::LEGAL;
- break;
- case 3:
- format = Fl_Paged_Device::EXECUTIVE;
- break;
- case 4:
- format = Fl_Paged_Device::A3;
- break;
- case 5:
- format = Fl_Paged_Device::A5;
- break;
- case 6:
- format = Fl_Paged_Device::B5;
- break;
- case 7:
- format = Fl_Paged_Device::ENVELOPE;
- break;
- case 8:
- format = Fl_Paged_Device::DLE;
- break;
- default:
- format = Fl_Paged_Device::A4;
- }
-
- { // page range choice
- int from = 1, to = pages;
- if (print_pages->value()) {
- sscanf(print_from->value(), "%d", &from);
- sscanf(print_to->value(), "%d", &to);
- }
- if (from < 1) from = 1;
- if (to > pages) to = pages;
- if (to < from) to = from;
- if (firstpage) *firstpage = from;
- if (lastpage) *lastpage = to;
- if (pages > 0) pages = to - from + 1;
- }
-
- if (print_output_mode[0]->value()) layout = Fl_Paged_Device::PORTRAIT;
- else if (print_output_mode[1]->value()) layout = Fl_Paged_Device::LANDSCAPE;
- else if (print_output_mode[2]->value()) layout = Fl_Paged_Device::PORTRAIT;
- else layout = Fl_Paged_Device::LANDSCAPE;
-
- int print_pipe = print_choice->value(); // 0 = print to file, >0 = printer (pipe)
-
- const char *media = print_page_size->text(print_page_size->value());
- const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data();
- if (!print_pipe) printer = "<File>";
-
- if (!print_pipe) // fall back to file printing
- return Fl_PostScript_File_Device::start_job (pages, format, layout);
-
- // Print: pipe the output into the lp command...
-
- char command[1024];
- if (style == SystemV) snprintf(command, sizeof(command), "lp -s -d %s -n %d -t '%s' -o media=%s",
- printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5), "FLTK", media);
- else snprintf(command, sizeof(command), "lpr -h -P%s -#%d -T FLTK ",
- printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5));
-
- Fl_PostScript_Graphics_Driver *ps = driver();
- ps->output = popen(command, "w");
- if (!ps->output) {
- fl_alert("could not run command: %s\n",command);
- return 1;
- }
- ps->close_command(pclose);
- this->set_current();
- return ps->start_postscript(pages, format, layout); // start printing
-}
-
-#endif // defined(FL_CFG_PRN_PS)
-
-
//
// End of "$Id$".
//
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx
new file mode 100644
index 000000000..0e4d53f8b
--- /dev/null
+++ b/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx
@@ -0,0 +1,327 @@
+//
+// "$Id$"
+//
+// Support for WIN32 printing for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2010-2016 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:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+#ifdef WIN32
+
+#include "../GDI/Fl_GDI_Graphics_Driver.H"
+
+#include <FL/Fl_Printer.H>
+
+
+#include <FL/fl_ask.H>
+#include <FL/math.h>
+#include <FL/fl_draw.H>
+
+extern HWND fl_window;
+
+/** Support for printing on the MSWindows platform */
+class Fl_WinAPI_Printer_Driver : public Fl_Paged_Device {
+ friend class Fl_Paged_Device;
+private:
+ int abortPrint;
+ PRINTDLG pd;
+ HDC hPr;
+ int prerr;
+ int left_margin;
+ int top_margin;
+ void absolute_printable_rect(int *x, int *y, int *w, int *h);
+ Fl_WinAPI_Printer_Driver(void);
+ int start_job(int pagecount, int *frompage = NULL, int *topage = NULL);
+ int start_page (void);
+ int printable_rect(int *w, int *h);
+ void margins(int *left, int *top, int *right, int *bottom);
+ void origin(int *x, int *y);
+ void origin(int x, int y);
+ void scale (float scale_x, float scale_y = 0.);
+ void rotate(float angle);
+ void translate(int x, int y);
+ void untranslate(void);
+ int end_page (void);
+ void end_job (void);
+ ~Fl_WinAPI_Printer_Driver(void);
+};
+
+Fl_WinAPI_Printer_Driver::Fl_WinAPI_Printer_Driver(void) : Fl_Paged_Device() {
+ hPr = NULL;
+ driver(new Fl_GDI_Printer_Graphics_Driver);
+}
+
+Fl_Paged_Device* Fl_Paged_Device::newPrinterDriver(void)
+{
+ return new Fl_WinAPI_Printer_Driver();
+}
+
+
+Fl_WinAPI_Printer_Driver::~Fl_WinAPI_Printer_Driver(void) {
+ if (hPr) end_job();
+ delete driver();
+}
+
+static void WIN_SetupPrinterDeviceContext(HDC prHDC)
+{
+ if ( !prHDC ) return;
+
+ fl_window = 0;
+ SetGraphicsMode(prHDC, GM_ADVANCED); // to allow for rotations
+ SetMapMode(prHDC, MM_ANISOTROPIC);
+ SetTextAlign(prHDC, TA_BASELINE|TA_LEFT);
+ SetBkMode(prHDC, TRANSPARENT);
+ // this matches 720 logical units to the number of device units in 10 inches of paper
+ // thus the logical unit is the point (= 1/72 inch)
+ SetWindowExtEx(prHDC, 720, 720, NULL);
+ SetViewportExtEx(prHDC, 10*GetDeviceCaps(prHDC, LOGPIXELSX), 10*GetDeviceCaps(prHDC, LOGPIXELSY), NULL);
+}
+
+
+int Fl_WinAPI_Printer_Driver::start_job (int pagecount, int *frompage, int *topage)
+// returns 0 iff OK
+{
+ if (pagecount == 0) pagecount = 10000;
+ DWORD commdlgerr;
+ DOCINFO di;
+ char docName [256];
+ int err = 0;
+
+ abortPrint = FALSE;
+ memset (&pd, 0, sizeof (PRINTDLG));
+ pd.lStructSize = sizeof (PRINTDLG);
+ pd.hwndOwner = GetForegroundWindow();
+ pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | PD_NOSELECTION;
+ pd.nMinPage = 1;
+ pd.nMaxPage = pagecount;
+ BOOL b = PrintDlg (&pd);
+ if (pd.hwndOwner) { // restore the correct state of mouse buttons and keyboard modifier keys (STR #3221)
+ WNDPROC windproc = (WNDPROC)GetWindowLongPtrW(pd.hwndOwner, GWLP_WNDPROC);
+ CallWindowProc(windproc, pd.hwndOwner, WM_ACTIVATEAPP, 1, 0);
+ }
+ if (b != 0) {
+ hPr = pd.hDC;
+ if (hPr != NULL) {
+ strcpy (docName, "FLTK");
+ memset(&di, 0, sizeof(DOCINFO));
+ di.cbSize = sizeof (DOCINFO);
+ di.lpszDocName = (LPCSTR) docName;
+ prerr = StartDoc (hPr, &di);
+ if (prerr < 1) {
+ abortPrint = TRUE;
+ //fl_alert ("StartDoc error %d", prerr);
+ err = 1;
+ }
+ } else {
+ commdlgerr = CommDlgExtendedError ();
+ fl_alert ("Unable to create print context, error %lu",
+ (unsigned long) commdlgerr);
+ err = 1;
+ }
+ } else {
+ err = 1;
+ }
+ if(!err) {
+ if((pd.Flags & PD_PAGENUMS) != 0 ) {
+ if (frompage) *frompage = pd.nFromPage;
+ if (topage) *topage = pd.nToPage;
+ }
+ else {
+ if (frompage) *frompage = 1;
+ if (topage) *topage = pagecount;
+ }
+ x_offset = 0;
+ y_offset = 0;
+ WIN_SetupPrinterDeviceContext (hPr);
+ driver()->gc(hPr);
+ this->set_current();
+ }
+ return err;
+}
+
+void Fl_WinAPI_Printer_Driver::end_job (void)
+{
+ Fl_Display_Device::display_device()->set_current();
+ if (hPr != NULL) {
+ if (! abortPrint) {
+ prerr = EndDoc (hPr);
+ if (prerr < 0) {
+ fl_alert ("EndDoc error %d", prerr);
+ }
+ }
+ DeleteDC (hPr);
+ if (pd.hDevMode != NULL) {
+ GlobalFree (pd.hDevMode);
+ }
+ if (pd.hDevNames != NULL) {
+ GlobalFree (pd.hDevNames);
+ }
+ }
+ hPr = NULL;
+}
+
+void Fl_WinAPI_Printer_Driver::absolute_printable_rect(int *x, int *y, int *w, int *h)
+{
+ POINT physPageSize;
+ POINT pixelsPerInch;
+ XFORM transform;
+
+ if (hPr == NULL) return;
+ HDC gc = (HDC)driver()->gc();
+ GetWorldTransform(gc, &transform);
+ ModifyWorldTransform(gc, NULL, MWT_IDENTITY);
+ SetWindowOrgEx(gc, 0, 0, NULL);
+
+ physPageSize.x = GetDeviceCaps(hPr, HORZRES);
+ physPageSize.y = GetDeviceCaps(hPr, VERTRES);
+ DPtoLP(hPr, &physPageSize, 1);
+ *w = physPageSize.x + 1;
+ *h = physPageSize.y + 1;
+ pixelsPerInch.x = GetDeviceCaps(hPr, LOGPIXELSX);
+ pixelsPerInch.y = GetDeviceCaps(hPr, LOGPIXELSY);
+ DPtoLP(hPr, &pixelsPerInch, 1);
+ left_margin = (pixelsPerInch.x / 4);
+ *w -= (pixelsPerInch.x / 2);
+ top_margin = (pixelsPerInch.y / 4);
+ *h -= (pixelsPerInch.y / 2);
+
+ *x = left_margin;
+ *y = top_margin;
+ origin(x_offset, y_offset);
+ SetWorldTransform(gc, &transform);
+}
+
+void Fl_WinAPI_Printer_Driver::margins(int *left, int *top, int *right, int *bottom)
+{
+ int x = 0, y = 0, w = 0, h = 0;
+ absolute_printable_rect(&x, &y, &w, &h);
+ if (left) *left = x;
+ if (top) *top = y;
+ if (right) *right = x;
+ if (bottom) *bottom = y;
+}
+
+int Fl_WinAPI_Printer_Driver::printable_rect(int *w, int *h)
+{
+ int x, y;
+ absolute_printable_rect(&x, &y, w, h);
+ return 0;
+}
+
+int Fl_WinAPI_Printer_Driver::start_page (void)
+{
+ int rsult, w, h;
+
+ rsult = 0;
+ if (hPr != NULL) {
+ WIN_SetupPrinterDeviceContext (hPr);
+ prerr = StartPage (hPr);
+ if (prerr < 0) {
+ fl_alert ("StartPage error %d", prerr);
+ rsult = 1;
+ }
+ printable_rect(&w, &h);
+ origin(0, 0);
+ fl_clip_region(0);
+ }
+ return rsult;
+}
+
+void Fl_WinAPI_Printer_Driver::origin (int deltax, int deltay)
+{
+ SetWindowOrgEx( (HDC)driver()->gc(), - left_margin - deltax, - top_margin - deltay, NULL);
+ x_offset = deltax;
+ y_offset = deltay;
+}
+
+void Fl_WinAPI_Printer_Driver::scale (float scalex, float scaley)
+{
+ if (scaley == 0.) scaley = scalex;
+ int w, h;
+ SetWindowExtEx((HDC)driver()->gc(), (int)(720 / scalex + 0.5), (int)(720 / scaley + 0.5), NULL);
+ printable_rect(&w, &h);
+ origin(0, 0);
+}
+
+void Fl_WinAPI_Printer_Driver::rotate (float rot_angle)
+{
+ XFORM mat;
+ float angle;
+ angle = (float) - (rot_angle * M_PI / 180.);
+ mat.eM11 = cos(angle);
+ mat.eM12 = sin(angle);
+ mat.eM21 = - mat.eM12;
+ mat.eM22 = mat.eM11;
+ mat.eDx = mat.eDy = 0;
+ SetWorldTransform((HDC)driver()->gc(), &mat);
+}
+
+int Fl_WinAPI_Printer_Driver::end_page (void)
+{
+ int rsult;
+
+ rsult = 0;
+ if (hPr != NULL) {
+ prerr = EndPage (hPr);
+ if (prerr < 0) {
+ abortPrint = TRUE;
+ fl_alert ("EndPage error %d", prerr);
+ rsult = 1;
+ }
+ }
+ return rsult;
+}
+
+static int translate_stack_depth = 0;
+const int translate_stack_max = 5;
+static int translate_stack_x[translate_stack_max];
+static int translate_stack_y[translate_stack_max];
+
+static void do_translate(int x, int y, HDC gc)
+{
+ XFORM tr;
+ tr.eM11 = tr.eM22 = 1;
+ tr.eM12 = tr.eM21 = 0;
+ tr.eDx = (FLOAT) x;
+ tr.eDy = (FLOAT) y;
+ ModifyWorldTransform(gc, &tr, MWT_LEFTMULTIPLY);
+}
+
+void Fl_WinAPI_Printer_Driver::translate (int x, int y)
+{
+ do_translate(x, y, (HDC)driver()->gc());
+ if (translate_stack_depth < translate_stack_max) {
+ translate_stack_x[translate_stack_depth] = x;
+ translate_stack_y[translate_stack_depth] = y;
+ translate_stack_depth++;
+ }
+}
+
+void Fl_WinAPI_Printer_Driver::untranslate (void)
+{
+ if (translate_stack_depth > 0) {
+ translate_stack_depth--;
+ do_translate( - translate_stack_x[translate_stack_depth], - translate_stack_y[translate_stack_depth], (HDC)driver()->gc() );
+ }
+}
+
+void Fl_WinAPI_Printer_Driver::origin(int *x, int *y)
+{
+ Fl_Paged_Device::origin(x, y);
+}
+
+#endif // WIN32
+
+//
+// End of "$Id$".
+//