]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/gnome/gprint.cpp
Added support for DrawEllipse and pen styles to
[wxWidgets.git] / src / gtk1 / gnome / gprint.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gprint.cpp
3 // Author: Robert Roebling
4 // Purpose: Implement GNOME printing support
5 // Created: 09/20/04
6 // Copyright: Robert Roebling
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
11 #pragma implementation "gprint.h"
12 #endif
13
14 // For compilers that support precompilation, includes "wx/wx.h".
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #include "wx/gtk/gnome/gprint.h"
22
23 #if wxUSE_LIBGNOMEPRINT
24
25 #include "math.h"
26
27 #include "wx/fontutil.h"
28 #include "wx/printdlg.h"
29 #include "wx/gtk/private.h"
30 #include "wx/module.h"
31 #include "wx/generic/prntdlgg.h"
32
33 #include <libgnomeprint/gnome-print.h>
34 #include <libgnomeprint/gnome-print-pango.h>
35 #include <libgnomeprint/gnome-print-config.h>
36 #include <libgnomeprintui/gnome-print-dialog.h>
37 #include <libgnomeprintui/gnome-print-job-preview.h>
38 #include <libgnomeprintui/gnome-print-paper-selector.h>
39
40 //----------------------------------------------------------------------------
41 // wxGnomePrintNativeData
42 //----------------------------------------------------------------------------
43
44 IMPLEMENT_CLASS(wxGnomePrintNativeData, wxPrintNativeDataBase)
45
46 wxGnomePrintNativeData::wxGnomePrintNativeData()
47 {
48 m_config = gnome_print_config_default();
49 m_job = gnome_print_job_new( m_config );
50 }
51
52 wxGnomePrintNativeData::~wxGnomePrintNativeData()
53 {
54 g_object_unref (G_OBJECT (m_config));
55 }
56
57 bool wxGnomePrintNativeData::TransferTo( wxPrintData &data )
58 {
59 // TODO
60 return true;
61 }
62
63 bool wxGnomePrintNativeData::TransferFrom( const wxPrintData &data )
64 {
65 // TODO
66 return true;
67 }
68
69 //----------------------------------------------------------------------------
70 // wxGnomePrintFactory
71 //----------------------------------------------------------------------------
72
73 wxPrinterBase* wxGnomePrintFactory::CreatePrinter( wxPrintDialogData *data )
74 {
75 return new wxGnomePrinter( data );
76 }
77
78 wxPrintPreviewBase *wxGnomePrintFactory::CreatePrintPreview( wxPrintout *preview,
79 wxPrintout *printout,
80 wxPrintDialogData *data )
81 {
82 return new wxPostScriptPrintPreview( preview, printout, data );
83 }
84
85 wxPrintPreviewBase *wxGnomePrintFactory::CreatePrintPreview( wxPrintout *preview,
86 wxPrintout *printout,
87 wxPrintData *data )
88 {
89 return new wxPostScriptPrintPreview( preview, printout, data );
90 }
91
92 wxPrintDialogBase *wxGnomePrintFactory::CreatePrintDialog( wxWindow *parent,
93 wxPrintDialogData *data )
94 {
95 return new wxGnomePrintDialog( parent, data );
96 }
97
98 wxPrintDialogBase *wxGnomePrintFactory::CreatePrintDialog( wxWindow *parent,
99 wxPrintData *data )
100 {
101 return new wxGnomePrintDialog( parent, data );
102 }
103
104 wxPageSetupDialogBase *wxGnomePrintFactory::CreatePageSetupDialog( wxWindow *parent,
105 wxPageSetupDialogData * data )
106 {
107 // The native page setup dialog is broken. It
108 // miscalculates newly entered values for the
109 // margins if you have not chose "points" but
110 // e.g. centimerters.
111 // This has been fixed in GNOME CVS (maybe
112 // fixed in libgnomeprintui 2.8.1)
113
114 return new wxGnomePageSetupDialog( parent, data );
115 }
116
117 bool wxGnomePrintFactory::HasPrintSetupDialog()
118 {
119 return false;
120 }
121
122 wxDialog *wxGnomePrintFactory::CreatePrintSetupDialog( wxWindow *parent, wxPrintData *data )
123 {
124 return NULL;
125 }
126
127 bool wxGnomePrintFactory::HasOwnPrintToFile()
128 {
129 return true;
130 }
131
132 bool wxGnomePrintFactory::HasPrinterLine()
133 {
134 return true;
135 }
136
137 wxString wxGnomePrintFactory::CreatePrinterLine()
138 {
139 // redundant now
140 return wxEmptyString;
141 }
142
143 bool wxGnomePrintFactory::HasStatusLine()
144 {
145 // redundant now
146 return true;
147 }
148
149 wxString wxGnomePrintFactory::CreateStatusLine()
150 {
151 // redundant now
152 return wxEmptyString;
153 }
154
155 wxPrintNativeDataBase *wxGnomePrintFactory::CreatePrintNativeData()
156 {
157 return new wxGnomePrintNativeData;
158 }
159
160 //----------------------------------------------------------------------------
161 // wxGnomePrintSetupDialog
162 //----------------------------------------------------------------------------
163
164 IMPLEMENT_CLASS(wxGnomePrintDialog, wxPrintDialogBase)
165
166 wxGnomePrintDialog::wxGnomePrintDialog( wxWindow *parent, wxPrintDialogData *data )
167 : wxPrintDialogBase(parent, wxID_ANY, _("Print"),
168 wxPoint(0, 0), wxSize(600, 600),
169 wxDEFAULT_DIALOG_STYLE |
170 wxTAB_TRAVERSAL)
171 {
172 if (data)
173 m_printDialogData = *data;
174
175 Init();
176 }
177
178 wxGnomePrintDialog::wxGnomePrintDialog( wxWindow *parent, wxPrintData *data )
179 : wxPrintDialogBase(parent, wxID_ANY, _("Print"),
180 wxPoint(0, 0), wxSize(600, 600),
181 wxDEFAULT_DIALOG_STYLE |
182 wxTAB_TRAVERSAL)
183 {
184 if (data)
185 m_printDialogData = *data;
186
187 Init();
188 }
189
190 void wxGnomePrintDialog::Init()
191 {
192 wxPrintData data = m_printDialogData.GetPrintData();
193
194 wxGnomePrintNativeData *native =
195 (wxGnomePrintNativeData*) data.GetNativeData();
196
197 m_widget = gnome_print_dialog_new( native->GetPrintJob(),
198 (guchar*)"Print",
199 GNOME_PRINT_DIALOG_RANGE|GNOME_PRINT_DIALOG_COPIES );
200
201 int flag = 0;
202 if (m_printDialogData.GetEnableSelection())
203 flag |= GNOME_PRINT_RANGE_SELECTION;
204 if (m_printDialogData.GetEnablePageNumbers())
205 flag |= GNOME_PRINT_RANGE_ALL|GNOME_PRINT_RANGE_RANGE;
206
207 gnome_print_dialog_construct_range_page( GNOME_PRINT_DIALOG( m_widget ),
208 flag,
209 m_printDialogData.GetMinPage(),
210 m_printDialogData.GetMaxPage(),
211 NULL,
212 NULL );
213 }
214
215 wxGnomePrintDialog::~wxGnomePrintDialog()
216 {
217 m_widget = NULL;
218 }
219
220 int wxGnomePrintDialog::ShowModal()
221 {
222 // Transfer data from m_printDalogData to dialog here
223
224 int response = gtk_dialog_run (GTK_DIALOG (m_widget));
225
226 if (response == GNOME_PRINT_DIALOG_RESPONSE_CANCEL)
227 {
228 gtk_widget_destroy(m_widget);
229 m_widget = NULL;
230
231 return wxID_CANCEL;
232 }
233
234 gint copies = 1;
235 gboolean collate = false;
236 gnome_print_dialog_get_copies( GNOME_PRINT_DIALOG(m_widget), &copies, &collate );
237 m_printDialogData.SetNoCopies( copies );
238 m_printDialogData.SetCollate( collate );
239
240 switch (gnome_print_dialog_get_range( GNOME_PRINT_DIALOG(m_widget) ))
241 {
242 case GNOME_PRINT_RANGE_SELECTION:
243 m_printDialogData.SetSelection( true );
244 break;
245 case GNOME_PRINT_RANGE_ALL:
246 m_printDialogData.SetAllPages( true );
247 m_printDialogData.SetFromPage( 0 );
248 m_printDialogData.SetToPage( 9999 );
249 break;
250 case GNOME_PRINT_RANGE_RANGE:
251 default:
252 gint start,end;
253 gnome_print_dialog_get_range_page( GNOME_PRINT_DIALOG(m_widget), &start, &end );
254 m_printDialogData.SetFromPage( start );
255 m_printDialogData.SetToPage( end );
256 break;
257 }
258
259 gtk_widget_destroy(m_widget);
260 m_widget = NULL;
261
262 if (response == GNOME_PRINT_DIALOG_RESPONSE_PREVIEW)
263 return wxID_PREVIEW;
264
265 return wxID_OK;
266 }
267
268 wxDC *wxGnomePrintDialog::GetPrintDC()
269 {
270 // Later
271 return NULL;
272 }
273
274 bool wxGnomePrintDialog::Validate()
275 {
276 return true;
277 }
278
279 bool wxGnomePrintDialog::TransferDataToWindow()
280 {
281 return true;
282 }
283
284 bool wxGnomePrintDialog::TransferDataFromWindow()
285 {
286 return true;
287 }
288
289 //----------------------------------------------------------------------------
290 // wxGnomePageSetupDialog
291 //----------------------------------------------------------------------------
292
293 IMPLEMENT_CLASS(wxGnomePageSetupDialog, wxPageSetupDialogBase)
294
295 wxGnomePageSetupDialog::wxGnomePageSetupDialog( wxWindow *parent,
296 wxPageSetupDialogData* data )
297 {
298 if (data)
299 m_pageDialogData = *data;
300
301 wxGnomePrintNativeData *native =
302 (wxGnomePrintNativeData*) m_pageDialogData.GetPrintData().GetNativeData();
303
304 // This is required as the page setup dialog
305 // calculates wrong values otherwise.
306 gnome_print_config_set( native->GetPrintConfig(),
307 (const guchar*) GNOME_PRINT_KEY_PREFERED_UNIT,
308 (const guchar*) "Pts" );
309
310 m_widget = gtk_dialog_new();
311
312 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( _("Page setup") ) );
313
314 GtkWidget *main = gnome_paper_selector_new_with_flags( native->GetPrintConfig(),
315 GNOME_PAPER_SELECTOR_MARGINS|GNOME_PAPER_SELECTOR_FEED_ORIENTATION );
316 gtk_container_set_border_width (GTK_CONTAINER (main), 8);
317 gtk_widget_show (main);
318
319 gtk_container_add( GTK_CONTAINER (GTK_DIALOG (m_widget)->vbox), main );
320
321 gtk_dialog_set_has_separator (GTK_DIALOG (m_widget), TRUE);
322
323 gtk_dialog_add_buttons (GTK_DIALOG (m_widget),
324 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
325 GTK_STOCK_OK, GTK_RESPONSE_OK,
326 NULL);
327
328 gtk_dialog_set_default_response (GTK_DIALOG (m_widget),
329 GTK_RESPONSE_OK);
330 }
331
332 wxGnomePageSetupDialog::~wxGnomePageSetupDialog()
333 {
334 }
335
336 wxPageSetupDialogData& wxGnomePageSetupDialog::GetPageSetupDialogData()
337 {
338 return m_pageDialogData;
339 }
340
341 int wxGnomePageSetupDialog::ShowModal()
342 {
343 wxGnomePrintNativeData *native =
344 (wxGnomePrintNativeData*) m_pageDialogData.GetPrintData().GetNativeData();
345 GnomePrintConfig *config = native->GetPrintConfig();
346
347 // Transfer data from m_pageDialogData to native dialog
348
349 int ret = gtk_dialog_run( GTK_DIALOG(m_widget) );
350
351 if (ret == GTK_RESPONSE_OK)
352 {
353 // Transfer data back to m_pageDialogData
354
355 // I don't know how querying the last parameter works
356 // I cannot test it as the dialog is currently broken
357 // anyways (it only works for points).
358 double ml,mr,mt,mb,pw,ph;
359 gnome_print_config_get_length (config,
360 (const guchar*) GNOME_PRINT_KEY_PAGE_MARGIN_LEFT, &ml, NULL);
361 gnome_print_config_get_length (config,
362 (const guchar*) GNOME_PRINT_KEY_PAGE_MARGIN_RIGHT, &mr, NULL);
363 gnome_print_config_get_length (config,
364 (const guchar*) GNOME_PRINT_KEY_PAGE_MARGIN_TOP, &mt, NULL);
365 gnome_print_config_get_length (config,
366 (const guchar*) GNOME_PRINT_KEY_PAGE_MARGIN_BOTTOM, &mb, NULL);
367 gnome_print_config_get_length (config,
368 (const guchar*) GNOME_PRINT_KEY_PAPER_WIDTH, &pw, NULL);
369 gnome_print_config_get_length (config,
370 (const guchar*) GNOME_PRINT_KEY_PAPER_HEIGHT, &ph, NULL);
371
372 // This probably assumes that the user entered the
373 // values in Pts. Since that is the only the dialog
374 // works right now, we need to fix this later.
375 const GnomePrintUnit *mm_unit = gnome_print_unit_get_by_abbreviation( (const guchar*) "mm" );
376 const GnomePrintUnit *pts_unit = gnome_print_unit_get_by_abbreviation( (const guchar*) "Pts" );
377 gnome_print_convert_distance( &ml, pts_unit, mm_unit );
378 gnome_print_convert_distance( &mr, pts_unit, mm_unit );
379 gnome_print_convert_distance( &mt, pts_unit, mm_unit );
380 gnome_print_convert_distance( &mb, pts_unit, mm_unit );
381 gnome_print_convert_distance( &pw, pts_unit, mm_unit );
382 gnome_print_convert_distance( &ph, pts_unit, mm_unit );
383
384 m_pageDialogData.SetMarginTopLeft( wxPoint( (int)(ml+0.5), (int)(mt+0.5)) );
385 m_pageDialogData.SetMarginBottomRight( wxPoint( (int)(mr+0.5), (int)(mb+0.5)) );
386
387 m_pageDialogData.SetPaperSize( wxSize( (int)(pw+0.5), (int)(ph+0.5) ) );
388
389 #if 0
390 wxPrintf( wxT("paper %d %d, top margin %d\n"),
391 m_pageDialogData.GetPaperSize().x,
392 m_pageDialogData.GetPaperSize().y,
393 m_pageDialogData.GetMarginTopLeft().x );
394 #endif
395
396 ret = wxID_OK;
397 }
398 else
399 {
400 ret = wxID_CANCEL;
401 }
402
403 gtk_widget_destroy( m_widget );
404 m_widget = NULL;
405
406 return ret;
407 }
408
409 bool wxGnomePageSetupDialog::Validate()
410 {
411 return true;
412 }
413
414 bool wxGnomePageSetupDialog::TransferDataToWindow()
415 {
416 return true;
417 }
418
419 bool wxGnomePageSetupDialog::TransferDataFromWindow()
420 {
421 return true;
422 }
423
424 //----------------------------------------------------------------------------
425 // wxGnomePrinter
426 //----------------------------------------------------------------------------
427
428 IMPLEMENT_CLASS(wxGnomePrinter, wxPrinterBase)
429
430 wxGnomePrinter::wxGnomePrinter( wxPrintDialogData *data ) :
431 wxPrinterBase( data )
432 {
433 m_gpc = NULL;
434 m_native_preview = false;
435 }
436
437 wxGnomePrinter::~wxGnomePrinter()
438 {
439 }
440
441 bool wxGnomePrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt )
442 {
443 if (!printout)
444 {
445 sm_lastError = wxPRINTER_ERROR;
446 return false;
447 }
448
449 wxPrintData printdata = GetPrintDialogData().GetPrintData();
450 wxGnomePrintNativeData *native =
451 (wxGnomePrintNativeData*) printdata.GetNativeData();
452
453 GnomePrintJob *job = gnome_print_job_new( native->GetPrintConfig() );
454 m_gpc = gnome_print_job_get_context (job);
455
456 // The GnomePrintJob is temporarily stored in the
457 // native print data as the native print dialog
458 // needs to access it.
459 native->SetPrintJob( job );
460
461
462 printout->SetIsPreview(false);
463
464 if (m_printDialogData.GetMinPage() < 1)
465 m_printDialogData.SetMinPage(1);
466 if (m_printDialogData.GetMaxPage() < 1)
467 m_printDialogData.SetMaxPage(9999);
468
469 wxDC *dc;
470 if (prompt)
471 dc = PrintDialog( parent );
472 else
473 dc = new wxGnomePrintDC( this );
474
475 if (m_native_preview)
476 printout->SetIsPreview(true);
477
478 if (!dc)
479 {
480 gnome_print_job_close( job );
481 g_object_unref (G_OBJECT (job));
482 sm_lastError = wxPRINTER_ERROR;
483 return false;
484 }
485
486 wxSize ScreenPixels = wxGetDisplaySize();
487 wxSize ScreenMM = wxGetDisplaySizeMM();
488
489 printout->SetPPIScreen( (int) ((ScreenPixels.GetWidth() * 25.4) / ScreenMM.GetWidth()),
490 (int) ((ScreenPixels.GetHeight() * 25.4) / ScreenMM.GetHeight()) );
491 printout->SetPPIPrinter( wxGnomePrintDC::GetResolution(),
492 wxGnomePrintDC::GetResolution() );
493
494 printout->SetDC(dc);
495
496 int w, h;
497 dc->GetSize(&w, &h);
498 printout->SetPageSizePixels((int)w, (int)h);
499 dc->GetSizeMM(&w, &h);
500 printout->SetPageSizeMM((int)w, (int)h);
501
502 printout->OnPreparePrinting();
503
504 // Get some parameters from the printout, if defined
505 int fromPage, toPage;
506 int minPage, maxPage;
507 printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
508
509 if (maxPage == 0)
510 {
511 gnome_print_job_close( job );
512 g_object_unref (G_OBJECT (job));
513 sm_lastError = wxPRINTER_ERROR;
514 return false;
515 }
516
517 printout->OnBeginPrinting();
518
519 int minPageNum = minPage, maxPageNum = maxPage;
520
521 if ( !m_printDialogData.GetAllPages() )
522 {
523 minPageNum = m_printDialogData.GetFromPage();
524 maxPageNum = m_printDialogData.GetToPage();
525 }
526
527
528 int copyCount;
529 for ( copyCount = 1;
530 copyCount <= m_printDialogData.GetNoCopies();
531 copyCount++ )
532 {
533 if (!printout->OnBeginDocument(minPageNum, maxPageNum))
534 {
535 wxLogError(_("Could not start printing."));
536 sm_lastError = wxPRINTER_ERROR;
537 break;
538 }
539
540 int pn;
541 for ( pn = minPageNum;
542 pn <= maxPageNum && printout->HasPage(pn);
543 pn++ )
544 {
545 dc->StartPage();
546 printout->OnPrintPage(pn);
547 dc->EndPage();
548 }
549
550 printout->OnEndDocument();
551 printout->OnEndPrinting();
552 }
553
554 gnome_print_job_close( job );
555 if (m_native_preview)
556 {
557 wxString title( _("Print preview") );
558 gtk_widget_show( gnome_print_job_preview_new( job, (const guchar*)(const char*)wxGTK_CONV(title) ));
559 }
560 else
561 {
562 gnome_print_job_print( job );
563 }
564
565 g_object_unref (G_OBJECT (job));
566 delete dc;
567
568 return (sm_lastError == wxPRINTER_NO_ERROR);
569 }
570
571 wxDC* wxGnomePrinter::PrintDialog( wxWindow *parent )
572 {
573 wxGnomePrintDialog dialog( parent, &m_printDialogData );
574 int ret = dialog.ShowModal();
575 if (ret == wxID_CANCEL)
576 {
577 sm_lastError = wxPRINTER_ERROR;
578 return NULL;
579 }
580
581 m_native_preview = ret == wxID_PREVIEW;
582
583 m_printDialogData = dialog.GetPrintDialogData();
584 return new wxGnomePrintDC( this );
585 }
586
587 bool wxGnomePrinter::Setup( wxWindow *parent )
588 {
589 return false;
590 }
591
592 //-----------------------------------------------------------------------------
593 // wxGnomePrintDC
594 //-----------------------------------------------------------------------------
595
596 IMPLEMENT_CLASS(wxGnomePrintDC, wxDCBase)
597
598 wxGnomePrintDC::wxGnomePrintDC( wxGnomePrinter *printer )
599 {
600 m_printer = printer;
601
602 m_gpc = printer->GetPrintContext();
603
604 m_layout = gnome_print_pango_create_layout( m_gpc );
605 m_fontdesc = pango_font_description_from_string( "Sans 12" );
606
607 m_currentRed = 0;
608 m_currentBlue = 0;
609 m_currentGreen = 0;
610
611 m_signX = 1; // default x-axis left to right
612 m_signY = -1; // default y-axis bottom up -> top down
613 }
614
615 wxGnomePrintDC::~wxGnomePrintDC()
616 {
617 }
618
619 bool wxGnomePrintDC::Ok() const
620 {
621 return true;
622 }
623
624 bool wxGnomePrintDC::DoFloodFill(wxCoord x1, wxCoord y1, const wxColour &col, int style )
625 {
626 return false;
627 }
628
629 bool wxGnomePrintDC::DoGetPixel(wxCoord x1, wxCoord y1, wxColour *col) const
630 {
631 return false;
632 }
633
634 void wxGnomePrintDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
635 {
636 if (m_pen.GetStyle() == wxTRANSPARENT) return;
637
638 SetPen( m_pen );
639
640 gnome_print_moveto ( m_gpc, XLOG2DEV(x1), YLOG2DEV(y1) );
641 gnome_print_lineto ( m_gpc, XLOG2DEV(x2), YLOG2DEV(y2) );
642 gnome_print_stroke ( m_gpc);
643
644 CalcBoundingBox( x1, y1 );
645 CalcBoundingBox( x2, y2 );
646 }
647
648 void wxGnomePrintDC::DoCrossHair(wxCoord x, wxCoord y)
649 {
650 }
651
652 void wxGnomePrintDC::DoDrawArc(wxCoord x1,wxCoord y1,wxCoord x2,wxCoord y2,wxCoord xc,wxCoord yc)
653 {
654 }
655
656 void wxGnomePrintDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
657 {
658 }
659
660 void wxGnomePrintDC::DoDrawPoint(wxCoord x, wxCoord y)
661 {
662 }
663
664 void wxGnomePrintDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
665 {
666 if (m_pen.GetStyle() == wxTRANSPARENT) return;
667
668 if (n <= 0) return;
669
670 SetPen (m_pen);
671
672 int i;
673 for ( i =0; i<n ; i++ )
674 CalcBoundingBox( XLOG2DEV(points[i].x+xoffset), YLOG2DEV(points[i].y+yoffset));
675
676 gnome_print_moveto ( m_gpc, XLOG2DEV(points[0].x+xoffset), YLOG2DEV(points[0].y+yoffset) );
677
678 for (i = 1; i < n; i++)
679 gnome_print_lineto ( m_gpc, XLOG2DEV(points[i].x+xoffset), YLOG2DEV(points[i].y+yoffset) );
680
681 gnome_print_stroke ( m_gpc);
682 }
683
684 void wxGnomePrintDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int fillStyle)
685 {
686 }
687
688 void wxGnomePrintDC::DoDrawPolyPolygon(int n, int count[], wxPoint points[], wxCoord xoffset, wxCoord yoffset, int fillStyle)
689 {
690 }
691
692 void wxGnomePrintDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
693 {
694 if (m_brush.GetStyle () != wxTRANSPARENT)
695 {
696 SetBrush( m_brush );
697
698 gnome_print_newpath( m_gpc );
699 gnome_print_moveto( m_gpc, XLOG2DEV(x), YLOG2DEV(y) );
700 gnome_print_lineto( m_gpc, XLOG2DEV(x + width), YLOG2DEV(y) );
701 gnome_print_lineto( m_gpc, XLOG2DEV(x + width), YLOG2DEV(y + height) );
702 gnome_print_lineto( m_gpc, XLOG2DEV(x), YLOG2DEV(y + height) );
703 gnome_print_closepath( m_gpc );
704 gnome_print_fill( m_gpc );
705
706 CalcBoundingBox( x, y );
707 CalcBoundingBox( x + width, y + height );
708 }
709
710 if (m_pen.GetStyle () != wxTRANSPARENT)
711 {
712 SetPen (m_pen);
713
714 gnome_print_newpath( m_gpc );
715 gnome_print_moveto( m_gpc, XLOG2DEV(x), YLOG2DEV(y) );
716 gnome_print_lineto( m_gpc, XLOG2DEV(x + width), YLOG2DEV(y) );
717 gnome_print_lineto( m_gpc, XLOG2DEV(x + width), YLOG2DEV(y + height) );
718 gnome_print_lineto( m_gpc, XLOG2DEV(x), YLOG2DEV(y + height) );
719 gnome_print_closepath( m_gpc );
720 gnome_print_stroke( m_gpc );
721
722 CalcBoundingBox( x, y );
723 CalcBoundingBox( x + width, y + height );
724 }
725 }
726
727 void wxGnomePrintDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius)
728 {
729 }
730
731 void wxGnomePrintDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
732 {
733 if (m_brush.GetStyle () != wxTRANSPARENT)
734 {
735 SetBrush( m_brush );
736
737 gnome_print_newpath( m_gpc );
738 gnome_print_moveto( m_gpc,
739 XLOG2DEV(x), YLOG2DEV(y+height/2) );
740
741 // start with top half
742 gnome_print_curveto( m_gpc,
743 XLOG2DEV(x), YLOG2DEV(y),
744 XLOG2DEV(x+width), YLOG2DEV(y),
745 XLOG2DEV(x+width), YLOG2DEV(y+height/2) );
746 // lower half
747 gnome_print_curveto( m_gpc,
748 XLOG2DEV(x+width), YLOG2DEV(y+height),
749 XLOG2DEV(x), YLOG2DEV(y+height),
750 XLOG2DEV(x), YLOG2DEV(y+height/2) );
751
752 gnome_print_closepath( m_gpc );
753 gnome_print_fill( m_gpc );
754
755 CalcBoundingBox( x, y );
756 CalcBoundingBox( x + width, y + height );
757 }
758
759 if (m_pen.GetStyle () != wxTRANSPARENT)
760 {
761 SetPen (m_pen);
762
763 gnome_print_newpath( m_gpc );
764 gnome_print_moveto( m_gpc,
765 XLOG2DEV(x), YLOG2DEV(y+height/2) );
766
767 // start with top half
768 gnome_print_curveto( m_gpc,
769 XLOG2DEV(x), YLOG2DEV(y),
770 XLOG2DEV(x+width), YLOG2DEV(y),
771 XLOG2DEV(x+width), YLOG2DEV(y+height/2) );
772 // lower half
773 gnome_print_curveto( m_gpc,
774 XLOG2DEV(x+width), YLOG2DEV(y+height),
775 XLOG2DEV(x), YLOG2DEV(y+height),
776 XLOG2DEV(x), YLOG2DEV(y+height/2) );
777
778 gnome_print_closepath( m_gpc );
779 gnome_print_stroke( m_gpc );
780
781 CalcBoundingBox( x, y );
782 CalcBoundingBox( x + width, y + height );
783 }
784 }
785
786 void wxGnomePrintDC::DoDrawSpline(wxList *points)
787 {
788 }
789
790 bool wxGnomePrintDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
791 wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask,
792 wxCoord xsrcMask, wxCoord ysrcMask)
793 {
794 return false;
795 }
796
797 void wxGnomePrintDC::DoDrawIcon( const wxIcon& icon, wxCoord x, wxCoord y )
798 {
799 DoDrawBitmap( icon, x, y, true );
800 }
801
802 void wxGnomePrintDC::DoDrawBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y, bool useMask )
803 {
804 if (!bitmap.Ok()) return;
805
806 if (bitmap.HasPixbuf())
807 {
808 GdkPixbuf *pixbuf = bitmap.GetPixbuf();
809 guchar *raw_image = gdk_pixbuf_get_pixels( pixbuf );
810 bool has_alpha = gdk_pixbuf_get_has_alpha( pixbuf );
811 int rowstride = gdk_pixbuf_get_rowstride( pixbuf );
812 int height = gdk_pixbuf_get_height( pixbuf );
813 int width = gdk_pixbuf_get_width( pixbuf );
814
815 gnome_print_gsave( m_gpc );
816 double matrix[6];
817 matrix[0] = XLOG2DEVREL(width);
818 matrix[1] = 0;
819 matrix[2] = 0;
820 matrix[3] = YLOG2DEVREL(height);
821 matrix[4] = XLOG2DEV(x);
822 matrix[5] = YLOG2DEV(y+height);
823 gnome_print_concat( m_gpc, matrix );
824 gnome_print_moveto( m_gpc, 0, 0 );
825 if (has_alpha)
826 gnome_print_rgbaimage( m_gpc, (guchar *)raw_image, width, height, rowstride );
827 else
828 gnome_print_rgbimage( m_gpc, (guchar *)raw_image, width, height, rowstride );
829 gnome_print_grestore( m_gpc );
830 }
831 else
832 {
833 wxImage image = bitmap.ConvertToImage();
834
835 if (!image.Ok()) return;
836
837 gnome_print_gsave( m_gpc );
838 double matrix[6];
839 matrix[0] = XLOG2DEVREL(image.GetWidth());
840 matrix[1] = 0;
841 matrix[2] = 0;
842 matrix[3] = YLOG2DEVREL(image.GetHeight());
843 matrix[4] = XLOG2DEV(x);
844 matrix[5] = YLOG2DEV(y+image.GetHeight());
845 gnome_print_concat( m_gpc, matrix );
846 gnome_print_moveto( m_gpc, 0, 0 );
847 gnome_print_rgbimage( m_gpc, (guchar*) image.GetData(), image.GetWidth(), image.GetHeight(), image.GetWidth()*3 );
848 gnome_print_grestore( m_gpc );
849 }
850 }
851
852 void wxGnomePrintDC::DoDrawText(const wxString& text, wxCoord x, wxCoord y )
853 {
854 DoDrawRotatedText( text, x, y, 0.0 );
855 }
856
857 void wxGnomePrintDC::DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle)
858 {
859 x = XLOG2DEV(x);
860 y = YLOG2DEV(y);
861
862 bool underlined = m_font.Ok() && m_font.GetUnderlined();
863
864 #if wxUSE_UNICODE
865 const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
866 #else
867 const wxWCharBuffer wdata = wxConvLocal.cMB2WC( text );
868 if ( !wdata )
869 return;
870 const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
871 #endif
872
873 size_t datalen = strlen((const char*)data);
874 pango_layout_set_text( m_layout, (const char*) data, datalen);
875
876 if (underlined)
877 {
878 PangoAttrList *attrs = pango_attr_list_new();
879 PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
880 a->start_index = 0;
881 a->end_index = datalen;
882 pango_attr_list_insert(attrs, a);
883 pango_layout_set_attributes(m_layout, attrs);
884 pango_attr_list_unref(attrs);
885 }
886
887 if (m_textForegroundColour.Ok())
888 {
889 unsigned char red = m_textForegroundColour.Red();
890 unsigned char blue = m_textForegroundColour.Blue();
891 unsigned char green = m_textForegroundColour.Green();
892
893 if (!(red == m_currentRed && green == m_currentGreen && blue == m_currentBlue))
894 {
895 double redPS = (double)(red) / 255.0;
896 double bluePS = (double)(blue) / 255.0;
897 double greenPS = (double)(green) / 255.0;
898
899 gnome_print_setrgbcolor( m_gpc, redPS, bluePS, greenPS );
900
901 m_currentRed = red;
902 m_currentBlue = blue;
903 m_currentGreen = green;
904 }
905 }
906
907 int w,h;
908
909 if (fabs(m_scaleY - 1.0) > 0.00001)
910 {
911 // If there is a user or actually any scale applied to
912 // the device context, scale the font.
913
914 // scale font description
915 gint oldSize = pango_font_description_get_size( m_fontdesc );
916 double size = oldSize;
917 size = size * m_scaleY;
918 pango_font_description_set_size( m_fontdesc, (gint)size );
919
920 // actually apply scaled font
921 pango_layout_set_font_description( m_layout, m_fontdesc );
922
923 pango_layout_get_pixel_size( m_layout, &w, &h );
924 #if 0
925 if ( m_backgroundMode == wxSOLID )
926 {
927 gdk_gc_set_foreground(m_textGC, m_textBackgroundColour.GetColor());
928 gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h);
929 gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor());
930 }
931 #endif
932 // Draw layout.
933 gnome_print_moveto (m_gpc, x, y);
934 if (fabs(angle) > 0.00001)
935 {
936 gnome_print_gsave( m_gpc );
937 gnome_print_rotate( m_gpc, angle );
938 gnome_print_pango_layout( m_gpc, m_layout );
939 gnome_print_grestore( m_gpc );
940 }
941 else
942 {
943 gnome_print_pango_layout( m_gpc, m_layout );
944 }
945
946 // reset unscaled size
947 pango_font_description_set_size( m_fontdesc, oldSize );
948
949 // actually apply unscaled font
950 pango_layout_set_font_description( m_layout, m_fontdesc );
951 }
952 else
953 {
954 pango_layout_get_pixel_size( m_layout, &w, &h );
955 #if 0
956 if ( m_backgroundMode == wxSOLID )
957 {
958 gdk_gc_set_foreground(m_textGC, m_textBackgroundColour.GetColor());
959 gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h);
960 gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor());
961 }
962 #endif
963 // Draw layout.
964 gnome_print_moveto (m_gpc, x, y);
965 if (fabs(angle) > 0.00001)
966 {
967 gnome_print_gsave( m_gpc );
968 gnome_print_rotate( m_gpc, angle );
969 gnome_print_pango_layout( m_gpc, m_layout );
970 gnome_print_grestore( m_gpc );
971 }
972 else
973 {
974 gnome_print_pango_layout( m_gpc, m_layout );
975 }
976 }
977
978 if (underlined)
979 {
980 // undo underline attributes setting:
981 pango_layout_set_attributes(m_layout, NULL);
982 }
983
984 CalcBoundingBox (x + w, y + h);
985 }
986
987 void wxGnomePrintDC::Clear()
988 {
989 }
990
991 void wxGnomePrintDC::SetFont( const wxFont& font )
992 {
993 m_font = font;
994
995 if (m_font.Ok())
996 {
997 if (m_fontdesc)
998 pango_font_description_free( m_fontdesc );
999
1000 m_fontdesc = pango_font_description_copy( m_font.GetNativeFontInfo()->description );
1001
1002 pango_layout_set_font_description( m_layout, m_fontdesc );
1003 }
1004 }
1005
1006 void wxGnomePrintDC::SetPen( const wxPen& pen )
1007 {
1008 if (!pen.Ok()) return;
1009
1010 // TODO: support for pen styles other than solid (use gnome_print_setdash)
1011
1012 m_pen = pen;
1013
1014 gnome_print_setlinewidth( m_gpc, XLOG2DEVREL( 1000 * m_pen.GetWidth() ) / 1000.0f );
1015
1016
1017 static const double dotted[] = {2.0, 5.0};
1018 static const double short_dashed[] = {4.0, 4.0};
1019 static const double wxCoord_dashed[] = {4.0, 8.0};
1020 static const double dotted_dashed[] = {6.0, 6.0, 2.0, 6.0};
1021
1022 switch (m_pen.GetStyle())
1023 {
1024 case wxDOT: gnome_print_setdash( m_gpc, 2, dotted, 0 ); break;
1025 case wxSHORT_DASH: gnome_print_setdash( m_gpc, 2, short_dashed, 0 ); break;
1026 case wxLONG_DASH: gnome_print_setdash( m_gpc, 2, wxCoord_dashed, 0 ); break;
1027 case wxDOT_DASH: gnome_print_setdash( m_gpc, 4, dotted_dashed, 0 ); break;
1028 case wxSOLID:
1029 case wxTRANSPARENT:
1030 default: gnome_print_setdash( m_gpc, 0, NULL, 0 ); break;
1031 }
1032
1033
1034 unsigned char red = m_pen.GetColour().Red();
1035 unsigned char blue = m_pen.GetColour().Blue();
1036 unsigned char green = m_pen.GetColour().Green();
1037
1038 if (!(red == m_currentRed && green == m_currentGreen && blue == m_currentBlue))
1039 {
1040 double redPS = (double)(red) / 255.0;
1041 double bluePS = (double)(blue) / 255.0;
1042 double greenPS = (double)(green) / 255.0;
1043
1044 gnome_print_setrgbcolor( m_gpc, redPS, bluePS, greenPS );
1045
1046 m_currentRed = red;
1047 m_currentBlue = blue;
1048 m_currentGreen = green;
1049 }
1050 }
1051
1052 void wxGnomePrintDC::SetBrush( const wxBrush& brush )
1053 {
1054 if (!brush.Ok()) return;
1055
1056 m_brush = brush;
1057
1058 // Brush colour
1059 unsigned char red = m_brush.GetColour().Red();
1060 unsigned char blue = m_brush.GetColour().Blue();
1061 unsigned char green = m_brush.GetColour().Green();
1062
1063 if (!m_colour)
1064 {
1065 // Anything not white is black
1066 if (! (red == (unsigned char) 255 &&
1067 blue == (unsigned char) 255 &&
1068 green == (unsigned char) 255) )
1069 {
1070 red = (unsigned char) 0;
1071 green = (unsigned char) 0;
1072 blue = (unsigned char) 0;
1073 }
1074 // setgray here ?
1075 }
1076
1077 if (!(red == m_currentRed && green == m_currentGreen && blue == m_currentBlue))
1078 {
1079 double redPS = (double)(red) / 255.0;
1080 double bluePS = (double)(blue) / 255.0;
1081 double greenPS = (double)(green) / 255.0;
1082
1083 gnome_print_setrgbcolor( m_gpc, redPS, bluePS, greenPS );
1084
1085 m_currentRed = red;
1086 m_currentBlue = blue;
1087 m_currentGreen = green;
1088 }
1089 }
1090
1091 void wxGnomePrintDC::SetLogicalFunction( int function )
1092 {
1093 }
1094
1095 void wxGnomePrintDC::SetBackground( const wxBrush& brush )
1096 {
1097 }
1098
1099 void wxGnomePrintDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
1100 {
1101 }
1102
1103 void wxGnomePrintDC::DestroyClippingRegion()
1104 {
1105 }
1106
1107 bool wxGnomePrintDC::StartDoc(const wxString& message)
1108 {
1109 SetDeviceOrigin( 0,0 );
1110
1111 return true;
1112 }
1113
1114 void wxGnomePrintDC::EndDoc()
1115 {
1116 gnome_print_end_doc( m_gpc );
1117 }
1118
1119 void wxGnomePrintDC::StartPage()
1120 {
1121 gnome_print_beginpage( m_gpc, (const guchar*) "1" );
1122 }
1123
1124 void wxGnomePrintDC::EndPage()
1125 {
1126 gnome_print_showpage( m_gpc );
1127 }
1128
1129 wxCoord wxGnomePrintDC::GetCharHeight() const
1130 {
1131 pango_layout_set_text( m_layout, "H", 1 );
1132
1133 int w,h;
1134 pango_layout_get_pixel_size( m_layout, &w, &h );
1135
1136 return h;
1137 }
1138
1139 wxCoord wxGnomePrintDC::GetCharWidth() const
1140 {
1141 pango_layout_set_text( m_layout, "H", 1 );
1142
1143 int w,h;
1144 pango_layout_get_pixel_size( m_layout, &w, &h );
1145
1146 return w;
1147 }
1148
1149 void wxGnomePrintDC::DoGetTextExtent(const wxString& string, wxCoord *width, wxCoord *height,
1150 wxCoord *descent,
1151 wxCoord *externalLeading,
1152 wxFont *theFont ) const
1153 {
1154 if ( width )
1155 *width = 0;
1156 if ( height )
1157 *height = 0;
1158 if ( descent )
1159 *descent = 0;
1160 if ( externalLeading )
1161 *externalLeading = 0;
1162
1163 if (string.IsEmpty())
1164 {
1165 return;
1166 }
1167
1168 // Set new font description
1169 if (theFont)
1170 pango_layout_set_font_description( m_layout, theFont->GetNativeFontInfo()->description );
1171
1172 // Set layout's text
1173 #if wxUSE_UNICODE
1174 const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
1175 const char *dataUTF8 = (const char *)data;
1176 #else
1177 const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string );
1178 if ( !wdata )
1179 {
1180 if (width) (*width) = 0;
1181 if (height) (*height) = 0;
1182 return;
1183 }
1184 const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
1185 const char *dataUTF8 = (const char *)data;
1186 #endif
1187
1188 if ( !dataUTF8 )
1189 {
1190 // hardly ideal, but what else can we do if conversion failed?
1191 return;
1192 }
1193
1194 pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) );
1195
1196 int w,h;
1197 pango_layout_get_pixel_size( m_layout, &w, &h );
1198
1199 if (width)
1200 *width = (wxCoord) w;
1201 if (height)
1202 *height = (wxCoord) h;
1203 if (descent)
1204 {
1205 PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
1206 int baseline = pango_layout_iter_get_baseline(iter);
1207 pango_layout_iter_free(iter);
1208 *descent = h - PANGO_PIXELS(baseline);
1209 }
1210
1211 // Reset old font description
1212 if (theFont)
1213 pango_layout_set_font_description( m_layout, m_fontdesc );
1214 }
1215
1216 void wxGnomePrintDC::DoGetSize(int* width, int* height) const
1217 {
1218 wxGnomePrintNativeData *native =
1219 (wxGnomePrintNativeData*) m_printData.GetNativeData();
1220
1221 // Query page size. This seems to omit the margins
1222 // right now, although it shouldn't
1223 double pw,ph;
1224 gnome_print_job_get_page_size( native->GetPrintJob(), &pw, &ph );
1225
1226 if (width)
1227 *width = (int) (pw + 0.5);
1228 if (height)
1229 *height = (int) (ph + 0.5);
1230 }
1231
1232 void wxGnomePrintDC::DoGetSizeMM(int *width, int *height) const
1233 {
1234 wxGnomePrintNativeData *native =
1235 (wxGnomePrintNativeData*) m_printData.GetNativeData();
1236
1237 // This code assumes values in Pts.
1238
1239 double pw,ph;
1240 gnome_print_job_get_page_size( native->GetPrintJob(), &pw, &ph );
1241
1242 // Convert to mm.
1243
1244 const GnomePrintUnit *mm_unit = gnome_print_unit_get_by_abbreviation( (const guchar*) "mm" );
1245 const GnomePrintUnit *pts_unit = gnome_print_unit_get_by_abbreviation( (const guchar*) "Pts" );
1246 gnome_print_convert_distance( &pw, pts_unit, mm_unit );
1247 gnome_print_convert_distance( &ph, pts_unit, mm_unit );
1248
1249 if (width)
1250 *width = (int) (pw + 0.5);
1251 if (height)
1252 *height = (int) (ph + 0.5);
1253 }
1254
1255 wxSize wxGnomePrintDC::GetPPI() const
1256 {
1257 return wxSize(72,72);
1258 }
1259
1260 void wxGnomePrintDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
1261 {
1262 m_signX = (xLeftRight ? 1 : -1);
1263 m_signY = (yBottomUp ? 1 : -1);
1264
1265 ComputeScaleAndOrigin();
1266 }
1267
1268 void wxGnomePrintDC::SetDeviceOrigin( wxCoord x, wxCoord y )
1269 {
1270 int h = 0;
1271 int w = 0;
1272 GetSize( &w, &h );
1273
1274 wxDC::SetDeviceOrigin( x, h-y );
1275 }
1276
1277 void wxGnomePrintDC::SetResolution(int ppi)
1278 {
1279 }
1280
1281 int wxGnomePrintDC::GetResolution()
1282 {
1283 return 72;
1284 }
1285
1286
1287 class wxGnomePrintModule: public wxModule
1288 {
1289 public:
1290 wxGnomePrintModule() {}
1291 bool OnInit() { wxPrintFactory::SetPrintFactory( new wxGnomePrintFactory ); return true; }
1292 void OnExit() { }
1293
1294 private:
1295 DECLARE_DYNAMIC_CLASS(wxGnomePrintModule)
1296 };
1297
1298 IMPLEMENT_DYNAMIC_CLASS(wxGnomePrintModule, wxModule)
1299
1300 #endif
1301 // wxUSE_LIBGNOMEPRINT