NTK 1.3.0
Fl_PostScript.cxx
1//
2// "$Id: Fl_PostScript.cxx 8623 2011-04-24 17:09:41Z AlbrechtS $"
3//
4// PostScript device support for the Fast Light Tool Kit (FLTK).
5//
6// Copyright 2010-2011 by Bill Spitzak and others.
7//
8// This library is free software; you can redistribute it and/or
9// modify it under the terms of the GNU Library General Public
10// License as published by the Free Software Foundation; either
11// version 2 of the License, or (at your option) any later version.
12//
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// Library General Public License for more details.
17//
18// You should have received a copy of the GNU Library General Public
19// License along with this library; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21// USA.
22//
23// Please report all bugs and problems to:
24//
25// http://www.fltk.org/str.php
26//
27
28#include <config.h>
29#include <FL/Fl_Cairo.H>
30#include <FL/Fl.H>
31#include <FL/fl_ask.H>
32#include <FL/fl_draw.H>
33#include <stdio.h>
34#include <FL/Fl_PostScript.H>
36#if defined(USE_X11)
37#include "Fl_Font.H"
38#if USE_XFT
39#include <X11/Xft/Xft.h>
40#endif
41#endif
42
43const char *Fl_PostScript_Graphics_Driver::class_id = "Fl_PostScript_Graphics_Driver";
44const char *Fl_PostScript_File_Device::class_id = "Fl_PostScript_File_Device";
46const char *Fl_PostScript_File_Device::file_chooser_title = "Select a .ps file";
47
52{
53 close_cmd_ = 0;
54 //lang_level_ = 3;
55 lang_level_ = 2;
56 mask = 0;
57 ps_filename_ = NULL;
58 scale_x = scale_y = 1.;
59 bg_r = bg_g = bg_b = 255;
60}
61
64 if(ps_filename_) free(ps_filename_);
65}
66
71{
72#ifdef __APPLE__
73 gc = fl_gc; // the display context is used by fl_text_extents()
74#endif
76}
77
85
86
98{
103 fnfc.filter("PostScript\t*.ps\n");
104 // Show native chooser
105 if ( fnfc.show() ) return 1;
107 ps->output = fopen(fnfc.filename(), "w");
108 if(ps->output == NULL) return 2;
109 ps->ps_filename_ = strdup(fnfc.filename());
110 ps->start_postscript(pagecount, format, layout);
111 this->set_current();
112 return 0;
113}
114
115static int dont_close(FILE *f)
116{
117 return 0;
118}
119
130int Fl_PostScript_File_Device::start_job (FILE *ps_output, int pagecount,
132{
134 ps->output = ps_output;
135 ps->ps_filename_ = NULL;
136 ps->start_postscript(pagecount, format, layout);
137 ps->close_command(dont_close); // so that end_job() doesn't close the file
138 this->set_current();
139 return 0;
140}
141
149
150#ifndef FL_DOXYGEN
151
152#if ! (defined(__APPLE__) || defined(WIN32) )
153 #include "print_panel.cxx"
154#endif
155
156// Prolog string
157
158static const char * prolog =
159"%%BeginProlog\n"
160"/L { /y2 exch def\n"
161"/x2 exch def\n"
162"/y1 exch def\n"
163"/x1 exch def\n"
164"newpath x1 y1 moveto x2 y2 lineto\n"
165"stroke}\n"
166"bind def\n"
167
168
169"/R { /dy exch def\n"
170"/dx exch def\n"
171"/y exch def\n"
172"/x exch def\n"
173"newpath\n"
174"x y moveto\n"
175"dx 0 rlineto\n"
176"0 dy rlineto\n"
177"dx neg 0 rlineto\n"
178"closepath stroke\n"
179"} bind def\n"
180
181"/CL {\n"
182"/dy exch def\n"
183"/dx exch def\n"
184"/y exch def\n"
185"/x exch def\n"
186"newpath\n"
187"x y moveto\n"
188"dx 0 rlineto\n"
189"0 dy rlineto\n"
190"dx neg 0 rlineto\n"
191"closepath\n"
192"clip\n"
193"} bind def\n"
194
195"/FR { /dy exch def\n"
196"/dx exch def\n"
197"/y exch def\n"
198"/x exch def\n"
199"currentlinewidth 0 setlinewidth newpath\n"
200"x y moveto\n"
201"dx 0 rlineto\n"
202"0 dy rlineto\n"
203"dx neg 0 rlineto\n"
204"closepath fill setlinewidth\n"
205"} bind def\n"
206
207"/GS { gsave } bind def\n"
208"/GR { grestore } bind def\n"
209
210"/SP { showpage } bind def\n"
211"/LW { setlinewidth } bind def\n"
212"/CF /Courier def\n"
213"/SF { /CF exch def } bind def\n"
214"/fsize 12 def\n"
215"/FS { /fsize exch def fsize CF findfont exch scalefont setfont }def \n"
216
217
218"/GL { setgray } bind def\n"
219"/SRGB { setrgbcolor } bind def\n"
220
221// color images
222
223"/CI { GS /py exch def /px exch def /sy exch def /sx exch def\n"
224"translate \n"
225"sx sy scale px py 8 \n"
226"[ px 0 0 py neg 0 py ]\n"
227"currentfile /ASCIIHexDecode filter\n false 3"
228" colorimage GR\n"
229"} bind def\n"
230
231// gray images
232
233"/GI { GS /py exch def /px exch def /sy exch def /sx exch def \n"
234"translate \n"
235"sx sy scale px py 8 \n"
236
237
238"[ px 0 0 py neg 0 py ]\n"
239"currentfile /ASCIIHexDecode filter\n"
240"image GR\n"
241"} bind def\n"
242
243// single-color bitmask
244
245"/MI { GS /py exch def /px exch def /sy exch def /sx exch def \n"
246"translate \n"
247"sx sy scale px py true \n"
248"[ px 0 0 py neg 0 py ]\n"
249"currentfile /ASCIIHexDecode filter\n"
250"imagemask GR\n"
251"} bind def\n"
252
253
254// path
255
256"/BFP { newpath moveto } def\n"
257"/BP { newpath } bind def \n"
258"/PL { lineto } bind def \n"
259"/PM { moveto } bind def \n"
260"/MT { moveto } bind def \n"
261"/LT { lineto } bind def \n"
262"/EFP { closepath fill } bind def\n" //was:stroke
263"/ELP { stroke } bind def\n"
264"/ECP { closepath stroke } bind def\n" // Closed (loop)
265"/LW { setlinewidth } bind def\n"
266
267// ////////////////////////// misc ////////////////
268"/TR { translate } bind def\n"
269"/CT { concat } bind def\n"
270"/RCT { matrix invertmatrix concat} bind def\n"
271"/SC { scale } bind def\n"
272//"/GPD { currentpagedevice /PageSize get} def\n"
273
274// show at position with desired width
275// usage:
276// width (string) x y show_pos_width
277"/show_pos_width {GS moveto dup dup stringwidth pop exch length 2 div dup 2 le {pop 9999} if "
278"1 sub exch 3 index exch sub exch "
279"div 0 2 index 1 -1 scale ashow pop pop GR} bind def\n" // spacing altered to match desired width
280//"/show_pos_width {GS moveto dup stringwidth pop 3 2 roll exch div -1 matrix scale concat "
281//"show GR } bind def\n" // horizontally scaled text to match desired width
282
283;
284
285
286static const char * prolog_2 = // prolog relevant only if lang_level >1
287
288// color image dictionaries
289"/CII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n"
290"translate \n"
291"sx sy scale\n"
292"/DeviceRGB setcolorspace\n"
293"/IDD 8 dict def\n"
294"IDD begin\n"
295"/ImageType 1 def\n"
296"/Width px def\n"
297"/Height py def\n"
298"/BitsPerComponent 8 def\n"
299"/Interpolate inter def\n"
300"/DataSource currentfile /ASCIIHexDecode filter def\n"
301"/MultipleDataSources false def\n"
302"/ImageMatrix [ px 0 0 py neg 0 py ] def\n"
303"/Decode [ 0 1 0 1 0 1 ] def\n"
304"end\n"
305"IDD image GR} bind def\n"
306
307// gray image dict
308"/GII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n"
309"translate \n"
310"sx sy scale\n"
311"/DeviceGray setcolorspace\n"
312"/IDD 8 dict def\n"
313"IDD begin\n"
314"/ImageType 1 def\n"
315"/Width px def\n"
316"/Height py def\n"
317"/BitsPerComponent 8 def\n"
318
319"/Interpolate inter def\n"
320"/DataSource currentfile /ASCIIHexDecode filter def\n"
321"/MultipleDataSources false def\n"
322"/ImageMatrix [ px 0 0 py neg 0 py ] def\n"
323"/Decode [ 0 1 ] def\n"
324"end\n"
325"IDD image GR} bind def\n"
326
327// Create a custom PostScript font derived from PostScript standard text fonts
328// The encoding of this custom font is as follows:
329// 0000-00FF coincides with Unicode, that is to ASCII + Latin-1
330// 0100-017F coincides with Unicode, that is to Latin Extended-A
331// 0180-01A6 encodes miscellaneous characters present in PostScript standard text fonts
332
333// use ISOLatin1Encoding for all text fonts
334"/ToISO { dup findfont dup length dict copy begin /Encoding ISOLatin1Encoding def currentdict end definefont pop } def\n"
335"/Helvetica ToISO /Helvetica-Bold ToISO /Helvetica-Oblique ToISO /Helvetica-BoldOblique ToISO \n"
336"/Courier ToISO /Courier-Bold ToISO /Courier-Oblique ToISO /Courier-BoldOblique ToISO \n"
337"/Times-Roman ToISO /Times-Bold ToISO /Times-Italic ToISO /Times-BoldItalic ToISO \n"
338
339// define LatinExtA, the encoding of Latin-extended-A + some additional characters
340// see http://www.adobe.com/devnet/opentype/archives/glyphlist.txt for their names
341"/LatinExtA \n"
342"[ "
343" /Amacron /amacron /Abreve /abreve /Aogonek /aogonek\n" // begin of Latin Extended-A code page
344" /Cacute /cacute /Ccircumflex /ccircumflex /Cdotaccent /cdotaccent /Ccaron /ccaron \n"
345" /Dcaron /dcaron /Dcroat /dcroat\n"
346" /Emacron /emacron /Ebreve /ebreve /Edotaccent /edotaccent /Eogonek /eogonek /Ecaron /ecaron\n"
347" /Gcircumflex /gcircumflex /Gbreve /gbreve /Gdotaccent /gdotaccent /Gcommaaccent /gcommaaccent \n"
348" /Hcircumflex /hcircumflex /Hbar /hbar \n"
349" /Itilde /itilde /Imacron /imacron /Ibreve /ibreve /Iogonek /iogonek /Idotaccent /dotlessi \n"
350" /IJ /ij /Jcircumflex /jcircumflex\n"
351" /Kcommaaccent /kcommaaccent /kgreenlandic \n"
352" /Lacute /lacute /Lcommaaccent /lcommaaccent /Lcaron /lcaron /Ldotaccent /ldotaccent /Lslash /lslash \n"
353" /Nacute /nacute /Ncommaaccent /ncommaaccent /Ncaron /ncaron /napostrophe /Eng /eng \n"
354" /Omacron /omacron /Obreve /obreve /Ohungarumlaut /ohungarumlaut /OE /oe \n"
355" /Racute /racute /Rcommaaccent /rcommaaccent /Rcaron /rcaron \n"
356" /Sacute /sacute /Scircumflex /scircumflex /Scedilla /scedilla /Scaron /scaron \n"
357" /Tcommaaccent /tcommaaccent /Tcaron /tcaron /Tbar /tbar \n"
358" /Utilde /utilde /Umacron /umacron /Ubreve /ubreve /Uring /uring /Uhungarumlaut /uhungarumlaut /Uogonek /uogonek \n"
359" /Wcircumflex /wcircumflex /Ycircumflex /ycircumflex /Ydieresis \n"
360" /Zacute /zacute /Zdotaccent /zdotaccent /Zcaron /zcaron \n"
361" /longs \n" // end of Latin Extended-A code page
362" /florin /circumflex /caron /breve /dotaccent /ring \n" // remaining characters from PostScript standard text fonts
363" /ogonek /tilde /hungarumlaut /endash /emdash \n"
364" /quoteleft /quoteright /quotesinglbase /quotedblleft /quotedblright \n"
365" /quotedblbase /dagger /daggerdbl /bullet /ellipsis \n"
366" /perthousand /guilsinglleft /guilsinglright /fraction /Euro \n"
367" /trademark /partialdiff /Delta /summation /radical \n"
368" /infinity /notequal /lessequal /greaterequal /lozenge \n"
369" /fi /fl /apple \n"
370" ] def \n"
371// deal with alternative PostScript names of some characters
372" /mycharstrings /Helvetica findfont /CharStrings get def\n"
373" /PSname2 { dup mycharstrings exch known {LatinExtA 3 -1 roll 3 -1 roll put}{pop pop} ifelse } def \n"
374" 16#20 /Gdot PSname2 16#21 /gdot PSname2 16#30 /Idot PSname2 16#3F /Ldot PSname2 16#40 /ldot PSname2 16#7F /slong PSname2 \n"
375
376// proc that gives LatinExtA encoding to a font
377"/ToLatinExtA { findfont dup length dict copy begin /Encoding LatinExtA def currentdict end definefont pop } def\n"
378// create Ext-versions of standard fonts that use LatinExtA encoding \n"
379"/HelveticaExt /Helvetica ToLatinExtA \n"
380"/Helvetica-BoldExt /Helvetica-Bold ToLatinExtA /Helvetica-ObliqueExt /Helvetica-Oblique ToLatinExtA \n"
381"/Helvetica-BoldObliqueExt /Helvetica-BoldOblique ToLatinExtA \n"
382"/CourierExt /Courier ToLatinExtA /Courier-BoldExt /Courier-Bold ToLatinExtA \n"
383"/Courier-ObliqueExt /Courier-Oblique ToLatinExtA /Courier-BoldObliqueExt /Courier-BoldOblique ToLatinExtA \n"
384"/Times-RomanExt /Times-Roman ToLatinExtA /Times-BoldExt /Times-Bold ToLatinExtA \n"
385"/Times-ItalicExt /Times-Italic ToLatinExtA /Times-BoldItalicExt /Times-BoldItalic ToLatinExtA \n"
386
387// proc to create a Type 0 font with 2-byte encoding
388// that merges a text font with ISO encoding + same font with LatinExtA encoding
389"/To2byte { 6 dict begin /FontType 0 def \n"
390"/FDepVector 3 1 roll findfont exch findfont 2 array astore def \n"
391"/FontMatrix [1 0 0 1 0 0] def /FMapType 6 def /Encoding [ 0 1 0 ] def\n"
392// 100: Hexa count of ISO array; A7: hexa count of LatinExtA array
393"/SubsVector < 01 0100 00A7 > def\n"
394"currentdict end definefont pop } def\n"
395// create Type 0 versions of standard fonts
396"/Helvetica2B /HelveticaExt /Helvetica To2byte \n"
397"/Helvetica-Bold2B /Helvetica-BoldExt /Helvetica-Bold To2byte \n"
398"/Helvetica-Oblique2B /Helvetica-ObliqueExt /Helvetica-Oblique To2byte \n"
399"/Helvetica-BoldOblique2B /Helvetica-BoldObliqueExt /Helvetica-BoldOblique To2byte \n"
400"/Courier2B /CourierExt /Courier To2byte \n"
401"/Courier-Bold2B /Courier-BoldExt /Courier-Bold To2byte \n"
402"/Courier-Oblique2B /Courier-ObliqueExt /Courier-Oblique To2byte \n"
403"/Courier-BoldOblique2B /Courier-BoldObliqueExt /Courier-BoldOblique To2byte \n"
404"/Times-Roman2B /Times-RomanExt /Times-Roman To2byte \n"
405"/Times-Bold2B /Times-BoldExt /Times-Bold To2byte \n"
406"/Times-Italic2B /Times-ItalicExt /Times-Italic To2byte \n"
407"/Times-BoldItalic2B /Times-BoldItalicExt /Times-BoldItalic To2byte \n"
408;
409
410static const char * prolog_2_pixmap = // prolog relevant only if lang_level == 2 for pixmaps/masked color images
411"/pixmap_mat {[ pixmap_sx 0 0 pixmap_sy neg 0 pixmap_sy ]} bind def\n"
412
413"/pixmap_dict {"
414"<< /PatternType 1 "
415"/PaintType 1 "
416"/TilingType 2 "
417"/BBox [0 0 pixmap_sx pixmap_sy] "
418"/XStep pixmap_sx "
419"/YStep pixmap_sy\n"
420"/PaintProc "
421"{ begin "
422"pixmap_w pixmap_h scale "
423"pixmap_sx pixmap_sy 8 "
424"pixmap_mat "
425"currentfile /ASCIIHexDecode filter "
426"false 3 "
427"colorimage "
428"end "
429"} bind "
430">>\n"
431"} bind def\n"
432
433"/pixmap_plot {"
434"GS "
435"/pixmap_sy exch def /pixmap_sx exch def\n"
436"/pixmap_h exch def /pixmap_w exch def\n"
437"translate\n"
438"pixmap_dict matrix makepattern setpattern\n"
439"pixmap_w pixmap_h scale\n"
440"pixmap_sx pixmap_sy\n"
441"true\n"
442"pixmap_mat\n"
443"currentfile /ASCIIHexDecode filter\n"
444"imagemask\n"
445"GR\n"
446"} bind def\n"
447;
448
449static const char * prolog_3 = // prolog relevant only if lang_level >2
450
451// masked color images
452"/CIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n"
453"translate \n"
454"sx sy scale\n"
455"/DeviceRGB setcolorspace\n"
456
457"/IDD 8 dict def\n"
458
459"IDD begin\n"
460"/ImageType 1 def\n"
461"/Width px def\n"
462"/Height py def\n"
463"/BitsPerComponent 8 def\n"
464"/Interpolate inter def\n"
465"/DataSource currentfile /ASCIIHexDecode filter def\n"
466"/MultipleDataSources false def\n"
467"/ImageMatrix [ px 0 0 py neg 0 py ] def\n"
468
469"/Decode [ 0 1 0 1 0 1 ] def\n"
470"end\n"
471
472"/IMD 8 dict def\n"
473"IMD begin\n"
474"/ImageType 1 def\n"
475"/Width mx def\n"
476"/Height my def\n"
477"/BitsPerComponent 1 def\n"
478// "/Interpolate inter def\n"
479"/ImageMatrix [ mx 0 0 my neg 0 my ] def\n"
480"/Decode [ 1 0 ] def\n"
481"end\n"
482
483"<<\n"
484"/ImageType 3\n"
485"/InterleaveType 2\n"
486"/MaskDict IMD\n"
487"/DataDict IDD\n"
488">> image GR\n"
489"} bind def\n"
490
491
492// masked gray images
493"/GIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n"
494"translate \n"
495"sx sy scale\n"
496"/DeviceGray setcolorspace\n"
497
498"/IDD 8 dict def\n"
499
500"IDD begin\n"
501"/ImageType 1 def\n"
502"/Width px def\n"
503"/Height py def\n"
504"/BitsPerComponent 8 def\n"
505"/Interpolate inter def\n"
506"/DataSource currentfile /ASCIIHexDecode filter def\n"
507"/MultipleDataSources false def\n"
508"/ImageMatrix [ px 0 0 py neg 0 py ] def\n"
509
510"/Decode [ 0 1 ] def\n"
511"end\n"
512
513"/IMD 8 dict def\n"
514
515"IMD begin\n"
516"/ImageType 1 def\n"
517"/Width mx def\n"
518"/Height my def\n"
519"/BitsPerComponent 1 def\n"
520"/ImageMatrix [ mx 0 0 my neg 0 my ] def\n"
521"/Decode [ 1 0 ] def\n"
522"end\n"
523
524"<<\n"
525"/ImageType 3\n"
526"/InterleaveType 2\n"
527"/MaskDict IMD\n"
528"/DataDict IDD\n"
529">> image GR\n"
530"} bind def\n"
531
532
533"\n"
534;
535
536// end prolog
537
538int Fl_PostScript_Graphics_Driver::start_postscript (int pagecount,
540//returns 0 iff OK
541{
542 int w, h, x;
543 if (format == Fl_Paged_Device::A4) {
544 left_margin = 18;
545 top_margin = 18;
546 }
547 else {
548 left_margin = 12;
549 top_margin = 12;
550 }
551 page_format_ = (enum Fl_Paged_Device::Page_Format)(format | layout);
552
553 fputs("%!PS-Adobe-3.0\n", output);
554 fputs("%%Creator: FLTK\n", output);
555 if (lang_level_>1)
556 fprintf(output, "%%%%LanguageLevel: %i\n" , lang_level_);
557 if ((pages_ = pagecount))
558 fprintf(output, "%%%%Pages: %i\n", pagecount);
559 else
560 fputs("%%Pages: (atend)\n", output);
561 fprintf(output, "%%%%BeginFeature: *PageSize %s\n", Fl_Paged_Device::page_formats[format].name );
564 if (lang_level_ == 3 && (layout & Fl_Paged_Device::LANDSCAPE) ) { x = w; w = h; h = x; }
565 fprintf(output, "<</PageSize[%d %d]>>setpagedevice\n", w, h );
566 fputs("%%EndFeature\n", output);
567 fputs("%%EndComments\n", output);
568 fputs(prolog, output);
569 if (lang_level_ > 1) {
570 fputs(prolog_2, output);
571 }
572 if (lang_level_ == 2) {
573 fputs(prolog_2_pixmap, output);
574 }
575 if (lang_level_ > 2)
576 fputs(prolog_3, output);
577 if (lang_level_ >= 3) {
578 fputs("/CS { clipsave } bind def\n", output);
579 fputs("/CR { cliprestore } bind def\n", output);
580 } else {
581 fputs("/CS { GS } bind def\n", output);
582 fputs("/CR { GR } bind def\n", output);
583 }
584 page_policy_ = 1;
585
586
587 fputs("%%EndProlog\n",output);
588 if (lang_level_ >= 2)
589 fprintf(output,"<< /Policies << /Pagesize 1 >> >> setpagedevice\n");
590
591 reset();
592 nPages=0;
593 return 0;
594}
595
596void Fl_PostScript_Graphics_Driver::recover(){
597 color(cr_,cg_,cb_);
598 line_style(linestyle_,linewidth_,linedash_);
600}
601
602void Fl_PostScript_Graphics_Driver::reset(){
603 gap_=1;
604 clip_=0;
605 cr_=cg_=cb_=0;
607 linewidth_=0;
608 linestyle_=FL_SOLID;
609 strcpy(linedash_,"");
610 Clip *c=clip_;
611
612 while(c){
613 clip_=clip_->prev;
614 delete c;
615 c=clip_;
616 }
617
618}
619
620void Fl_PostScript_Graphics_Driver::page_policy(int p){
621 page_policy_ = p;
622 if(lang_level_>=2)
623 fprintf(output,"<< /Policies << /Pagesize %i >> >> setpagedevice\n", p);
624}
625
626// //////////////////// paging //////////////////////////////////////////
627
628
629
630void Fl_PostScript_Graphics_Driver::page(double pw, double ph, int media) {
631
632 if (nPages){
633 fprintf(output, "CR\nGR\nGR\nGR\nSP\nrestore\n");
634 }
635 ++nPages;
636 fprintf(output, "%%%%Page: %i %i\n" , nPages , nPages);
637 if (pw>ph){
638 fprintf(output, "%%%%PageOrientation: Landscape\n");
639 }else{
640 fprintf(output, "%%%%PageOrientation: Portrait\n");
641 }
642
643 fprintf(output, "%%%%BeginPageSetup\n");
644 if((media & Fl_Paged_Device::MEDIA) &&(lang_level_>1)){
645 int r = media & Fl_Paged_Device::REVERSED;
646 if(r) r = 2;
647 fprintf(output, "<< /PageSize [%i %i] /Orientation %i>> setpagedevice\n", (int)(pw+.5), (int)(ph+.5), r);
648 }
649 fprintf(output, "%%%%EndPageSetup\n");
650
651 pw_ = pw;
652 ph_ = ph;
653 reset();
654
655 fprintf(output, "save\n");
656 fprintf(output, "GS\n");
657 fprintf(output, "%g %g TR\n", (double)0 /*lm_*/ , ph_ /* - tm_*/);
658 fprintf(output, "1 -1 SC\n");
659 line_style(0);
660 fprintf(output, "GS\n");
661
662 if (!((media & Fl_Paged_Device::MEDIA) &&(lang_level_>1))){
663 if (pw > ph) {
664 if(media & Fl_Paged_Device::REVERSED) {
665 fprintf(output, "-90 rotate %i 0 translate\n", int(-pw));
666 }
667 else {
668 fprintf(output, "90 rotate -%i -%i translate\n", (lang_level_ == 2 ? int(pw - ph) : 0), int(ph));
669 }
670 }
671 else {
672 if(media & Fl_Paged_Device::REVERSED)
673 fprintf(output, "180 rotate %i %i translate\n", int(-pw), int(-ph));
674 }
675 }
676 fprintf(output, "GS\nCS\n");
677}
678
679void Fl_PostScript_Graphics_Driver::page(int format){
680
681
682 if(format & Fl_Paged_Device::LANDSCAPE){
683 ph_=Fl_Paged_Device::page_formats[format & 0xFF].width;
684 pw_=Fl_Paged_Device::page_formats[format & 0xFF].height;
685 }else{
686 pw_=Fl_Paged_Device::page_formats[format & 0xFF].width;
687 ph_=Fl_Paged_Device::page_formats[format & 0xFF].height;
688 }
689 page(pw_,ph_,format & 0xFF00);//,orientation only;
690}
691
692void Fl_PostScript_Graphics_Driver::rect(int x, int y, int w, int h) {
693 // Commented code does not work, i can't find the bug ;-(
694 // fprintf(output, "GS\n");
695 // fprintf(output, "%i, %i, %i, %i R\n", x , y , w, h);
696 // fprintf(output, "GR\n");
697 fprintf(output, "GS\n");
698 fprintf(output,"BP\n");
699 fprintf(output, "%i %i MT\n", x , y);
700 fprintf(output, "%i %i LT\n", x+w-1 , y);
701 fprintf(output, "%i %i LT\n", x+w-1 , y+h-1);
702 fprintf(output, "%i %i LT\n", x , y+h-1);
703 fprintf(output, "ECP\n");
704 fprintf(output, "GR\n");
705}
706
707void Fl_PostScript_Graphics_Driver::rectf(int x, int y, int w, int h) {
708 fprintf(output, "%g %g %i %i FR\n", x-0.5, y-0.5, w, h);
709}
710
711void Fl_PostScript_Graphics_Driver::line(int x1, int y1, int x2, int y2) {
712 fprintf(output, "GS\n");
713 fprintf(output, "%i %i %i %i L\n", x1 , y1, x2 ,y2);
714 fprintf(output, "GR\n");
715}
716
717void Fl_PostScript_Graphics_Driver::line(int x0, int y0, int x1, int y1, int x2, int y2) {
718 fprintf(output, "GS\n");
719 fprintf(output,"BP\n");
720 fprintf(output, "%i %i MT\n", x0 , y0);
721 fprintf(output, "%i %i LT\n", x1 , y1);
722 fprintf(output, "%i %i LT\n", x2 , y2);
723 fprintf(output, "ELP\n");
724 fprintf(output, "GR\n");
725}
726
727void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3){
728 fprintf(output, "GS\n");
729 fprintf(output,"BP\n");
730 fprintf(output, "%i %i MT\n", x , y );
731 fprintf(output, "%i %i LT\n", x1 , y );
732 fprintf(output, "%i %i LT\n", x1 , y2);
733 fprintf(output,"%i %i LT\n", x3 , y2);
734 fprintf(output, "ELP\n");
735 fprintf(output, "GR\n");
736}
737
738
739void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2){
740
741 fprintf(output, "GS\n");
742 fprintf(output,"BP\n");
743 fprintf(output, "%i %i MT\n", x , y);
744 fprintf(output,"%i %i LT\n", x1 , y);
745 fprintf(output, "%i %i LT\n", x1 , y2 );
746 fprintf(output, "ELP\n");
747 fprintf(output, "GR\n");
748}
749
750void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1){
751 fprintf(output, "GS\n");
752 fprintf(output,"BP\n");
753 fprintf(output, "%i %i MT\n", x , y);
754 fprintf(output, "%i %i LT\n", x1 , y );
755 fprintf(output, "ELP\n");
756
757 fprintf(output, "GR\n");
758}
759
760void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3){
761 fprintf(output, "GS\n");
762
763 fprintf(output,"BP\n");
764 fprintf(output,"%i %i MT\n", x , y);
765 fprintf(output, "%i %i LT\n", x , y1 );
766 fprintf(output, "%i %i LT\n", x2 , y1 );
767 fprintf(output , "%i %i LT\n", x2 , y3);
768 fprintf(output, "ELP\n");
769 fprintf(output, "GR\n");
770}
771
772void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2){
773 fprintf(output, "GS\n");
774 fprintf(output,"BP\n");
775 fprintf(output, "%i %i MT\n", x , y);
776 fprintf(output, "%i %i LT\n", x , y1);
777 fprintf(output, "%i %i LT\n", x2 , y1);
778 fprintf(output, "ELP\n");
779 fprintf(output, "GR\n");
780}
781
782void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1){
783 fprintf(output, "GS\n");
784 fprintf(output,"BP\n");
785 fprintf(output, "%i %i MT\n", x , y);
786 fprintf(output, "%i %i LT\n", x , y1);
787 fprintf(output, "ELP\n");
788 fprintf(output, "GR\n");
789}
790
791void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
792 fprintf(output, "GS\n");
793 fprintf(output,"BP\n");
794 fprintf(output, "%i %i MT\n", x0 , y0);
795 fprintf(output, "%i %i LT\n", x1 , y1);
796 fprintf(output, "%i %i LT\n", x2 , y2);
797 fprintf(output, "ECP\n");
798 fprintf(output, "GR\n");
799}
800
801void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
802 fprintf(output, "GS\n");
803 fprintf(output,"BP\n");
804 fprintf(output, "%i %i MT\n", x0 , y0);
805 fprintf(output, "%i %i LT\n", x1 , y1);
806 fprintf(output, "%i %i LT\n", x2 , y2);
807 fprintf(output, "%i %i LT\n", x3 , y3);
808 fprintf(output, "ECP\n");
809 fprintf(output, "GR\n");
810}
811
812void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
813 fprintf(output, "GS\n");
814 fprintf(output,"BP\n");
815 fprintf(output, "%i %i MT\n", x0 , y0);
816 fprintf(output,"%i %i LT\n", x1 , y1);
817 fprintf(output, "%i %i LT\n", x2 , y2);
818 fprintf(output, "EFP\n");
819 fprintf(output, "GR\n");
820}
821
822void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
823 fprintf(output, "GS\n");
824 fprintf(output,"BP\n");
825 fprintf(output, "%i %i MT\n", x0 , y0 );
826 fprintf(output, "%i %i LT\n", x1 , y1 );
827 fprintf(output, "%i %i LT\n", x2 , y2 );
828 fprintf(output, "%i %i LT\n", x3 , y3 );
829
830 fprintf(output, "EFP\n");
831 fprintf(output, "GR\n");
832}
833
834void Fl_PostScript_Graphics_Driver::point(int x, int y){
835 rectf(x,y,1,1);
836}
837
838static int dashes_flat[5][7]={
839{-1,0,0,0,0,0,0},
840{3,1,-1,0,0,0,0},
841{1,1,-1,0,0,0,0},
842{3,1,1,1,-1,0,0},
843{3,1,1,1,1,1,-1}
844};
845
846
847//yeah, hack...
848static double dashes_cap[5][7]={
849{-1,0,0,0,0,0,0},
850{2,2,-1,0,0,0,0},
851{0.01,1.99,-1,0,0,0,0},
852{2,2,0.01,1.99,-1,0,0},
853{2,2,0.01,1.99,0.01,1.99,-1}
854};
855
856
857void Fl_PostScript_Graphics_Driver::line_style(int style, int width, char* dashes){
858 //line_styled_=1;
859
860 linewidth_=width;
861 linestyle_=style;
862 //dashes_= dashes;
863 if(dashes){
864 if(dashes != linedash_)
865 strcpy(linedash_,dashes);
866
867 }else
868 linedash_[0]=0;
869 char width0 = 0;
870 if(!width){
871 width=1; //for screen drawing compatibility
872 width0=1;
873 }
874
875 fprintf(output, "%i setlinewidth\n", width);
876
877 if(!style && (!dashes || !(*dashes)) && width0) //system lines
878 style = FL_CAP_SQUARE;
879
880 int cap = (style &0xf00) >> 8;
881 if(cap) cap--;
882 fprintf(output,"%i setlinecap\n", cap);
883
884 int join = (style & 0xf000) >> 12;
885
886 if(join) join--;
887 fprintf(output,"%i setlinejoin\n", join);
888
889
890 fprintf(output, "[");
891 if(dashes && *dashes){
892 while(*dashes){
893 fprintf(output, "%i ", *dashes);
894 dashes++;
895 }
896 }else{
897 int * ds;
898 if(style & 0x200){ // round and square caps, dash length need to be adjusted
899 double *dt = dashes_cap[style & 0xff];
900 while (*dt >= 0){
901 fprintf(output, "%g ",width * (*dt));
902 dt++;
903 }
904 }else{
905
906 ds = dashes_flat[style & 0xff];
907 while (*ds >= 0){
908 fprintf(output, "%i ",width * (*ds));
909 ds++;
910 }
911 }
912 }
913 fprintf(output, "] 0 setdash\n");
914}
915
916static const char *_fontNames[] = {
917"Helvetica2B",
918"Helvetica-Bold2B",
919"Helvetica-Oblique2B",
920"Helvetica-BoldOblique2B",
921"Courier2B",
922"Courier-Bold2B",
923"Courier-Oblique2B",
924"Courier-BoldOblique2B",
925"Times-Roman2B",
926"Times-Bold2B",
927"Times-Italic2B",
928"Times-BoldItalic2B",
929"Symbol",
930"Courier2B",
931"Courier-Bold2B",
932"ZapfDingbats"
933};
934
935void Fl_PostScript_Graphics_Driver::font(int f, int s) {
937 driver->font(f,s); // Use display fonts for font measurement
939 Fl_Font_Descriptor *desc = driver->font_descriptor();
940 this->font_descriptor(desc);
941 if (f < FL_FREE_FONT) {
942 float ps_size = s;
943 fprintf(output, "/%s SF\n" , _fontNames[f]);
944#if defined(USE_X11)
945#if USE_XFT
946 // Xft font height is sometimes larger than the required size (see STR 2566).
947 // Increase the PostScript font size by 15% without exceeding the display font height
948 int max = desc->font->height;
949 ps_size = s * 1.15;
950 if (ps_size > max) ps_size = max;
951#else
952 // Non-Xft fonts can be smaller than required.
953 // Set the PostScript font size to the display font height
954 char *name = desc->font->font_name_list[0];
955 char *p = strstr(name, "--");
956 if (p) {
957 sscanf(p + 2, "%f", &ps_size);
958 }
959#endif // USE_XFT
960#endif // USE_X11
961 fprintf(output,"%.1f FS\n", ps_size);
962 }
963}
964
965double Fl_PostScript_Graphics_Driver::width(const char *s, int n) {
966 return Fl_Display_Device::display_device()->driver()->width(s, n);
967}
968
970 return Fl_Display_Device::display_device()->driver()->height();
971}
972
974 return Fl_Display_Device::display_device()->driver()->descent();
975}
976
977void Fl_PostScript_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
978 Fl_Display_Device::display_device()->driver()->text_extents(c, n, dx, dy, w, h);
979}
980
981
983 Fl::get_color(c, cr_, cg_, cb_);
984 color(cr_, cg_, cb_);
985}
986
987void Fl_PostScript_Graphics_Driver::color(unsigned char r, unsigned char g, unsigned char b) {
989 cr_ = r; cg_ = g; cb_ = b;
990 if (r == g && g == b) {
991 double gray = r/255.0;
992 fprintf(output, "%g GL\n", gray);
993 } else {
994 double fr, fg, fb;
995 fr = r/255.0;
996 fg = g/255.0;
997 fb = b/255.0;
998 fprintf(output, "%g %g %g SRGB\n", fr , fg , fb);
999 }
1000}
1001
1002void Fl_PostScript_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y)
1003{
1004 fprintf(output, "GS %d %d translate %d rotate\n", x, y, - angle);
1005 this->transformed_draw(str, n, 0, 0);
1006 fprintf(output, "GR\n");
1007}
1008
1009
1010// computes the mask for the RGB image img of all pixels with color != bg
1011static uchar *calc_mask(uchar *img, int w, int h, Fl_Color bg)
1012{
1013 uchar red, green, blue, r, g, b;
1014 uchar bit, byte, *q;
1015 Fl::get_color(bg, red, green, blue);
1016 int W = (w+7)/8; // width of mask
1017 uchar* mask = new uchar[W * h];
1018 q = mask;
1019 while (h-- > 0) { // for each row
1020 bit = 0x80; // byte with last bit set
1021 byte = 0; // next mask byte to compute
1022 for (int j = 0; j < w; j++) { // for each column
1023 r = *img++; // the pixel color components
1024 g = *img++;
1025 b = *img++;
1026 // if pixel doesn't have bg color, put it in mask
1027 if (r != red || g != green || b != blue) byte |= bit;
1028 bit = bit>>1; // shift bit one step to the right
1029 if (bit == 0) { // single set bit has fallen out
1030 *q++ = byte; // enter byte in mask
1031 byte = 0; // reset next mask byte to zero
1032 bit = 0x80; // and this byte
1033 }
1034 }
1035 if (bit != 0x80) *q++ = byte; // enter last columns' byte in mask
1036 }
1037 return mask;
1038}
1039
1040// write to PostScript a bitmap image of a UTF8 string
1041static void transformed_draw_extra(const char* str, int n, double x, double y, int w,
1042 FILE *output, Fl_Graphics_Driver *driver, bool rtl) {
1043 // scale for bitmask computation
1044#if defined(USE_X11) && !USE_XFT
1045 float scale = 1; // don't scale because we can't expect to have scalable fonts
1046#else
1047 float scale = 2;
1048#endif
1049 Fl_Fontsize old_size = driver->size();
1050 Fl_Font fontnum = driver->font();
1051 int w_scaled = (int)(w * (scale + 0.5));
1052 int h = (int)(driver->height() * scale);
1053 // create an offscreen image of the string
1054 Fl_Color text_color = driver->color();
1055 Fl_Color bg_color = fl_contrast(FL_WHITE, text_color);
1056 Fl_Offscreen off = fl_create_offscreen(w_scaled, (int)(h+3*scale) );
1057 fl_begin_offscreen(off);
1058 fl_color(bg_color);
1059 // color offscreen background with a shade contrasting with the text color
1060 fl_rectf(0, 0, w_scaled, (int)(h+3*scale) );
1061 fl_color(text_color);
1062#if defined(USE_X11) && !USE_XFT
1063 // force seeing this font as new so it's applied to the offscreen graphics context
1064 fl_graphics_driver->font_descriptor(NULL);
1065 fl_font(fontnum, 0);
1066#endif
1067 fl_font(fontnum, (Fl_Fontsize)(scale * old_size) );
1068 int w2 = (int)fl_width(str, n);
1069 // draw string in offscreen
1070 if (rtl) fl_rtl_draw(str, n, w2, (int)(h * 0.8) );
1071 else fl_draw(str, n, 1, (int)(h * 0.8) );
1072 // read (most of) the offscreen image
1073 uchar *img = fl_read_image(NULL, 1, 1, w2, h, 0);
1075 driver->font(fontnum, old_size);
1077 // compute the mask of what is not the background
1078 uchar *mask = calc_mask(img, w2, h, bg_color);
1079 delete[] img;
1080 // write the string image to PostScript as a scaled bitmask
1081 scale = w2 / float(w);
1082 fprintf(output, "%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w2/scale, h/scale, w2, h);
1083 uchar *di;
1084 int wmask = (w2+7)/8;
1085 for (int j = h - 1; j >= 0; j--){
1086 di = mask + j * wmask;
1087 for (int i = 0; i < wmask; i++){
1088 //if (!(i%80)) fprintf(output, "\n"); // don't have lines longer than 255 chars
1089 fprintf(output, "%2.2x", *di );
1090 di++;
1091 }
1092 fprintf(output,"\n");
1093 }
1094 fprintf(output,">\n");
1095 delete[] mask;
1096}
1097
1098static int is_in_table(unsigned utf) {
1099 unsigned i;
1100 static unsigned extra_table_roman[] = { // unicodes/*names*/ of other characters from PostScript standard fonts
1101 0x192/*florin*/, 0x2C6/*circumflex*/, 0x2C7/*caron*/,
1102 0x2D8/*breve*/, 0x2D9/*dotaccent*/, 0x2DA/*ring*/, 0x2DB/*ogonek*/, 0x2DC/*tilde*/, 0x2DD/*hungarumlaut*/,
1103 0x2013/*endash*/, 0x2014/*emdash*/, 0x2018/*quoteleft*/, 0x2019/*quoteright*/,
1104 0x201A/*quotesinglbase*/, 0x201C/*quotedblleft*/, 0x201D/*quotedblright*/, 0x201E/*quotedblbase*/,
1105 0x2020/*dagger*/, 0x2021/*daggerdbl*/, 0x2022/*bullet*/,
1106 0x2026/*ellipsis*/, 0x2030/*perthousand*/, 0x2039/*guilsinglleft*/, 0x203A/*guilsinglright*/,
1107 0x2044/*fraction*/, 0x20AC/*Euro*/, 0x2122/*trademark*/,
1108 0x2202/*partialdiff*/, 0x2206/*Delta*/, 0x2211/*summation*/, 0x221A/*radical*/,
1109 0x221E/*infinity*/, 0x2260/*notequal*/, 0x2264/*lessequal*/,
1110 0x2265/*greaterequal*/,
1111 0x25CA/*lozenge*/, 0xFB01/*fi*/, 0xFB02/*fl*/,
1112 0xF8FF/*apple*/
1113 };
1114 for ( i = 0; i < sizeof(extra_table_roman)/sizeof(int); i++) {
1115 if (extra_table_roman[i] == utf) return i + 0x180;
1116 }
1117 return 0;
1118}
1119
1120// outputs in PostScript a UTF8 string using the same width in points as on display
1121void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y) {
1122 int len, code;
1123 if (!n || !str || !*str) return;
1124 // compute display width of string
1125 int w = (int)width(str, n);
1126 if (w == 0) return;
1128 transformed_draw_extra(str, n, x, y, w, output, this, false);
1129 return;
1130 }
1131 fprintf(output, "%d <", w);
1132 // transforms UTF8 encoding to our custom PostScript encoding as follows:
1133 // extract each unicode character
1134 // if unicode <= 0x17F, unicode and PostScript codes are identical
1135 // if unicode is one of the values listed in extra_table_roman above
1136 // its PostScript code is 0x180 + the character's rank in extra_table_roman
1137 // if unicode is something else, draw all string as bitmap image
1138
1139 const char *last = str + n;
1140 const char *str2 = str;
1141 while (str2 < last) {
1142 // Extract each unicode character of string.
1143 unsigned utf = fl_utf8decode(str2, last, &len);
1144 str2 += len;
1145 if (utf <= 0x17F) { // until Latin Extended-A
1146 ;
1147 }
1148 else if ( (code = is_in_table(utf)) != 0) { // other handled characters
1149 utf = code;
1150 }
1151 else { // unhandled character: draw all string as bitmap image
1152 fprintf(output, "> pop pop\n"); // close and ignore the opened hex string
1153 transformed_draw_extra(str, n, x, y, w, output, this, false);
1154 return;
1155 }
1156 fprintf(output, "%4.4X", utf);
1157 }
1158 fprintf(output, "> %g %g show_pos_width\n", x, y);
1159}
1160
1161void Fl_PostScript_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
1162 int w = (int)width(str, n);
1163 transformed_draw_extra(str, n, x - w, y, w, output, this, true);
1164}
1165
1166void Fl_PostScript_Graphics_Driver::concat(){
1167 fprintf(output,"[%g %g %g %g %g %g] CT\n", fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y);
1168}
1169
1170void Fl_PostScript_Graphics_Driver::reconcat(){
1171 fprintf(output, "[%g %g %g %g %g %g] RCT\n" , fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y);
1172}
1173
1175
1176
1178 fprintf(output, "GS\n");
1179 concat();
1180
1181 fprintf(output, "BP\n");
1182 gap_=1;
1183 shape_=POINTS;
1184}
1185
1187 fprintf(output, "GS\n");
1188 concat();
1189 fprintf(output, "BP\n");
1190 gap_=1;
1191 shape_=LINE;
1192}
1193
1195 fprintf(output, "GS\n");
1196 concat();
1197 fprintf(output, "BP\n");
1198 gap_=1;
1199 shape_=LOOP;
1200}
1201
1203 fprintf(output, "GS\n");
1204 concat();
1205 fprintf(output, "BP\n");
1206 gap_=1;
1207 shape_=POLYGON;
1208}
1209
1210void Fl_PostScript_Graphics_Driver::vertex(double x, double y){
1211 if(shape_==POINTS){
1212 fprintf(output,"%g %g MT\n", x , y);
1213 gap_=1;
1214 return;
1215 }
1216 if(gap_){
1217 fprintf(output,"%g %g MT\n", x , y);
1218 gap_=0;
1219 }else
1220 fprintf(output, "%g %g LT\n", x , y);
1221}
1222
1223void Fl_PostScript_Graphics_Driver::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3){
1224 if(shape_==NONE) return;
1225 if(gap_)
1226 fprintf(output,"%g %g MT\n", x , y);
1227 else
1228 fprintf(output, "%g %g LT\n", x , y);
1229 gap_=0;
1230
1231 fprintf(output, "%g %g %g %g %g %g curveto \n", x1 , y1 , x2 , y2 , x3 , y3);
1232}
1233
1234
1235void Fl_PostScript_Graphics_Driver::circle(double x, double y, double r){
1236 if(shape_==NONE){
1237 fprintf(output, "GS\n");
1238 concat();
1239 // fprintf(output, "BP\n");
1240 fprintf(output,"%g %g %g 0 360 arc\n", x , y , r);
1241 reconcat();
1242 // fprintf(output, "ELP\n");
1243 fprintf(output, "GR\n");
1244 }else
1245
1246 fprintf(output, "%g %g %g 0 360 arc\n", x , y , r);
1247
1248}
1249
1250void Fl_PostScript_Graphics_Driver::arc(double x, double y, double r, double start, double a){
1251 if(shape_==NONE) return;
1252 gap_=0;
1253 if(start>a)
1254 fprintf(output, "%g %g %g %g %g arc\n", x , y , r , -start, -a);
1255 else
1256 fprintf(output, "%g %g %g %g %g arcn\n", x , y , r , -start, -a);
1257
1258}
1259
1260void Fl_PostScript_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) {
1261 fprintf(output, "GS\n");
1262 //fprintf(output, "BP\n");
1263 begin_line();
1264 fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5);
1265 fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 );
1266 arc(0,0,1,a2,a1);
1267 // fprintf(output, "0 0 1 %g %g arc\n" , -a1 , -a2);
1268 fprintf(output, "%g %g SC\n", 2.0/(w-1) , 2.0/(h-1) );
1269 fprintf(output, "%g %g TR\n", -x - w/2.0 +0.5 , -y - h/2.0 +0.5);
1270 end_line();
1271
1272 // fprintf(output, "%g setlinewidth\n", 2/sqrt(w*h));
1273 // fprintf(output, "ELP\n");
1274 // fprintf(output, 2.0/w , 2.0/w , " SC\n";
1275 // fprintf(output, (-x - w/2.0) , (-y - h/2) , " TR\n";
1276 fprintf(output, "GR\n");
1277}
1278
1279void Fl_PostScript_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) {
1280
1281 fprintf(output, "GS\n");
1282 fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5);
1283 fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 );
1284 begin_polygon();
1285 vertex(0,0);
1286 arc(0.0,0.0, 1, a2, a1);
1287 end_polygon();
1288 fprintf(output, "GR\n");
1289}
1290
1292 gap_=1;
1293 reconcat();
1294 fprintf(output, "ELP\n"); //??
1295 fprintf(output, "GR\n");
1296 shape_=NONE;
1297}
1298
1300 gap_=1;
1301 reconcat();
1302 fprintf(output, "ELP\n");
1303 fprintf(output, "GR\n");
1304 shape_=NONE;
1305}
1307 gap_=1;
1308 reconcat();
1309 fprintf(output, "ECP\n");
1310 fprintf(output, "GR\n");
1311 shape_=NONE;
1312}
1313
1315
1316 gap_=1;
1317 reconcat();
1318 fprintf(output, "EFP\n");
1319 fprintf(output, "GR\n");
1320 shape_=NONE;
1321}
1322
1324 reconcat();
1325 if(gap_){
1326 fprintf(output, "%g %g MT\n", x , y);
1327 gap_=0;
1328 }else
1329 fprintf(output, "%g %g LT\n", x , y);
1330 concat();
1331}
1332
1334
1335void Fl_PostScript_Graphics_Driver::push_clip(int x, int y, int w, int h) {
1336 Clip * c=new Clip();
1337 clip_box(x,y,w,h,c->x,c->y,c->w,c->h);
1338 c->prev=clip_;
1339 clip_=c;
1340 fprintf(output, "CR\nCS\n");
1341 if(lang_level_<3)
1342 recover();
1343 fprintf(output, "%g %g %i %i CL\n", clip_->x-0.5 , clip_->y-0.5 , clip_->w , clip_->h);
1344
1345}
1346
1348 Clip * c = new Clip();
1349 c->prev=clip_;
1350 clip_=c;
1351 clip_->x = clip_->y = clip_->w = clip_->h = -1;
1352 fprintf(output, "CR\nCS\n");
1353 if(lang_level_<3)
1354 recover();
1355}
1356
1358 if(!clip_)return;
1359 Clip * c=clip_;
1360 clip_=clip_->prev;
1361 delete c;
1362 fprintf(output, "CR\nCS\n");
1363 if(clip_ && clip_->w >0)
1364 fprintf(output, "%g %g %i %i CL\n", clip_->x - 0.5, clip_->y - 0.5, clip_->w , clip_->h);
1365 // uh, -0.5 is to match screen clipping, for floats there should be something beter
1366 if(lang_level_<3)
1367 recover();
1368}
1369
1370int Fl_PostScript_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H){
1371 if(!clip_){
1372 X=x;Y=y;W=w;H=h;
1373 return 1;
1374 }
1375 if(clip_->w < 0){
1376 X=x;Y=y;W=w;H=h;
1377 return 1;
1378 }
1379 int ret=0;
1380 if (x > (X=clip_->x)) {X=x; ret=1;}
1381 if (y > (Y=clip_->y)) {Y=y; ret=1;}
1382 if ((x+w) < (clip_->x+clip_->w)) {
1383 W=x+w-X;
1384
1385 ret=1;
1386
1387 }else
1388 W = clip_->x + clip_->w - X;
1389 if(W<0){
1390 W=0;
1391 return 1;
1392 }
1393 if ((y+h) < (clip_->y+clip_->h)) {
1394 H=y+h-Y;
1395 ret=1;
1396 }else
1397 H = clip_->y + clip_->h - Y;
1398 if(H<0){
1399 W=0;
1400 H=0;
1401 return 1;
1402 }
1403 return ret;
1404}
1405
1406int Fl_PostScript_Graphics_Driver::not_clipped(int x, int y, int w, int h){
1407 if(!clip_) return 1;
1408 if(clip_->w < 0) return 1;
1409 int X, Y, W, H;
1410 clip_box(x, y, w, h, X, Y, W, H);
1411 if(W) return 1;
1412 return 0;
1413}
1414
1415
1416void Fl_PostScript_File_Device::margins(int *left, int *top, int *right, int *bottom) // to implement
1417{
1418 Fl_PostScript_Graphics_Driver *ps = driver();
1419 if(left) *left = (int)(ps->left_margin / ps->scale_x + .5);
1420 if(right) *right = (int)(ps->left_margin / ps->scale_x + .5);
1421 if(top) *top = (int)(ps->top_margin / ps->scale_y + .5);
1422 if(bottom) *bottom = (int)(ps->top_margin / ps->scale_y + .5);
1423}
1424
1426//returns 0 iff OK
1427{
1428 Fl_PostScript_Graphics_Driver *ps = driver();
1429 if(w) *w = (int)((ps->pw_ - 2 * ps->left_margin) / ps->scale_x + .5);
1430 if(h) *h = (int)((ps->ph_ - 2 * ps->top_margin) / ps->scale_y + .5);
1431 return 0;
1432}
1433
1434void Fl_PostScript_File_Device::origin(int *x, int *y)
1435{
1437}
1438
1439void Fl_PostScript_File_Device::origin(int x, int y)
1440{
1441 x_offset = x;
1442 y_offset = y;
1443 Fl_PostScript_Graphics_Driver *ps = driver();
1444 fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n",
1445 ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x, y, ps->angle);
1446}
1447
1448void Fl_PostScript_File_Device::scale (float s_x, float s_y)
1449{
1450 if (s_y == 0.) s_y = s_x;
1451 Fl_PostScript_Graphics_Driver *ps = driver();
1452 ps->scale_x = s_x;
1453 ps->scale_y = s_y;
1454 fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %f rotate GS\n",
1455 ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, ps->angle);
1456}
1457
1458void Fl_PostScript_File_Device::rotate (float rot_angle)
1459{
1460 Fl_PostScript_Graphics_Driver *ps = driver();
1461 ps->angle = - rot_angle;
1462 fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n",
1463 ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x_offset, y_offset, ps->angle);
1464}
1465
1466void Fl_PostScript_File_Device::translate(int x, int y)
1467{
1468 fprintf(driver()->output, "GS %d %d translate GS\n", x, y);
1469}
1470
1472{
1473 fprintf(driver()->output, "GR GR\n");
1474}
1475
1477{
1478 Fl_PostScript_Graphics_Driver *ps = driver();
1479 ps->page(ps->page_format_);
1480 x_offset = 0;
1481 y_offset = 0;
1482 ps->scale_x = ps->scale_y = 1.;
1483 ps->angle = 0;
1484 fprintf(ps->output, "GR GR GS %d %d translate GS\n", ps->left_margin, ps->top_margin);
1485 return 0;
1486}
1487
1489{
1490 return 0;
1491}
1492
1494// finishes PostScript & closes file
1495{
1496 Fl_PostScript_Graphics_Driver *ps = driver();
1497 if (ps->nPages) { // for eps nPages is 0 so it is fine ....
1498 fprintf(ps->output, "CR\nGR\nGR\nGR\nSP\n restore\n");
1499 if (!ps->pages_){
1500 fprintf(ps->output, "%%%%Trailer\n");
1501 fprintf(ps->output, "%%%%Pages: %i\n" , ps->nPages);
1502 };
1503 } else
1504 fprintf(ps->output, "GR\n restore\n");
1505 fputs("%%EOF",ps->output);
1506 ps->reset();
1507 fflush(ps->output);
1508 if(ferror(ps->output)) {
1509 fl_alert ("Error during PostScript data output.");
1510 }
1511 if (ps->close_cmd_) {
1512 (*ps->close_cmd_)(ps->output);
1513 } else {
1514 fclose(ps->output);
1515 }
1516 while (ps->clip_){
1517 Fl_PostScript_Graphics_Driver::Clip * c= ps->clip_;
1518 ps->clip_= ps->clip_->prev;
1519 delete c;
1520 }
1522}
1523
1524#if ! (defined(__APPLE__) || defined(WIN32) )
1525int Fl_PostScript_Printer::start_job(int pages, int *firstpage, int *lastpage) {
1526 enum Fl_Paged_Device::Page_Format format;
1527 enum Fl_Paged_Device::Page_Layout layout;
1528
1529 // first test version for print dialog
1530 if (!print_panel) make_print_panel();
1531 print_load();
1532 print_selection->deactivate();
1533 print_all->setonly();
1534 print_all->do_callback();
1535 print_from->value("1");
1536 { char tmp[10]; snprintf(tmp, sizeof(tmp), "%d", pages); print_to->value(tmp); }
1537 print_panel->show(); // this is modal
1538 while (print_panel->shown()) Fl::wait();
1539
1540 if (!print_start) // user clicked cancel
1541 return 1;
1542
1543 // get options
1544
1545 format = print_page_size->value() ? Fl_Paged_Device::A4 : Fl_Paged_Device::LETTER;
1546 { // page range choice
1547 int from = 1, to = pages;
1548 if (print_pages->value()) {
1549 sscanf(print_from->value(), "%d", &from);
1550 sscanf(print_to->value(), "%d", &to);
1551 }
1552 if (from < 1) from = 1;
1553 if (to > pages) to = pages;
1554 if (to < from) to = from;
1555 if (firstpage) *firstpage = from;
1556 if (lastpage) *lastpage = to;
1557 pages = to - from + 1;
1558 }
1559
1560 if (print_output_mode[0]->value()) layout = Fl_Paged_Device::PORTRAIT;
1561 else if (print_output_mode[1]->value()) layout = Fl_Paged_Device::LANDSCAPE;
1562 else if (print_output_mode[2]->value()) layout = Fl_Paged_Device::PORTRAIT;
1563 else layout = Fl_Paged_Device::LANDSCAPE;
1564
1565 int print_pipe = print_choice->value(); // 0 = print to file, >0 = printer (pipe)
1566
1567 const char *media = print_page_size->text(print_page_size->value());
1568 const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data();
1569 if (!print_pipe) printer = "<File>";
1570
1571 if (!print_pipe) // fall back to file printing
1572 return Fl_PostScript_File_Device::start_job (pages, format, layout);
1573
1574 // Print: pipe the output into the lp command...
1575
1576 char command[1024];
1577 snprintf(command, sizeof(command), "lp -s -d %s -n %d -t '%s' -o media=%s",
1578 printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5),
1579 "FLTK", media);
1580
1581 Fl_PostScript_Graphics_Driver *ps = driver();
1582 ps->output = popen(command, "w");
1583 if (!ps->output) {
1584 fl_alert("could not run command: %s\n",command);
1585 return 1;
1586 }
1587 ps->close_command(pclose);
1588 this->set_current();
1589 return ps->start_postscript(pages, format, layout); // start printing
1590}
1591
1592#endif // ! (defined(__APPLE__) || defined(WIN32) )
1593
1594#endif // FL_DOXYGEN
1595
1596//
1597// End of "$Id: Fl_PostScript.cxx 8623 2011-04-24 17:09:41Z AlbrechtS $".
1598//
int Fl_Font
A font number is an index into the internal font table.
Definition Enumerations.H:707
const Fl_Font FL_HELVETICA
Helvetica (or Arial) normal (0)
Definition Enumerations.H:709
Fl_Color fl_rgb_color(uchar r, uchar g, uchar b)
Returns the 24-bit color value closest to r, g, b.
Definition Enumerations.H:829
unsigned int Fl_Color
an FLTK color value
Definition Enumerations.H:764
const Fl_Font FL_FREE_FONT
first one to allocate
Definition Enumerations.H:726
int Fl_Fontsize
Size of a font in pixels.
Definition Enumerations.H:736
Fl static class.
FL_EXPORT Fl_Graphics_Driver * fl_graphics_driver
Points to the driver that currently receives all graphics requests.
Fl_Native_File_Chooser widget.
declaration of classes Fl_PostScript_Graphics_Driver, Fl_PostScript_File_Device.
static Fl_Display_Device * display_device()
Returns the platform display device.
Definition Fl_Device.H:626
A virtual class subclassed for each graphics driver FLTK uses.
Definition Fl_Device.H:110
virtual int height()=0
see fl_height().
Fl_Color color()
see fl_color(void).
Definition Fl_Device.H:400
Fl_Graphics_Driver()
The constructor.
Definition Fl_Device.cxx:77
static matrix * fl_matrix
Points to the current coordinate transformation matrix.
Definition Fl_Device.H:144
Fl_Font_Descriptor * font_descriptor()
Returns a pointer to the current Fl_Font_Descriptor for the graphics driver.
Definition Fl_Device.H:402
virtual void color(Fl_Color c)
see fl_color(Fl_Color c).
Definition Fl_Device.H:262
Fl_Fontsize size()
see fl_size().
Definition Fl_Device.H:388
virtual void font(Fl_Font face, Fl_Fontsize size)
see fl_font(Fl_Font face, Fl_Fontsize size).
Definition Fl_Device.H:384
Fl_Font font()
see fl_font(void).
Definition Fl_Device.H:386
This class lets an FLTK application easily and consistently access the operating system's native file...
Definition Fl_Native_File_Chooser.H:158
const char * filter() const
Returns the filter string last set.
Definition Fl_Native_File_Chooser_FLTK.cxx:300
void type(int)
Sets the current Fl_Native_File_Chooser::Type of browser.
Definition Fl_Native_File_Chooser_FLTK.cxx:112
void options(int)
Sets the platform specific chooser options to val.
Definition Fl_Native_File_Chooser_FLTK.cxx:137
const char * filename() const
Return the filename the user choose.
Definition Fl_Native_File_Chooser_FLTK.cxx:230
@ BROWSE_SAVE_FILE
browse to save a file
Definition Fl_Native_File_Chooser.H:165
int show()
Post the chooser's dialog.
Definition Fl_Native_File_Chooser_FLTK.cxx:155
@ SAVEAS_CONFIRM
Show native 'Save As' overwrite confirm dialog (if supported)
Definition Fl_Native_File_Chooser.H:170
void title(const char *)
Set the title of the file chooser's dialog window.
Definition Fl_Native_File_Chooser_FLTK.cxx:260
int y_offset
vertical offset to the origin of graphics coordinates
Definition Fl_Paged_Device.H:116
virtual void origin(int x, int y)
Sets the position in page coordinates of the origin of graphics functions.
Definition Fl_Paged_Device.cxx:204
Page_Layout
Possible page layouts.
Definition Fl_Paged_Device.H:90
@ REVERSED
Reversed orientation.
Definition Fl_Paged_Device.H:93
@ PORTRAIT
Portrait orientation.
Definition Fl_Paged_Device.H:91
@ LANDSCAPE
Landscape orientation.
Definition Fl_Paged_Device.H:92
int x_offset
horizontal offset to the origin of graphics coordinates
Definition Fl_Paged_Device.H:114
Page_Format
Possible page formats.
Definition Fl_Paged_Device.H:54
@ A4
A4 format.
Definition Fl_Paged_Device.H:59
@ LETTER
Letter format.
Definition Fl_Paged_Device.H:82
static const page_format page_formats[NO_PAGE_FORMATS]
width, height and name of all elements of the enum Page_Format.
Definition Fl_Paged_Device.H:254
void translate(int x, int y)
Translates the current graphics origin accounting for the current rotation.
Fl_PostScript_File_Device()
The constructor.
Definition Fl_PostScript.cxx:70
void untranslate(void)
Undoes the effect of a previous translate() call.
static const char * file_chooser_title
Label of the PostScript file chooser window.
Definition Fl_PostScript.H:246
~Fl_PostScript_File_Device()
The destructor.
Definition Fl_PostScript.cxx:145
int end_page(void)
To be called at the end of each page.
int start_job(int pagecount, enum Fl_Paged_Device::Page_Format format=Fl_Paged_Device::A4, enum Fl_Paged_Device::Page_Layout layout=Fl_Paged_Device::PORTRAIT)
Begins the session where all graphics requests will go to a local PostScript file.
Definition Fl_PostScript.cxx:96
void rotate(float angle)
Rotates the graphics operations relatively to paper.
Fl_PostScript_Graphics_Driver * driver()
Returns the PostScript driver of this drawing surface.
Definition Fl_PostScript.cxx:81
void margins(int *left, int *top, int *right, int *bottom)
Computes the dimensions of margins that lie between the printable page area and the full page.
void scale(float scale_x, float scale_y=0.)
Changes the scaling of page coordinates.
void end_job(void)
To be called at the end of a print job.
int start_page(void)
Starts a new printed page.
void origin(int *x, int *y)
Computes the page coordinates of the current origin of graphics functions.
int printable_rect(int *w, int *h)
Computes the width and height of the printable area of the page.
PostScript graphical backend.
Definition Fl_PostScript.H:64
void begin_polygon()
see fl_begin_polygon().
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H)
see fl_clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H).
void rect(int x, int y, int w, int h)
see fl_rect(int x, int y, int w, int h).
void arc(double x, double y, double r, double start, double a)
see fl_arc(double x, double y, double r, double start, double end).
void line_style(int style, int width=0, char *dashes=0)
see fl_line_style(int style, int width, char* dashes).
Fl_PostScript_Graphics_Driver()
The constructor.
Definition Fl_PostScript.cxx:51
void begin_line()
see fl_begin_line().
void pie(int x, int y, int w, int h, double a1, double a2)
see fl_pie(int x, int y, int w, int h, double a1, double a2).
void begin_loop()
see fl_begin_loop().
void pop_clip()
see fl_pop_clip().
void begin_points()
see fl_begin_points().
void end_points()
see fl_end_points().
void rtl_draw(const char *s, int n, int x, int y)
see fl_rtl_draw(const char *str, int n, int x, int y).
void transformed_vertex(double x, double y)
see fl_transformed_vertex(double xf, double yf).
void end_polygon()
see fl_end_polygon().
void xyline(int x, int y, int x1)
see fl_xyline(int x, int y, int x1).
double width(const char *, int)
see fl_width(const char *str, int n).
void polygon(int x0, int y0, int x1, int y1, int x2, int y2)
see fl_polygon(int x0, int y0, int x1, int y1, int x2, int y2).
void draw(const char *s, int n, int x, int y)
see fl_draw(const char *str, int n, int x, int y).
Definition Fl_PostScript.H:196
void loop(int x0, int y0, int x1, int y1, int x2, int y2)
see fl_loop(int x0, int y0, int x1, int y1, int x2, int y2).
void circle(double x, double y, double r)
see fl_circle(double x, double y, double r).
~Fl_PostScript_Graphics_Driver()
The destructor.
Definition Fl_PostScript.cxx:63
void line(int x1, int y1, int x2, int y2)
see fl_line(int x, int y, int x1, int y1).
void curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3)
see fl_curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3,...
void rectf(int x, int y, int w, int h)
see fl_rectf(int x, int y, int w, int h).
void end_loop()
see fl_end_loop().
void push_no_clip()
see fl_push_no_clip().
void point(int x, int y)
see fl_point(int x, int y).
void vertex(double x, double y)
see fl_vertex(double x, double y).
void yxline(int x, int y, int y1)
see fl_yxline(int x, int y, int y1).
void push_clip(int x, int y, int w, int h)
see fl_push_clip(int x, int y, int w, int h).
void text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h)
see fl_text_extents(const char*, int n, int& dx, int& dy, int& w, int& h).
int not_clipped(int x, int y, int w, int h)
see fl_not_clipped(int x, int y, int w, int h).
int height()
see fl_height().
int descent()
see fl_descent().
void end_line()
see fl_end_line().
int start_job(int pages, int *firstpage=NULL, int *lastpage=NULL)
Starts a print job.
void driver(Fl_Graphics_Driver *graphics_driver)
Sets the graphics driver of this drawing surface.
Definition Fl_Device.H:605
virtual void set_current(void)
Use this drawing surface for future graphics requests.
Definition Fl_Device.cxx:69
Fl_Graphics_Driver * driver()
Returns the graphics driver of this drawing surface.
Definition Fl_Device.H:607
static int wait()
Waits until "something happens" and then returns.
Definition Fl.cxx:605
utility header to pull drawing functions together
unsigned char uchar
unsigned char
Definition fl_types.h:39
FL_EXPORT Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg)
Returns a color that contrasts with the background color.
Definition fl_color.cxx:412
FL_EXPORT double fl_width(const char *txt)
Returns the typographical width of a nul-terminated string.
Definition fl_font.cxx:68
static unsigned get_color(Fl_Color i)
Returns the RGB value(s) for the given FLTK color index.
Definition fl_color.cxx:330
Fl_Font fl_font()
Returns the face set by the most recent call to fl_font().
Definition fl_draw.H:508
Fl_Color fl_color()
Returns the last fl_color() that was set.
Definition fl_draw.H:79
void fl_begin_offscreen(Fl_Offscreen ctx)
Send all subsequent drawing commands to this offscreen buffer.
Definition Fl_Double_Window.cxx:258
Fl_Offscreen fl_create_offscreen(int w, int h)
Creation of an offscreen graphics buffer.
Definition Fl_Double_Window.cxx:200
void fl_rectf(int x, int y, int w, int h)
Colors with current color a rectangle that exactly fills the given bounding box.
Definition fl_draw.H:217
void fl_rtl_draw(const char *str, int n, int x, int y)
Draws an array of n characters right to left starting at given location.
Definition fl_draw.H:615
void fl_delete_offscreen(Fl_Offscreen ctx)
Deletion of an offscreen graphics buffer.
Definition Fl_Double_Window.cxx:241
FL_EXPORT uchar * fl_read_image(uchar *p, int X, int Y, int W, int H, int alpha=0)
Reads an RGB(A) image from the current window or off-screen buffer.
Definition fl_read_image.cxx:91
void fl_end_offscreen()
Quit sending drawing commands to the current offscreen buffer.
Definition Fl_Double_Window.cxx:276
FL_EXPORT void fl_draw(const char *str, int x, int y)
Draws a nul-terminated string starting at the given location.
Definition fl_font.cxx:73
@ FL_CAP_SQUARE
cap style: end wraps end point
Definition fl_draw.H:196
@ FL_SOLID
line style: ___________
Definition fl_draw.H:188
FL_EXPORT unsigned fl_utf8decode(const char *p, const char *end, int *len)
Definition fl_utf.c:140
int width
width in points
Definition Fl_Paged_Device.H:101
int height
height in points
Definition Fl_Paged_Device.H:103