summaryrefslogtreecommitdiff
path: root/app/wlib/gtklib/print.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/wlib/gtklib/print.c')
-rw-r--r--app/wlib/gtklib/print.c858
1 files changed, 858 insertions, 0 deletions
diff --git a/app/wlib/gtklib/print.c b/app/wlib/gtklib/print.c
new file mode 100644
index 0000000..9f4a4a8
--- /dev/null
+++ b/app/wlib/gtklib/print.c
@@ -0,0 +1,858 @@
+/** \file print.c
+ * Printing functions using GTK's print API
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2015 Martin Fischer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <pwd.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <math.h>
+#include <locale.h>
+
+#include <stdint.h>
+
+#include "gtkint.h"
+#include <gtk/gtkprintunixdialog.h>
+#include <gtk/gtkprintjob.h>
+
+#include "wlib.h"
+#include "i18n.h"
+
+extern wDrawColor wDrawColorWhite;
+extern wDrawColor wDrawColorBlack;
+
+/*****************************************************************************
+ *
+ * MACROS
+ *
+ */
+
+#define PRINT_PORTRAIT (0)
+#define PRINT_LANDSCAPE (1)
+
+#define PPI (72.0)
+#define P2I( P ) ((P)/PPI)
+
+#define CENTERMARK_LENGTH (60) /**< size of cross marking center of circles */
+#define DASH_LENGTH (8.0) /**< length of single dash */
+
+#define PAGESETTINGS "xtrkcad.page" /**< filename for page settings */
+#define PRINTSETTINGS "xtrkcad.printer" /**< filename for printer settings */
+
+/*****************************************************************************
+ *
+ * VARIABLES
+ *
+ */
+
+static GtkPrintSettings *settings; /**< current printer settings */
+static GtkPageSetup *page_setup; /**< current paper settings */
+static GtkPrinter *selPrinter; /**< printer selected by user */
+static GtkPrintJob *curPrintJob; /**< currently active print job */
+extern struct wDraw_t psPrint_d;
+
+static wBool_t printContinue; /**< control print job, FALSE for cancelling */
+
+static wIndex_t pageCount; /**< unused, could be used for progress indicator */
+static wIndex_t totalPageCount; /**< unused, could be used for progress indicator */
+
+static double paperWidth; /**< physical paper width */
+static double paperHeight; /**< physical paper height */
+static double tBorder; /**< top margin */
+static double rBorder; /**< right margin */
+static double lBorder; /**< left margin */
+static double bBorder; /**< bottom margin */
+
+static long printFormat = PRINT_LANDSCAPE;
+
+/*****************************************************************************
+ *
+ * FUNCTIONS
+ *
+ */
+
+static void WlibGetPaperSize( void );
+
+/**
+ * Initialize printer und paper selection using the saved settings
+ *
+ * \param op IN print operation to initialize. If NULL only the global
+ * settings are loaded.
+ */
+
+void
+WlibApplySettings( GtkPrintOperation *op )
+{
+ gchar *filename;
+ GError *err = NULL;
+ GtkWidget *dialog;
+
+ filename = g_build_filename( wGetAppWorkDir(), PRINTSETTINGS, NULL );
+
+ if( !(settings = gtk_print_settings_new_from_file( filename, &err ))) {
+ if( err->code != G_FILE_ERROR_NOENT ) {
+ // ignore file not found error as defaults will be used
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ } else {
+ // create default print settings
+ settings = gtk_print_settings_new();
+ }
+ g_error_free (err);
+ }
+ g_free( filename );
+
+ if (settings && op )
+ gtk_print_operation_set_print_settings (op, settings);
+
+ err = NULL;
+ filename = g_build_filename( wGetAppWorkDir(), PAGESETTINGS, NULL );
+ if( !(page_setup = gtk_page_setup_new_from_file( filename, &err ))) {
+ // ignore file not found error as defaults will be used
+ if( err->code != G_FILE_ERROR_NOENT ) {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ } else {
+ page_setup = gtk_page_setup_new();
+ }
+ g_error_free (err);
+ } else {
+ // on success get the paper dimensions
+ WlibGetPaperSize();
+ }
+ g_free( filename );
+
+ if( page_setup && op )
+ gtk_print_operation_set_default_page_setup (op, page_setup);
+
+}
+
+/**
+ * Save the printer settings. If op is not NULL the settings are retrieved
+ * from the print operation. Otherwise the state of the globals is saved.
+ *
+ * \param op IN printer operation. If NULL the glabal variables are used
+ */
+
+void
+WlibSaveSettings( GtkPrintOperation *op )
+{
+ GError *err = NULL;
+ gchar *filename;
+ GtkWidget *dialog;
+
+ if( op ) {
+ if (settings != NULL)
+ g_object_unref (settings);
+ settings = g_object_ref (gtk_print_operation_get_print_settings (op));
+ }
+ filename = g_build_filename( wGetAppWorkDir(), PRINTSETTINGS, NULL );
+ if( !gtk_print_settings_to_file( settings, filename, &err )) {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+
+ g_error_free (err);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
+ g_free( filename );
+
+ if( op ) {
+ if (page_setup != NULL)
+ g_object_unref (page_setup);
+ page_setup = g_object_ref (gtk_print_operation_get_default_page_setup (op));
+ }
+ filename = g_build_filename( wGetAppWorkDir(), PAGESETTINGS, NULL );
+ if( !gtk_page_setup_to_file( page_setup, filename, &err )) {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+
+ g_error_free (err);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
+ g_free( filename );
+
+}
+
+/**
+ * Page setup function. Previous settings are loaded and the setup
+ * dialog is shown. The settings are saved after the dialog ends.
+ *
+ * \param callback IN unused
+ */
+
+void wPrintSetup( wPrintSetupCallBack_p callback )
+{
+ GtkPageSetup *new_page_setup;
+ gchar *filename;
+ GError *err;
+ GtkWidget *dialog;
+
+ WlibApplySettings( NULL );
+
+ new_page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (gtkMainW->gtkwin),
+ page_setup, settings);
+ if (page_setup)
+ g_object_unref (page_setup);
+
+ page_setup = new_page_setup;
+
+ WlibGetPaperSize();
+ WlibSaveSettings( NULL );
+}
+
+/*****************************************************************************
+ *
+ * BASIC PRINTING
+ *
+ */
+
+
+/**
+ * set the current line type for printing operations
+ *
+ * \param lineWidth IN new line width
+ * \param lineType IN flag for line type (dashed or full)
+ * \param opts IN unused
+ * \return
+ */
+
+
+static void setLineType(
+ double lineWidth,
+ wDrawLineType_e lineType,
+ wDrawOpts opts )
+{
+ cairo_t *cr = psPrint_d.printContext;
+ double dashLength = DASH_LENGTH;
+
+ if (lineWidth < 0.0) {
+ lineWidth = P2I(-lineWidth)*2.0;
+ }
+
+ // make sure that there is a minimum line width used
+ if ( lineWidth == 0.0 )
+ lineWidth = 0.1;
+
+ cairo_set_line_width( cr, lineWidth );
+
+ if (lineType == wDrawLineDash)
+ cairo_set_dash( cr, &dashLength, 1, 0.0 );
+ else
+ cairo_set_dash( cr, NULL, 0, 0.0 );
+}
+
+/**
+ * set the color for the following print operations
+ *
+ * \param color IN the new color
+ * \return
+ */
+
+static void psSetColor(
+ wDrawColor color )
+{
+ cairo_t *cr = psPrint_d.printContext;
+ GdkColor* const gcolor = gtkGetColor(color, TRUE);
+
+ cairo_set_source_rgb(cr, gcolor->red / 65535.0,
+ gcolor->green / 65535.0,
+ gcolor->blue / 65535.0);
+}
+
+/**
+ * Print a straight line
+ *
+ * \param x0, y0 IN starting point in pixels
+ * \param x1, y1 IN ending point in pixels
+ * \param width line width
+ * \param lineType
+ * \param color color
+ * \param opts ?
+ */
+
+void psPrintLine(
+ wPos_t x0, wPos_t y0,
+ wPos_t x1, wPos_t y1,
+ wDrawWidth width,
+ wDrawLineType_e lineType,
+ wDrawColor color,
+ wDrawOpts opts )
+{
+ if (color == wDrawColorWhite)
+ return;
+ if (opts&wDrawOptTemp)
+ return;
+
+ psSetColor(color);
+ setLineType( width, lineType, opts );
+
+ cairo_move_to( psPrint_d.printContext,
+ x0, y0 );
+ cairo_line_to( psPrint_d.printContext,
+ x1, y1 );
+ cairo_stroke( psPrint_d.printContext );
+}
+
+/**
+ * Print an arc around a specified center
+ *
+ * \param x0, y0 IN center of arc
+ * \param r IN radius
+ * \param angle0, angle1 IN start and end angle
+ * \param drawCenter draw marking for center
+ * \param width line width
+ * \param lineType
+ * \param color color
+ * \param opts ?
+ */
+
+void psPrintArc(
+ wPos_t x0, wPos_t y0,
+ wPos_t r,
+ double angle0,
+ double angle1,
+ wBool_t drawCenter,
+ wDrawWidth width,
+ wDrawLineType_e lineType,
+ wDrawColor color,
+ wDrawOpts opts )
+{
+ cairo_t *cr = psPrint_d.printContext;
+
+ if (color == wDrawColorWhite)
+ return;
+ if (opts&wDrawOptTemp)
+ return;
+
+ psSetColor(color);
+ setLineType(width, lineType, opts);
+
+ if (angle1 >= 360.0)
+ angle1 = 359.999;
+ angle1 = 90.0-(angle0+angle1);
+ while (angle1 < 0.0) angle1 += 360.0;
+ while (angle1 >= 360.0) angle1 -= 360.0;
+ angle0 = 90.0-angle0;
+ while (angle0 < 0.0) angle0 += 360.0;
+ while (angle0 >= 360.0) angle0 -= 360.0;
+
+ // draw the curve
+ cairo_arc( cr, x0, y0, r, angle1 * M_PI / 180.0, angle0 * M_PI / 180.0 );
+
+ if( drawCenter ) {
+ // draw crosshair for center of curve
+ cairo_move_to( cr, x0 - CENTERMARK_LENGTH / 2, y0 );
+ cairo_line_to( cr, x0 + CENTERMARK_LENGTH / 2, y0 );
+ cairo_move_to( cr, x0, y0 - CENTERMARK_LENGTH / 2 );
+ cairo_line_to( cr, x0, y0 + CENTERMARK_LENGTH / 2 );
+ }
+ cairo_stroke( psPrint_d.printContext );
+}
+
+/**
+ * Print a filled rectangle
+ *
+ * \param x0, y0 IN top left corner
+ * \param x1, y1 IN bottom right corner
+ * \param color IN fill color
+ * \param opts IN options
+ * \return
+ */
+
+void psPrintFillRectangle(
+ wPos_t x0, wPos_t y0,
+ wPos_t x1, wPos_t y1,
+ wDrawColor color,
+ wDrawOpts opts )
+{
+ cairo_t *cr = psPrint_d.printContext;
+ double width = x0 - x1;
+ double height = y0 - y1;
+
+ if (color == wDrawColorWhite)
+ return;
+ if (opts&wDrawOptTemp)
+ return;
+ psSetColor(color);
+
+ cairo_rectangle( cr, x0, y0, width, height );
+
+ cairo_fill( cr );
+}
+
+/**
+ * Print a filled polygon
+ *
+ * \param p IN a list of x and y coordinates
+ * \param cnt IN the number of points
+ * \param color IN fill color
+ * \param opts IN options
+ * \return
+ */
+
+void psPrintFillPolygon(
+ wPos_t p[][2],
+ int cnt,
+ wDrawColor color,
+ wDrawOpts opts )
+{
+ int inx;
+ cairo_t *cr = psPrint_d.printContext;
+
+ if (color == wDrawColorWhite)
+ return;
+ if (opts&wDrawOptTemp)
+ return;
+
+ psSetColor(color);
+
+ cairo_move_to( cr, p[ 0 ][ 0 ], p[ 0 ][ 1 ] );
+ for (inx=0; inx<cnt; inx++)
+ cairo_line_to( cr, p[ inx ][ 0 ], p[ inx ][ 1 ] );
+ cairo_fill( cr );
+}
+
+/**
+ * Print a filled circle
+ *
+ * \param x0, y0 IN coordinates of center (in pixels )
+ * \param r IN radius
+ * \param color IN fill color
+ * \param opts IN options
+ * \return
+ */
+
+void psPrintFillCircle(
+ wPos_t x0, wPos_t y0,
+ wPos_t r,
+ wDrawColor color,
+ wDrawOpts opts )
+{
+ if (color == wDrawColorWhite)
+ return;
+ if (opts&wDrawOptTemp)
+ return;
+ psSetColor(color);
+
+ cairo_arc( psPrint_d.printContext,
+ x0, y0, r, 0.0, 2 * M_PI );
+
+ cairo_fill( psPrint_d.printContext );
+}
+
+
+/**
+ * Print a string at the given position using specified font and text size.
+ * The orientatoion of the y-axis in XTrackCAD is wrong for cairo. So for
+ * all other print primitives a flip operation is done. As this would
+ * also affect the string orientation, printing a string has to be
+ * treated differently. The starting point is transformed, then the
+ * string is rotated and scaled as needed. Finally the string position
+ * translated to the starting point calculated previously. The same
+ * solution would have to be applied to a bitmap should printing
+ * bitmaps ever be implemented.
+ *
+ * \param x IN x position in pixels
+ * \param y IN y position in pixels
+ * \param a IN angle of baseline in degrees. Positive is clockwise, 0 is direction of positive x axis
+ * \param s IN string to print
+ * \param fp IN font
+ * \param fs IN font size
+ * \param color IN text color
+ * \param opts IN ???
+ * \return
+ */
+
+void psPrintString(
+ wPos_t x, wPos_t y,
+ double a,
+ char * s,
+ wFont_p fp,
+ double fs,
+ wDrawColor color,
+ wDrawOpts opts )
+{
+ char * cp;
+ double x0 = (double)x, y0 = (double)y;
+ double text_height;
+
+ cairo_t *cr;
+ cairo_matrix_t matrix;
+
+ PangoLayout *layout;
+ PangoFontDescription *desc;
+ PangoFontMetrics *metrics;
+ PangoContext *pcontext;
+
+ if (color == wDrawColorWhite)
+ return;
+
+ cr = psPrint_d.printContext;
+
+ // get the current transformation matrix and transform the starting
+ // point of the string
+ cairo_get_matrix( cr, &matrix );
+ cairo_matrix_transform_point( &matrix, &x0, &y0 );
+
+ cairo_save( cr );
+
+ layout = pango_cairo_create_layout( cr );
+
+ // set the correct font and size
+ /** \todo use a getter function instead of double conversion */
+ desc = pango_font_description_from_string (gtkFontTranslate( fp ));
+
+ //don't know why the size has to be reduced to 75% :-(
+ pango_font_description_set_size(desc, fs * PANGO_SCALE *0.75 );
+
+ // render the string to a Pango layout
+ pango_layout_set_font_description (layout, desc);
+ pango_layout_set_text (layout, s, -1);
+ pango_layout_set_width (layout, -1);
+ pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
+
+ // get the height of the string
+ pcontext = pango_cairo_create_context( cr );
+ metrics = pango_context_get_metrics(pcontext, desc, pango_context_get_language(pcontext));
+ text_height = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
+
+ // transform the string to the correct position
+ cairo_identity_matrix( cr );
+
+ cairo_translate( cr, x0 + text_height * sin ( -a * M_PI / 180.0) , y0 - text_height * cos ( a * M_PI / 180.0) );
+ cairo_rotate( cr, -a * M_PI / 180.0 );
+
+ // set the color
+ psSetColor( color );
+
+ // and show the string
+ pango_cairo_show_layout (cr, layout);
+
+ // free unused objects
+ g_object_unref( layout );
+ g_object_unref( pcontext );
+
+ cairo_restore( cr );
+}
+
+/**
+ * Create clipping retangle.
+ *
+ * \param x, y IN starting position
+ * \param w, h IN width and height of rectangle
+ * \return
+ */
+
+void wPrintClip( wPos_t x, wPos_t y, wPos_t w, wPos_t h )
+{
+ cairo_move_to( psPrint_d.printContext, x, y );
+ cairo_rel_line_to( psPrint_d.printContext, w, 0 );
+ cairo_rel_line_to( psPrint_d.printContext, 0, h );
+ cairo_rel_line_to( psPrint_d.printContext, -w, 0 );
+ cairo_close_path( psPrint_d.printContext );
+ cairo_clip( psPrint_d.printContext );
+}
+
+/*****************************************************************************
+ *
+ * PAGE FUNCTIONS
+ *
+ */
+
+/**
+ * Get the paper dimensions and margins and setup the internal variables
+ * \return
+ */
+
+static void
+WlibGetPaperSize( void )
+{
+ double temp;
+
+ bBorder = gtk_page_setup_get_bottom_margin( page_setup, GTK_UNIT_INCH );
+ tBorder = gtk_page_setup_get_top_margin( page_setup, GTK_UNIT_INCH );
+ lBorder = gtk_page_setup_get_left_margin( page_setup, GTK_UNIT_INCH );
+ rBorder = gtk_page_setup_get_right_margin( page_setup, GTK_UNIT_INCH );
+ paperHeight = gtk_page_setup_get_paper_height( page_setup, GTK_UNIT_INCH );
+ paperWidth = gtk_page_setup_get_paper_width( page_setup, GTK_UNIT_INCH );
+
+ // XTrackCAD does page orientation itself. Basic assumption is that the
+ // paper is always oriented in portrait mode. Ignore settings by user
+ if( paperHeight < paperWidth ) {
+ temp = paperHeight;
+ paperHeight = paperWidth;
+ paperWidth = temp;
+ }
+}
+
+/**
+ * Get the paper size. The size returned is the printable area of the
+ * currently selected paper, ie. the physical size minus the margins.
+ * \param w OUT printable width of the paper in inches
+ * \param h OUT printable height of the paper in inches
+ * \return
+ */
+
+void wPrintGetPageSize(
+ double * w,
+ double * h )
+{
+ // if necessary load the settings
+ if( !settings )
+ WlibApplySettings( NULL );
+
+ WlibGetPaperSize();
+
+ *w = paperWidth -lBorder - rBorder;
+ *h = paperHeight - tBorder - bBorder;
+}
+
+/**
+ * Get the paper size. The size returned is the physical size of the
+ * currently selected paper.
+ * \param w OUT physical width of the paper in inches
+ * \param h OUT physical height of the paper in inches
+ * \return
+ */
+
+void wPrintGetPhysSize(
+ double * w,
+ double * h )
+{
+ // if necessary load the settings
+ if( !settings )
+ WlibApplySettings( NULL );
+
+ WlibGetPaperSize();
+
+ *w = paperWidth;
+ *h = paperHeight;
+}
+
+/**
+ * Cancel the current print job. This function is preserved here for
+ * reference in case the function should be implemented again.
+ * \param context IN unused
+ * \return
+ */
+static void printAbort( void * context )
+{
+ printContinue = FALSE;
+// wWinShow( printAbortW, FALSE );
+}
+
+/**
+ * Initialize new page.
+ * The cairo_save() / cairo_restore() cycle was added to solve problems
+ * with a multi page print operation. This might actually be a bug in
+ * cairo but I didn't examine that any further.
+ *
+ * \return print context for the print operation
+ */
+wDraw_p wPrintPageStart( void )
+{
+ pageCount++;
+
+ cairo_save( psPrint_d.printContext );
+
+ return &psPrint_d;
+}
+
+/**
+ * End of page. This function returns the contents of printContinue. The
+ * caller continues printing as long as TRUE is returned. Setting
+ * printContinue to FALSE in an asynchronous handler therefore cleanly
+ * terminates a print job at the end of the page.
+ *
+ * \param p IN ignored
+ * \return always printContinue
+ */
+
+
+wBool_t wPrintPageEnd( wDraw_p p )
+{
+ cairo_show_page( psPrint_d.printContext );
+
+ cairo_restore( psPrint_d.printContext );
+
+ return printContinue;
+}
+
+/*****************************************************************************
+ *
+ * PRINT START/END
+ *
+ */
+
+
+/**
+ * Start a new document
+ *
+ * \param title IN title of document ( name of layout )
+ * \param fTotalPageCount IN number of pages to print (unused)
+ * \param copiesP OUT ???
+ * \return TRUE if successful, FALSE if cancelled by user
+ */
+
+wBool_t wPrintDocStart( const char * title, int fTotalPageCount, int * copiesP )
+{
+ GtkWidget *printDialog;
+ gint res;
+ cairo_surface_type_t surface_type;
+ cairo_matrix_t matrix;
+
+ printDialog = gtk_print_unix_dialog_new( title, GTK_WINDOW(gtkMainW->gtkwin));
+
+ // load the settings
+ WlibApplySettings( NULL );
+
+ // and apply them to the printer dialog
+ gtk_print_unix_dialog_set_settings( (GtkPrintUnixDialog *)printDialog, settings );
+ gtk_print_unix_dialog_set_page_setup( (GtkPrintUnixDialog *)printDialog, page_setup );
+
+ res = gtk_dialog_run( (GtkDialog *)printDialog );
+ if( res == GTK_RESPONSE_OK ) {
+ selPrinter = gtk_print_unix_dialog_get_selected_printer( (GtkPrintUnixDialog *)printDialog );
+
+ if( settings )
+ g_object_unref (settings);
+ settings = gtk_print_unix_dialog_get_settings( (GtkPrintUnixDialog *)printDialog );
+
+ if( page_setup )
+ g_object_unref( page_setup );
+ page_setup = gtk_print_unix_dialog_get_page_setup( (GtkPrintUnixDialog *)printDialog );
+
+ curPrintJob = gtk_print_job_new( title,
+ selPrinter,
+ settings,
+ page_setup );
+
+ psPrint_d.curPrintSurface = gtk_print_job_get_surface( curPrintJob,
+ NULL );
+ psPrint_d.printContext = cairo_create( psPrint_d.curPrintSurface );
+
+ //update the paper dimensions
+ WlibGetPaperSize();
+
+ /* for the file based surfaces the resolution is 72 dpi (see documentation) */
+ surface_type = cairo_surface_get_type( psPrint_d.curPrintSurface );
+ if( surface_type == CAIRO_SURFACE_TYPE_PDF ||
+ surface_type == CAIRO_SURFACE_TYPE_PS ||
+ surface_type == CAIRO_SURFACE_TYPE_SVG )
+ psPrint_d.dpi = 72;
+ else
+ psPrint_d.dpi = (double)gtk_print_settings_get_resolution( settings );
+
+ // in XTrackCAD 0,0 is top left, in cairo bottom left. This is
+ // corrected via the following transformations.
+ // also the translate makes sure that the drawing is rendered
+ // within the paper margins
+
+ cairo_scale( psPrint_d.printContext, 1.0, -1.0 );
+ cairo_translate( psPrint_d.printContext, lBorder * psPrint_d.dpi, -(paperHeight-bBorder) *psPrint_d.dpi );
+
+ WlibSaveSettings( NULL );
+ }
+ gtk_widget_destroy (printDialog);
+
+ if (copiesP)
+ *copiesP = 1;
+
+ printContinue = TRUE;
+
+ if( res != GTK_RESPONSE_OK )
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Callback for job finished event. Destroys the cairo context.
+ *
+ * \param job IN unused
+ * \param data IN unused
+ * \param err IN if != NULL, an error dialog ist displayed
+ * \return
+ */
+
+void
+doPrintJobFinished( GtkPrintJob *job, void *data, GError *err )
+{
+ GtkWidget *dialog;
+
+ cairo_destroy( psPrint_d.printContext );
+ if( err ) {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+ }
+}
+
+/**
+ * Finish the print operation
+ * \return
+ */
+
+void wPrintDocEnd( void )
+{
+ cairo_surface_finish( psPrint_d.curPrintSurface );
+
+ gtk_print_job_send( curPrintJob,
+ doPrintJobFinished,
+ NULL,
+ NULL );
+
+// wWinShow( printAbortW, FALSE );
+}
+
+
+wBool_t wPrintQuit( void )
+{
+ return FALSE;
+}
+
+
+wBool_t wPrintInit( void )
+{
+ return TRUE;
+}