1 /////////////////////////////////////////////////////////////////////////////
3 // Author: Robert Roebling
4 // Purpose: Implement GNOME printing support
6 // Copyright: Robert Roebling
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
11 #pragma implementation "gprint.h"
14 // For compilers that support precompilation, includes "wx/wx.h".
15 #include "wx/wxprec.h"
21 #include "wx/gtk/gnome/gprint.h"
23 #if wxUSE_LIBGNOMEPRINT
27 #include "wx/fontutil.h"
28 #include "wx/printdlg.h"
29 #include "wx/gtk/private.h"
31 #include <libgnomeprint/gnome-print.h>
32 #include <libgnomeprint/gnome-print-pango.h>
33 #include <libgnomeprintui/gnome-print-dialog.h>
35 //----------------------------------------------------------------------------
36 // wxGnomePrintNativeData
37 //----------------------------------------------------------------------------
39 IMPLEMENT_CLASS(wxGnomePrintNativeData
, wxPrintNativeDataBase
)
41 wxGnomePrintNativeData::wxGnomePrintNativeData()
43 m_config
= gnome_print_config_default();
44 m_job
= gnome_print_job_new( m_config
);
47 wxGnomePrintNativeData::~wxGnomePrintNativeData()
49 g_object_unref (G_OBJECT (m_config
));
50 g_object_unref (G_OBJECT (m_job
));
53 bool wxGnomePrintNativeData::TransferTo( wxPrintData
&data
)
59 bool wxGnomePrintNativeData::TransferFrom( const wxPrintData
&data
)
65 //----------------------------------------------------------------------------
66 // wxGnomePrintFactory
67 //----------------------------------------------------------------------------
69 wxPrinterBase
* wxGnomePrintFactory::CreatePrinter( wxPrintDialogData
*data
)
71 return new wxGnomePrinter( data
);
74 wxPrintPreviewBase
*wxGnomePrintFactory::CreatePrintPreview( wxPrintout
*preview
,
76 wxPrintDialogData
*data
)
78 return new wxPostScriptPrintPreview( preview
, printout
, data
);
81 wxPrintPreviewBase
*wxGnomePrintFactory::CreatePrintPreview( wxPrintout
*preview
,
85 return new wxPostScriptPrintPreview( preview
, printout
, data
);
88 wxPrintDialogBase
*wxGnomePrintFactory::CreatePrintDialog( wxWindow
*parent
,
89 wxPrintDialogData
*data
)
91 return new wxGenericPrintDialog( parent
, data
);
94 wxPrintDialogBase
*wxGnomePrintFactory::CreatePrintDialog( wxWindow
*parent
,
97 return new wxGenericPrintDialog( parent
, data
);
100 bool wxGnomePrintFactory::HasPrintSetupDialog()
105 wxDialog
*wxGnomePrintFactory::CreatePrintSetupDialog( wxWindow
*parent
, wxPrintData
*data
)
107 return new wxGnomePrintSetupDialog( parent
, data
);
110 bool wxGnomePrintFactory::HasOwnPrintToFile()
115 bool wxGnomePrintFactory::HasPrinterLine()
120 wxString
wxGnomePrintFactory::CreatePrinterLine()
122 // We should query "gnome_config_default" here
123 return _("GNOME print");
126 bool wxGnomePrintFactory::HasStatusLine()
131 wxString
wxGnomePrintFactory::CreateStatusLine()
133 // We should query "gnome_config_default" here
137 wxPrintNativeDataBase
*wxGnomePrintFactory::CreatePrintNativeData()
139 return new wxGnomePrintNativeData
;
142 //----------------------------------------------------------------------------
143 // wxGnomePrintSetupDialog
144 //----------------------------------------------------------------------------
146 IMPLEMENT_CLASS(wxGnomePrintSetupDialog
, wxDialog
)
148 wxGnomePrintSetupDialog::wxGnomePrintSetupDialog( wxWindow
*parent
, wxPrintData
*data
)
150 wxGnomePrintNativeData
*native
=
151 (wxGnomePrintNativeData
*) data
->GetNativeData();
153 m_widget
= gnome_print_dialog_new (native
->GetPrintJob(), (guchar
*)"Print setup", 0);
156 wxGnomePrintSetupDialog::~wxGnomePrintSetupDialog()
161 int wxGnomePrintSetupDialog::ShowModal()
163 int response
= gtk_dialog_run (GTK_DIALOG (m_widget
));
164 gtk_widget_destroy(m_widget
);
167 if (response
== GNOME_PRINT_DIALOG_RESPONSE_CANCEL
)
173 bool wxGnomePrintSetupDialog::Validate()
178 bool wxGnomePrintSetupDialog::TransferDataToWindow()
183 bool wxGnomePrintSetupDialog::TransferDataFromWindow()
189 //----------------------------------------------------------------------------
191 //----------------------------------------------------------------------------
193 IMPLEMENT_CLASS(wxGnomePrinter
, wxPrinterBase
)
195 wxGnomePrinter::wxGnomePrinter( wxPrintDialogData
*data
) :
196 wxPrinterBase( data
)
201 wxGnomePrinter::~wxGnomePrinter()
205 bool wxGnomePrinter::Print(wxWindow
*parent
, wxPrintout
*printout
, bool prompt
)
209 sm_lastError
= wxPRINTER_ERROR
;
213 wxPrintData printdata
= GetPrintDialogData().GetPrintData();
214 wxGnomePrintNativeData
*data
=
215 (wxGnomePrintNativeData
*) printdata
.GetNativeData();
217 // The GnomePrintJob is temporarily stored in the
218 // native print data as the native print setup dialog
219 // needs to access it.
220 GnomePrintJob
*job
= data
->GetPrintJob();
221 m_gpc
= gnome_print_job_get_context (job
);
223 printout
->SetIsPreview(false);
225 if (m_printDialogData
.GetMinPage() < 1)
226 m_printDialogData
.SetMinPage(1);
227 if (m_printDialogData
.GetMaxPage() < 1)
228 m_printDialogData
.SetMaxPage(9999);
232 dc
= PrintDialog( parent
);
234 dc
= new wxGnomePrintDC( this );
238 gnome_print_job_close( job
);
239 sm_lastError
= wxPRINTER_ERROR
;
243 wxSize ScreenPixels
= wxGetDisplaySize();
244 wxSize ScreenMM
= wxGetDisplaySizeMM();
246 printout
->SetPPIScreen( (int) ((ScreenPixels
.GetWidth() * 25.4) / ScreenMM
.GetWidth()),
247 (int) ((ScreenPixels
.GetHeight() * 25.4) / ScreenMM
.GetHeight()) );
248 printout
->SetPPIPrinter( wxPostScriptDC::GetResolution(),
249 wxPostScriptDC::GetResolution() );
255 printout
->SetPageSizePixels((int)w
, (int)h
);
256 dc
->GetSizeMM(&w
, &h
);
257 printout
->SetPageSizeMM((int)w
, (int)h
);
259 printout
->OnPreparePrinting();
260 printout
->OnBeginPrinting();
262 if (!printout
->OnBeginDocument(0, 0))
264 sm_lastError
= wxPRINTER_ERROR
;
269 for (pn
= 1; pn
<= 2; pn
++)
272 printout
->OnPrintPage(pn
);
276 printout
->OnEndDocument();
277 printout
->OnEndPrinting();
280 gnome_print_job_close( job
);
281 gnome_print_job_print( job
);
285 return (sm_lastError
== wxPRINTER_NO_ERROR
);
288 wxDC
* wxGnomePrinter::PrintDialog( wxWindow
*parent
)
290 wxPrintDialog
dialog( parent
, &m_printDialogData
);
291 if (dialog
.ShowModal() == wxID_CANCEL
)
293 sm_lastError
= wxPRINTER_ERROR
;
297 return new wxGnomePrintDC( this );
300 bool wxGnomePrinter::Setup( wxWindow
*parent
)
305 //-----------------------------------------------------------------------------
307 //-----------------------------------------------------------------------------
309 IMPLEMENT_CLASS(wxGnomePrintDC
, wxDCBase
)
311 wxGnomePrintDC::wxGnomePrintDC( wxGnomePrinter
*printer
)
315 m_gpc
= printer
->GetPrintContext();
317 m_layout
= gnome_print_pango_create_layout( m_gpc
);
318 m_fontdesc
= pango_font_description_from_string( "Sans 12" );
324 m_signX
= 1; // default x-axis left to right
325 m_signY
= -1; // default y-axis bottom up -> top down
328 wxGnomePrintDC::~wxGnomePrintDC()
332 bool wxGnomePrintDC::Ok() const
337 bool wxGnomePrintDC::DoFloodFill(wxCoord x1
, wxCoord y1
, const wxColour
&col
, int style
)
342 bool wxGnomePrintDC::DoGetPixel(wxCoord x1
, wxCoord y1
, wxColour
*col
) const
347 void wxGnomePrintDC::DoDrawLine(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
349 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
353 gnome_print_moveto ( m_gpc
, XLOG2DEV(x1
), YLOG2DEV(y1
) );
354 gnome_print_lineto ( m_gpc
, XLOG2DEV(x2
), YLOG2DEV(y2
) );
355 gnome_print_stroke ( m_gpc
);
357 CalcBoundingBox( x1
, y1
);
358 CalcBoundingBox( x2
, y2
);
361 void wxGnomePrintDC::DoCrossHair(wxCoord x
, wxCoord y
)
365 void wxGnomePrintDC::DoDrawArc(wxCoord x1
,wxCoord y1
,wxCoord x2
,wxCoord y2
,wxCoord xc
,wxCoord yc
)
369 void wxGnomePrintDC::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
373 void wxGnomePrintDC::DoDrawPoint(wxCoord x
, wxCoord y
)
377 void wxGnomePrintDC::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
381 void wxGnomePrintDC::DoDrawPolygon(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
385 void wxGnomePrintDC::DoDrawPolyPolygon(int n
, int count
[], wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
389 void wxGnomePrintDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
391 if (m_brush
.GetStyle () != wxTRANSPARENT
)
395 gnome_print_newpath( m_gpc
);
396 gnome_print_moveto( m_gpc
, XLOG2DEV(x
), YLOG2DEV(y
) );
397 gnome_print_lineto( m_gpc
, XLOG2DEV(x
+ width
), YLOG2DEV(y
) );
398 gnome_print_lineto( m_gpc
, XLOG2DEV(x
+ width
), YLOG2DEV(y
+ height
) );
399 gnome_print_lineto( m_gpc
, XLOG2DEV(x
), YLOG2DEV(y
+ height
) );
400 gnome_print_closepath( m_gpc
);
401 gnome_print_fill( m_gpc
);
403 CalcBoundingBox( x
, y
);
404 CalcBoundingBox( x
+ width
, y
+ height
);
407 if (m_pen
.GetStyle () != wxTRANSPARENT
)
411 gnome_print_newpath( m_gpc
);
412 gnome_print_moveto( m_gpc
, XLOG2DEV(x
), YLOG2DEV(y
) );
413 gnome_print_lineto( m_gpc
, XLOG2DEV(x
+ width
), YLOG2DEV(y
) );
414 gnome_print_lineto( m_gpc
, XLOG2DEV(x
+ width
), YLOG2DEV(y
+ height
) );
415 gnome_print_lineto( m_gpc
, XLOG2DEV(x
), YLOG2DEV(y
+ height
) );
416 gnome_print_closepath( m_gpc
);
417 gnome_print_stroke( m_gpc
);
419 CalcBoundingBox( x
, y
);
420 CalcBoundingBox( x
+ width
, y
+ height
);
424 void wxGnomePrintDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
428 void wxGnomePrintDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
432 void wxGnomePrintDC::DoDrawSpline(wxList
*points
)
436 bool wxGnomePrintDC::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
437 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
438 wxCoord xsrcMask
, wxCoord ysrcMask
)
443 void wxGnomePrintDC::DoDrawIcon( const wxIcon
& icon
, wxCoord x
, wxCoord y
)
445 DoDrawBitmap( icon
, x
, y
, true );
448 void wxGnomePrintDC::DoDrawBitmap( const wxBitmap
& bitmap
, wxCoord x
, wxCoord y
, bool useMask
)
450 if (!bitmap
.Ok()) return;
453 // TODO do something clever here
454 if (bitmap
.HasPixbuf())
460 wxImage image
= bitmap
.ConvertToImage();
462 if (!image
.Ok()) return;
464 gnome_print_moveto (m_gpc
, XLOG2DEV(x
), YLOG2DEV(y
) );
465 gnome_print_rgbimage( m_gpc
, (guchar
*) image
.GetData(), image
.GetWidth(), image
.GetHeight(), image
.GetWidth()*3 );
469 void wxGnomePrintDC::DoDrawText(const wxString
& text
, wxCoord x
, wxCoord y
)
473 if (m_textForegroundColour
.Ok())
475 unsigned char red
= m_textForegroundColour
.Red();
476 unsigned char blue
= m_textForegroundColour
.Blue();
477 unsigned char green
= m_textForegroundColour
.Green();
479 if (!(red
== m_currentRed
&& green
== m_currentGreen
&& blue
== m_currentBlue
))
481 double redPS
= (double)(red
) / 255.0;
482 double bluePS
= (double)(blue
) / 255.0;
483 double greenPS
= (double)(green
) / 255.0;
485 gnome_print_setrgbcolor( m_gpc
, redPS
, bluePS
, greenPS
);
488 m_currentBlue
= blue
;
489 m_currentGreen
= green
;
496 bool underlined
= m_font
.Ok() && m_font
.GetUnderlined();
499 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( text
);
501 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( text
);
504 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
507 size_t datalen
= strlen((const char*)data
);
508 pango_layout_set_text( m_layout
, (const char*) data
, datalen
);
512 PangoAttrList
*attrs
= pango_attr_list_new();
513 PangoAttribute
*a
= pango_attr_underline_new(PANGO_UNDERLINE_SINGLE
);
515 a
->end_index
= datalen
;
516 pango_attr_list_insert(attrs
, a
);
517 pango_layout_set_attributes(m_layout
, attrs
);
518 pango_attr_list_unref(attrs
);
523 if (fabs(m_scaleY
- 1.0) > 0.00001)
525 // If there is a user or actually any scale applied to
526 // the device context, scale the font.
528 // scale font description
529 gint oldSize
= pango_font_description_get_size( m_fontdesc
);
530 double size
= oldSize
;
531 size
= size
* m_scaleY
;
532 pango_font_description_set_size( m_fontdesc
, (gint
)size
);
534 // actually apply scaled font
535 pango_layout_set_font_description( m_layout
, m_fontdesc
);
537 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
539 if ( m_backgroundMode
== wxSOLID
)
541 gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor());
542 gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
);
543 gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor());
547 gnome_print_moveto (m_gpc
, x
, y
);
548 gnome_print_pango_layout( m_gpc
, m_layout
);
550 // reset unscaled size
551 pango_font_description_set_size( m_fontdesc
, oldSize
);
553 // actually apply unscaled font
554 pango_layout_set_font_description( m_layout
, m_fontdesc
);
558 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
560 if ( m_backgroundMode
== wxSOLID
)
562 gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor());
563 gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
);
564 gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor());
568 gnome_print_moveto (m_gpc
, x
, y
);
569 gnome_print_pango_layout( m_gpc
, m_layout
);
576 // undo underline attributes setting:
577 pango_layout_set_attributes(m_layout
, NULL
);
580 // CalcBoundingBox (x + width, y + height);
581 CalcBoundingBox (x
, y
);
584 void wxGnomePrintDC::DoDrawRotatedText(const wxString
& text
, wxCoord x
, wxCoord y
, double angle
)
588 void wxGnomePrintDC::Clear()
592 void wxGnomePrintDC::SetFont( const wxFont
& font
)
599 pango_font_description_free( m_fontdesc
);
601 m_fontdesc
= pango_font_description_copy( m_font
.GetNativeFontInfo()->description
);
603 pango_layout_set_font_description( m_layout
, m_fontdesc
);
607 void wxGnomePrintDC::SetPen( const wxPen
& pen
)
609 if (!pen
.Ok()) return;
611 int oldStyle
= m_pen
.GetStyle();
615 gnome_print_setlinewidth( m_gpc
, XLOG2DEVREL( 1000 * m_pen
.GetWidth() ) / 1000.0f
);
617 unsigned char red
= m_pen
.GetColour().Red();
618 unsigned char blue
= m_pen
.GetColour().Blue();
619 unsigned char green
= m_pen
.GetColour().Green();
621 if (!(red
== m_currentRed
&& green
== m_currentGreen
&& blue
== m_currentBlue
))
623 double redPS
= (double)(red
) / 255.0;
624 double bluePS
= (double)(blue
) / 255.0;
625 double greenPS
= (double)(green
) / 255.0;
627 gnome_print_setrgbcolor( m_gpc
, redPS
, bluePS
, greenPS
);
630 m_currentBlue
= blue
;
631 m_currentGreen
= green
;
635 void wxGnomePrintDC::SetBrush( const wxBrush
& brush
)
637 if (!brush
.Ok()) return;
642 unsigned char red
= m_brush
.GetColour().Red();
643 unsigned char blue
= m_brush
.GetColour().Blue();
644 unsigned char green
= m_brush
.GetColour().Green();
648 // Anything not white is black
649 if (! (red
== (unsigned char) 255 &&
650 blue
== (unsigned char) 255 &&
651 green
== (unsigned char) 255) )
653 red
= (unsigned char) 0;
654 green
= (unsigned char) 0;
655 blue
= (unsigned char) 0;
660 if (!(red
== m_currentRed
&& green
== m_currentGreen
&& blue
== m_currentBlue
))
662 double redPS
= (double)(red
) / 255.0;
663 double bluePS
= (double)(blue
) / 255.0;
664 double greenPS
= (double)(green
) / 255.0;
666 gnome_print_setrgbcolor( m_gpc
, redPS
, bluePS
, greenPS
);
669 m_currentBlue
= blue
;
670 m_currentGreen
= green
;
674 void wxGnomePrintDC::SetLogicalFunction( int function
)
678 void wxGnomePrintDC::SetBackground( const wxBrush
& brush
)
682 void wxGnomePrintDC::DoSetClippingRegion(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
686 void wxGnomePrintDC::DestroyClippingRegion()
690 bool wxGnomePrintDC::StartDoc(const wxString
& message
)
692 SetDeviceOrigin( 0,0 );
697 void wxGnomePrintDC::EndDoc()
701 void wxGnomePrintDC::StartPage()
703 gnome_print_beginpage( m_gpc
, (const guchar
*) "1" );
706 void wxGnomePrintDC::EndPage()
708 gnome_print_showpage( m_gpc
);
711 wxCoord
wxGnomePrintDC::GetCharHeight() const
716 wxCoord
wxGnomePrintDC::GetCharWidth() const
721 void wxGnomePrintDC::DoGetTextExtent(const wxString
& string
, wxCoord
*width
, wxCoord
*height
,
723 wxCoord
*externalLeading
,
724 wxFont
*theFont
) const
732 if ( externalLeading
)
733 *externalLeading
= 0;
735 if (string
.IsEmpty())
740 // Set new font description
742 pango_layout_set_font_description( m_layout
, theFont
->GetNativeFontInfo()->description
);
746 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( string
);
747 const char *dataUTF8
= (const char *)data
;
749 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( string
);
752 if (width
) (*width
) = 0;
753 if (height
) (*height
) = 0;
756 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
757 const char *dataUTF8
= (const char *)data
;
762 // hardly ideal, but what else can we do if conversion failed?
766 pango_layout_set_text( m_layout
, dataUTF8
, strlen(dataUTF8
) );
769 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
772 *width
= (wxCoord
) w
;
774 *height
= (wxCoord
) h
;
777 PangoLayoutIter
*iter
= pango_layout_get_iter(m_layout
);
778 int baseline
= pango_layout_iter_get_baseline(iter
);
779 pango_layout_iter_free(iter
);
780 *descent
= h
- PANGO_PIXELS(baseline
);
783 // Reset old font description
785 pango_layout_set_font_description( m_layout
, m_fontdesc
);
788 void wxGnomePrintDC::DoGetSize(int* width
, int* height
) const
790 // No idea if that is efficient
791 GnomePrintConfig
*config
= gnome_print_config_default();
794 bool result
= gnome_print_config_get_page_size( config
, &w
, &h
);
798 // Standard PS resolution DIN A4 size.
809 void wxGnomePrintDC::DoGetSizeMM(int *width
, int *height
) const
813 /// Later, for now DIN A4
823 wxSize
wxGnomePrintDC::GetPPI() const
825 return wxSize(72,72);
828 void wxGnomePrintDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
830 m_signX
= (xLeftRight
? 1 : -1);
831 m_signY
= (yBottomUp
? 1 : -1);
833 ComputeScaleAndOrigin();
836 void wxGnomePrintDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
842 wxDC::SetDeviceOrigin( x
, h
-y
);
845 void wxGnomePrintDC::SetResolution(int ppi
)
849 int wxGnomePrintDC::GetResolution()
855 class wxGnomePrintModule
: public wxModule
858 wxGnomePrintModule() {}
859 bool OnInit() { wxPrintFactory::SetPrintFactory( new wxGnomePrintFactory
); return true; }
863 DECLARE_DYNAMIC_CLASS(wxGnomePrintModule
)
866 IMPLEMENT_DYNAMIC_CLASS(wxGnomePrintModule
, wxModule
)
869 // wxUSE_LIBGNOMEPRINT