PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/fltk/src/Fl_PS_Printer.cxx

http://luafltk.googlecode.com/
C++ | 1354 lines | 1050 code | 198 blank | 106 comment | 118 complexity | bf511c15b0b59ed7cab33bebbaec3bfd MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-3.0, 0BSD
  1. //
  2. // "$Id: Fl_PS_Printer.cxx 7522 2010-04-18 06:57:37Z manolo $"
  3. //
  4. // PostScript device support for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 2010 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. #include <FL/Fl.H>
  28. #include <FL/fl_ask.H>
  29. #include <FL/fl_draw.H>
  30. #include <stdio.h>
  31. #include <FL/Fl_PSfile_Device.H>
  32. #include <FL/Fl_Native_File_Chooser.H>
  33. const char *Fl_PSfile_Device::file_chooser_title = "Select a .ps file";
  34. /**
  35. @brief The constructor.
  36. */
  37. Fl_PSfile_Device::Fl_PSfile_Device(void)
  38. {
  39. close_cmd_ = 0;
  40. //lang_level_ = 3;
  41. lang_level_ = 2;
  42. mask = 0;
  43. ps_filename_ = NULL;
  44. type_ = postscript_device;
  45. scale_x = scale_y = 1.;
  46. #ifdef __APPLE__
  47. gc = fl_gc; // the display context is used by fl_text_extents()
  48. #endif
  49. }
  50. /**
  51. @brief Begins the session where all graphics requests will go to a local PostScript file.
  52. *
  53. Opens a file dialog entitled with Fl_PSfile_Device::file_chooser_title to select an output PostScript file.
  54. @param pagecount The total number of pages to be created.
  55. @param format Desired page format.
  56. @param layout Desired page layout.
  57. @return 0 iff OK, 1 if user cancelled the file dialog, 2 if fopen failed on user-selected output file.
  58. */
  59. int Fl_PSfile_Device::start_job (int pagecount, enum Page_Format format, enum Page_Layout layout)
  60. {
  61. Fl_Native_File_Chooser fnfc;
  62. fnfc.title(Fl_PSfile_Device::file_chooser_title);
  63. fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
  64. fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM);
  65. fnfc.filter("PostScript\t*.ps\n");
  66. // Show native chooser
  67. if ( fnfc.show() ) return 1;
  68. output = fopen(fnfc.filename(), "w");
  69. if(output == NULL) return 2;
  70. ps_filename_ = strdup(fnfc.filename());
  71. start_postscript(pagecount, format, layout);
  72. return 0;
  73. }
  74. /**
  75. @brief Begins the session where all graphics requests will go to FILE pointer.
  76. *
  77. @param ps_output A writable FILE pointer that will receive PostScript output and that will be closed
  78. when end_job() will be called.
  79. @param pagecount The total number of pages to be created.
  80. @param format Desired page format.
  81. @param layout Desired page layout.
  82. @return always 0.
  83. */
  84. int Fl_PSfile_Device::start_job (FILE *ps_output, int pagecount, enum Page_Format format, enum Page_Layout layout)
  85. {
  86. output = ps_output;
  87. ps_filename_ = NULL;
  88. start_postscript(pagecount, format, layout);
  89. return 0;
  90. }
  91. /**
  92. @brief The destructor.
  93. */
  94. Fl_PSfile_Device::~Fl_PSfile_Device() {
  95. if (ps_filename_) free(ps_filename_);
  96. }
  97. #ifndef FL_DOXYGEN
  98. #if ! (defined(__APPLE__) || defined(WIN32) )
  99. #include "print_panel.cxx"
  100. #endif
  101. const Fl_PSfile_Device::page_format Fl_PSfile_Device::page_formats[NO_PAGE_FORMATS] = { // order of enum Page_Format
  102. // comes from appendix B of 5003.PPD_Spec_v4.3.pdf
  103. // A* // index(Ai) = i
  104. {2384, 3370, "A0"},
  105. {1684, 2384, "A1"},
  106. {1191, 1684, "A2"},
  107. { 842, 1191, "A3"},
  108. { 595, 842, "A4"},
  109. { 420, 595, "A5"},
  110. { 297, 420, "A6"},
  111. { 210, 297, "A7"},
  112. { 148, 210, "A8"},
  113. { 105, 148, "A9"},
  114. // B* // index(Bi) = i+10
  115. {2920, 4127, "B0"},
  116. {2064, 2920, "B1"},
  117. {1460, 2064, "B2"},
  118. {1032, 1460, "B3"},
  119. { 729, 1032, "B4"},
  120. { 516, 729, "B5"},
  121. { 363, 516, "B6"},
  122. { 258, 363, "B7"},
  123. { 181, 258, "B8"},
  124. { 127, 181, "B9"},
  125. { 91, 127, "B10"},
  126. // others
  127. { 459, 649, "EnvC5"}, // envelope
  128. { 312, 624, "EnvDL"}, // envelope
  129. { 522, 756, "Executive"},
  130. { 595, 935, "Folio"},
  131. {1224, 792, "Ledger"}, // landscape
  132. { 612, 1008, "Legal"},
  133. { 612, 792, "Letter"},
  134. { 792, 1224, "Tabloid"},
  135. { 297, 684, "Env10"} // envelope
  136. };
  137. // Prolog string
  138. static const char * prolog =
  139. "%%BeginProlog\n"
  140. "/L { /y2 exch def\n"
  141. "/x2 exch def\n"
  142. "/y1 exch def\n"
  143. "/x1 exch def\n"
  144. "newpath x1 y1 moveto x2 y2 lineto\n"
  145. "stroke}\n"
  146. "bind def\n"
  147. "/R { /dy exch def\n"
  148. "/dx exch def\n"
  149. "/y exch def\n"
  150. "/x exch def\n"
  151. "newpath\n"
  152. "x y moveto\n"
  153. "dx 0 rlineto\n"
  154. "0 dy rlineto\n"
  155. "dx neg 0 rlineto\n"
  156. "closepath stroke\n"
  157. "} bind def\n"
  158. "/CL {\n"
  159. "/dy exch def\n"
  160. "/dx exch def\n"
  161. "/y exch def\n"
  162. "/x exch def\n"
  163. "newpath\n"
  164. "x y moveto\n"
  165. "dx 0 rlineto\n"
  166. "0 dy rlineto\n"
  167. "dx neg 0 rlineto\n"
  168. "closepath\n"
  169. "clip\n"
  170. "} bind def\n"
  171. "/FR { /dy exch def\n"
  172. "/dx exch def\n"
  173. "/y exch def\n"
  174. "/x exch def\n"
  175. "currentlinewidth 0 setlinewidth newpath\n"
  176. "x y moveto\n"
  177. "dx 0 rlineto\n"
  178. "0 dy rlineto\n"
  179. "dx neg 0 rlineto\n"
  180. "closepath fill setlinewidth\n"
  181. "} bind def\n"
  182. "/GS { gsave } bind def\n"
  183. "/GR { grestore } bind def\n"
  184. "/SP { showpage } bind def\n"
  185. "/LW { setlinewidth } bind def\n"
  186. "/CF /Courier def\n"
  187. "/SF { /CF exch def } bind def\n"
  188. "/fsize 12 def\n"
  189. "/FS { /fsize exch def fsize CF findfont exch scalefont setfont }def \n"
  190. "/GL { setgray } bind def\n"
  191. "/SRGB { setrgbcolor } bind def\n"
  192. // color images
  193. "/CI { GS /py exch def /px exch def /sy exch def /sx exch def\n"
  194. "translate \n"
  195. "sx sy scale px py 8 \n"
  196. "[ px 0 0 py neg 0 py ]\n"
  197. "currentfile /ASCIIHexDecode filter\n false 3"
  198. " colorimage GR\n"
  199. "} bind def\n"
  200. // gray images
  201. "/GI { GS /py exch def /px exch def /sy exch def /sx exch def \n"
  202. "translate \n"
  203. "sx sy scale px py 8 \n"
  204. "[ px 0 0 py neg 0 py ]\n"
  205. "currentfile /ASCIIHexDecode filter\n"
  206. "image GR\n"
  207. "} bind def\n"
  208. // single-color bitmask
  209. "/MI { GS /py exch def /px exch def /sy exch def /sx exch def \n"
  210. "translate \n"
  211. "sx sy scale px py false \n"
  212. "[ px 0 0 py neg 0 py ]\n"
  213. "currentfile /ASCIIHexDecode filter\n"
  214. "imagemask GR\n"
  215. "} bind def\n"
  216. // path
  217. "/BFP { newpath moveto } def\n"
  218. "/BP { newpath } bind def \n"
  219. "/PL { lineto } bind def \n"
  220. "/PM { moveto } bind def \n"
  221. "/MT { moveto } bind def \n"
  222. "/LT { lineto } bind def \n"
  223. "/EFP { closepath fill } bind def\n" //was:stroke
  224. "/ELP { stroke } bind def\n"
  225. "/ECP { closepath stroke } bind def\n" // Closed (loop)
  226. "/LW { setlinewidth } bind def\n"
  227. // ////////////////////////// misc ////////////////
  228. "/TR { translate } bind def\n"
  229. "/CT { concat } bind def\n"
  230. "/RCT { matrix invertmatrix concat} bind def\n"
  231. "/SC { scale } bind def\n"
  232. //"/GPD { currentpagedevice /PageSize get} def\n"
  233. // show at position with desired width
  234. // usage:
  235. // width (string) x y show_pos_width
  236. "/show_pos_width {GS moveto dup dup stringwidth pop exch length exch 3 index exch sub exch "
  237. "div 0 2 index 1 -1 scale ashow pop pop GR} bind def\n" // spacing altered to match desired width
  238. //"/show_pos_width {GS moveto dup stringwidth pop 3 2 roll exch div -1 matrix scale concat "
  239. //"show GR } bind def\n" // horizontally scaled text to match desired width
  240. ;
  241. static const char * prolog_2 = // prolog relevant only if lang_level >1
  242. // color image dictionaries
  243. "/CII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n"
  244. "translate \n"
  245. "sx sy scale\n"
  246. "/DeviceRGB setcolorspace\n"
  247. "/IDD 8 dict def\n"
  248. "IDD begin\n"
  249. "/ImageType 1 def\n"
  250. "/Width px def\n"
  251. "/Height py def\n"
  252. "/BitsPerComponent 8 def\n"
  253. "/Interpolate inter def\n"
  254. "/DataSource currentfile /ASCIIHexDecode filter def\n"
  255. "/MultipleDataSources false def\n"
  256. "/ImageMatrix [ px 0 0 py neg 0 py ] def\n"
  257. "/Decode [ 0 1 0 1 0 1 ] def\n"
  258. "end\n"
  259. "IDD image GR} bind def\n"
  260. // gray image dict
  261. "/GII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n"
  262. "translate \n"
  263. "sx sy scale\n"
  264. "/DeviceGray setcolorspace\n"
  265. "/IDD 8 dict def\n"
  266. "IDD begin\n"
  267. "/ImageType 1 def\n"
  268. "/Width px def\n"
  269. "/Height py def\n"
  270. "/BitsPerComponent 8 def\n"
  271. "/Interpolate inter def\n"
  272. "/DataSource currentfile /ASCIIHexDecode filter def\n"
  273. "/MultipleDataSources false def\n"
  274. "/ImageMatrix [ px 0 0 py neg 0 py ] def\n"
  275. "/Decode [ 0 1 ] def\n"
  276. "end\n"
  277. "IDD image GR} bind def\n"
  278. ;
  279. static const char * prolog_2_pixmap = // prolog relevant only if lang_level == 2 for pixmaps
  280. "/pixmap_size { /pixmap_sy exch def /pixmap_sx exch def } bind def\n"
  281. "/pixmap_mat {[ pixmap_sx 0 0 pixmap_sy neg 0 pixmap_sy ]} bind def\n"
  282. "/pixmap_dict {"
  283. "<< /PatternType 1 "
  284. "/PaintType 1 "
  285. "/TilingType 2 "
  286. "/BBox [0 0 pixmap_sx pixmap_sy] "
  287. "/XStep pixmap_sx "
  288. "/YStep pixmap_sy\n"
  289. "/PaintProc "
  290. "{ begin "
  291. "pixmap_sx pixmap_sy scale "
  292. "pixmap_sx pixmap_sy 8 "
  293. "pixmap_mat "
  294. "pixmap_data "
  295. "false 3 "
  296. "colorimage "
  297. "end "
  298. "} bind "
  299. ">>\n"
  300. "} bind def\n"
  301. "/pixmap_plot {"
  302. "GS "
  303. "/pixmap_y exch def /pixmap_x exch def\n"
  304. "pixmap_x pixmap_y translate\n"
  305. "pixmap_dict matrix makepattern setpattern\n"
  306. "pixmap_sx pixmap_sy scale\n"
  307. "pixmap_sx pixmap_sy\n"
  308. "true\n"
  309. "pixmap_mat\n"
  310. "pixmap_mask\n"
  311. "imagemask\n"
  312. "GR\n"
  313. "} bind def\n"
  314. "/pixmap_loaddata { /pixmap_data currentfile pixmap_sx pixmap_sy 3 mul mul string readhexstring "
  315. "} bind def\n"
  316. "/pixmap_loadmask { "
  317. "/pixmap_mask currentfile pixmap_sx 8 div ceiling cvi pixmap_sy mul string readhexstring "
  318. "} bind def\n"
  319. ;
  320. static const char * prolog_3 = // prolog relevant only if lang_level >2
  321. // masked color images
  322. "/CIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n"
  323. "translate \n"
  324. "sx sy scale\n"
  325. "/DeviceRGB setcolorspace\n"
  326. "/IDD 8 dict def\n"
  327. "IDD begin\n"
  328. "/ImageType 1 def\n"
  329. "/Width px def\n"
  330. "/Height py def\n"
  331. "/BitsPerComponent 8 def\n"
  332. "/Interpolate inter def\n"
  333. "/DataSource currentfile /ASCIIHexDecode filter def\n"
  334. "/MultipleDataSources false def\n"
  335. "/ImageMatrix [ px 0 0 py neg 0 py ] def\n"
  336. "/Decode [ 0 1 0 1 0 1 ] def\n"
  337. "end\n"
  338. "/IMD 8 dict def\n"
  339. "IMD begin\n"
  340. "/ImageType 1 def\n"
  341. "/Width mx def\n"
  342. "/Height my def\n"
  343. "/BitsPerComponent 1 def\n"
  344. // "/Interpolate inter def\n"
  345. "/ImageMatrix [ mx 0 0 my neg 0 my ] def\n"
  346. "/Decode [ 1 0 ] def\n"
  347. "end\n"
  348. "<<\n"
  349. "/ImageType 3\n"
  350. "/InterleaveType 2\n"
  351. "/MaskDict IMD\n"
  352. "/DataDict IDD\n"
  353. ">> image GR\n"
  354. "} bind def\n"
  355. // masked gray images
  356. "/GIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n"
  357. "translate \n"
  358. "sx sy scale\n"
  359. "/DeviceGray setcolorspace\n"
  360. "/IDD 8 dict def\n"
  361. "IDD begin\n"
  362. "/ImageType 1 def\n"
  363. "/Width px def\n"
  364. "/Height py def\n"
  365. "/BitsPerComponent 8 def\n"
  366. "/Interpolate inter def\n"
  367. "/DataSource currentfile /ASCIIHexDecode filter def\n"
  368. "/MultipleDataSources false def\n"
  369. "/ImageMatrix [ px 0 0 py neg 0 py ] def\n"
  370. "/Decode [ 0 1 ] def\n"
  371. "end\n"
  372. "/IMD 8 dict def\n"
  373. "IMD begin\n"
  374. "/ImageType 1 def\n"
  375. "/Width mx def\n"
  376. "/Height my def\n"
  377. "/BitsPerComponent 1 def\n"
  378. "/ImageMatrix [ mx 0 0 my neg 0 my ] def\n"
  379. "/Decode [ 1 0 ] def\n"
  380. "end\n"
  381. "<<\n"
  382. "/ImageType 3\n"
  383. "/InterleaveType 2\n"
  384. "/MaskDict IMD\n"
  385. "/DataDict IDD\n"
  386. ">> image GR\n"
  387. "} bind def\n"
  388. "\n"
  389. ;
  390. // end prolog
  391. int Fl_PSfile_Device::start_postscript (int pagecount, enum Page_Format format, enum Page_Layout layout)
  392. //returns 0 iff OK
  393. {
  394. int w, h, x;
  395. this->set_current();
  396. if (format == A4) {
  397. left_margin = 18;
  398. top_margin = 18;
  399. }
  400. else {
  401. left_margin = 12;
  402. top_margin = 12;
  403. }
  404. page_format_ = (enum Page_Format)(format | layout);
  405. fputs("%!PS-Adobe-3.0\n", output);
  406. fputs("%%Creator: FLTK\n", output);
  407. if (lang_level_>1)
  408. fprintf(output, "%%%%LanguageLevel: %i\n" , lang_level_);
  409. if ((pages_ = pagecount))
  410. fprintf(output, "%%%%Pages: %i\n", pagecount);
  411. else
  412. fputs("%%Pages: (atend)\n", output);
  413. fprintf(output, "%%%%BeginFeature: *PageSize %s\n", page_formats[format].name );
  414. w = page_formats[format].width;
  415. h = page_formats[format].height;
  416. if (lang_level_ == 3 && (layout & LANDSCAPE) ) { x = w; w = h; h = x; }
  417. fprintf(output, "<</PageSize[%d %d]>>setpagedevice\n", w, h );
  418. fputs("%%EndFeature\n", output);
  419. fputs("%%EndComments\n", output);
  420. fputs(prolog, output);
  421. if (lang_level_ > 1) {
  422. fputs(prolog_2, output);
  423. }
  424. if (lang_level_ == 2) {
  425. fputs(prolog_2_pixmap, output);
  426. }
  427. if (lang_level_ > 2)
  428. fputs(prolog_3, output);
  429. if (lang_level_ >= 3) {
  430. fputs("/CS { clipsave } bind def\n", output);
  431. fputs("/CR { cliprestore } bind def\n", output);
  432. } else {
  433. fputs("/CS { GS } bind def\n", output);
  434. fputs("/CR { GR } bind def\n", output);
  435. }
  436. page_policy_ = 1;
  437. fputs("%%EndProlog\n",output);
  438. if (lang_level_ >= 2)
  439. fprintf(output,"<< /Policies << /Pagesize 1 >> >> setpagedevice\n");
  440. reset();
  441. nPages=0;
  442. return 0;
  443. }
  444. void Fl_PSfile_Device::recover(){
  445. color(cr_,cg_,cb_);
  446. line_style(linestyle_,linewidth_,linedash_);
  447. font(font_,size_);
  448. }
  449. void Fl_PSfile_Device::reset(){
  450. gap_=1;
  451. clip_=0;
  452. cr_=cg_=cb_=0;
  453. font_=FL_HELVETICA;
  454. size_=12;
  455. linewidth_=0;
  456. linestyle_=FL_SOLID;
  457. strcpy(linedash_,"");
  458. Clip *c=clip_; ////just not to have memory leaks for badly writen code (forgotten clip popping)
  459. while(c){
  460. clip_=clip_->prev;
  461. delete c;
  462. c=clip_;
  463. }
  464. }
  465. void Fl_PSfile_Device::page_policy(int p){
  466. page_policy_ = p;
  467. if(lang_level_>=2)
  468. fprintf(output,"<< /Policies << /Pagesize %i >> >> setpagedevice\n", p);
  469. }
  470. // //////////////////// paging //////////////////////////////////////////
  471. void Fl_PSfile_Device::page(double pw, double ph, int media) {
  472. if (nPages){
  473. fprintf(output, "CR\nGR\nGR\nGR\nSP\nrestore\n");
  474. }
  475. ++nPages;
  476. fprintf(output, "%%%%Page: %i %i\n" , nPages , nPages);
  477. if (pw>ph){
  478. fprintf(output, "%%%%PageOrientation: Landscape\n");
  479. }else{
  480. fprintf(output, "%%%%PageOrientation: Portrait\n");
  481. }
  482. fprintf(output, "%%%%BeginPageSetup\n");
  483. if((media & MEDIA) &&(lang_level_>1)){
  484. int r = media & REVERSED;
  485. if(r) r = 2;
  486. fprintf(output, "<< /PageSize [%i %i] /Orientation %i>> setpagedevice\n", (int)(pw+.5), (int)(ph+.5), r);
  487. }
  488. fprintf(output, "%%%%EndPageSetup\n");
  489. pw_ = pw;
  490. ph_ = ph;
  491. reset();
  492. fprintf(output, "save\n");
  493. fprintf(output, "GS\n");
  494. fprintf(output, "%g %g TR\n", (double)0 /*lm_*/ , ph_ /* - tm_*/);
  495. fprintf(output, "1 -1 SC\n");
  496. line_style(0);
  497. fprintf(output, "GS\n");
  498. if (!((media & MEDIA) &&(lang_level_>1))){
  499. if (pw > ph) {
  500. if(media & REVERSED) {
  501. fprintf(output, "-90 rotate %i 0 translate\n", int(-pw));
  502. }
  503. else {
  504. fprintf(output, "90 rotate -%i -%i translate\n", (lang_level_ == 2 ? int(pw - ph) : 0), int(ph));
  505. }
  506. }
  507. else {
  508. if(media & REVERSED)
  509. fprintf(output, "180 rotate %i %i translate\n", int(-pw), int(-ph));
  510. }
  511. }
  512. fprintf(output, "GS\nCS\n");
  513. };
  514. void Fl_PSfile_Device::page(int format){
  515. if(format & LANDSCAPE){
  516. ph_=Fl_PSfile_Device::page_formats[format & 0xFF].width;
  517. pw_=Fl_PSfile_Device::page_formats[format & 0xFF].height;
  518. }else{
  519. pw_=Fl_PSfile_Device::page_formats[format & 0xFF].width;
  520. ph_=Fl_PSfile_Device::page_formats[format & 0xFF].height;
  521. }
  522. page(pw_,ph_,format & 0xFF00);//,orientation only;
  523. };
  524. void Fl_PSfile_Device::rect(int x, int y, int w, int h) {
  525. // Commented code does not work, i can't find the bug ;-(
  526. // fprintf(output, "GS\n");
  527. // fprintf(output, "%i, %i, %i, %i R\n", x , y , w, h);
  528. // fprintf(output, "GR\n");
  529. fprintf(output, "GS\n");
  530. fprintf(output,"BP\n");
  531. fprintf(output, "%i %i MT\n", x , y);
  532. fprintf(output, "%i %i LT\n", x+w-1 , y);
  533. fprintf(output, "%i %i LT\n", x+w-1 , y+h-1);
  534. fprintf(output, "%i %i LT\n", x , y+h-1);
  535. fprintf(output, "ECP\n");
  536. fprintf(output, "GR\n");
  537. }
  538. void Fl_PSfile_Device::rectf(int x, int y, int w, int h) {
  539. fprintf(output, "%g %g %i %i FR\n", x-0.5, y-0.5, w, h);
  540. }
  541. void Fl_PSfile_Device::line(int x1, int y1, int x2, int y2) {
  542. fprintf(output, "GS\n");
  543. fprintf(output, "%i %i %i %i L\n", x1 , y1, x2 ,y2);
  544. fprintf(output, "GR\n");
  545. }
  546. void Fl_PSfile_Device::line(int x0, int y0, int x1, int y1, int x2, int y2) {
  547. fprintf(output, "GS\n");
  548. fprintf(output,"BP\n");
  549. fprintf(output, "%i %i MT\n", x0 , y0);
  550. fprintf(output, "%i %i LT\n", x1 , y1);
  551. fprintf(output, "%i %i LT\n", x2 , y2);
  552. fprintf(output, "ELP\n");
  553. fprintf(output, "GR\n");
  554. }
  555. void Fl_PSfile_Device::xyline(int x, int y, int x1, int y2, int x3){
  556. fprintf(output, "GS\n");
  557. fprintf(output,"BP\n");
  558. fprintf(output, "%i %i MT\n", x , y );
  559. fprintf(output, "%i %i LT\n", x1 , y );
  560. fprintf(output, "%i %i LT\n", x1 , y2);
  561. fprintf(output,"%i %i LT\n", x3 , y2);
  562. fprintf(output, "ELP\n");
  563. fprintf(output, "GR\n");
  564. };
  565. void Fl_PSfile_Device::xyline(int x, int y, int x1, int y2){
  566. fprintf(output, "GS\n");
  567. fprintf(output,"BP\n");
  568. fprintf(output, "%i %i MT\n", x , y);
  569. fprintf(output,"%i %i LT\n", x1 , y);
  570. fprintf(output, "%i %i LT\n", x1 , y2 );
  571. fprintf(output, "ELP\n");
  572. fprintf(output, "GR\n");
  573. };
  574. void Fl_PSfile_Device::xyline(int x, int y, int x1){
  575. fprintf(output, "GS\n");
  576. fprintf(output,"BP\n");
  577. fprintf(output, "%i %i MT\n", x , y);
  578. fprintf(output, "%i %i LT\n", x1 , y );
  579. fprintf(output, "ELP\n");
  580. fprintf(output, "GR\n");
  581. };
  582. void Fl_PSfile_Device::yxline(int x, int y, int y1, int x2, int y3){
  583. fprintf(output, "GS\n");
  584. fprintf(output,"BP\n");
  585. fprintf(output,"%i %i MT\n", x , y);
  586. fprintf(output, "%i %i LT\n", x , y1 );
  587. fprintf(output, "%i %i LT\n", x2 , y1 );
  588. fprintf(output , "%i %i LT\n", x2 , y3);
  589. fprintf(output, "ELP\n");
  590. fprintf(output, "GR\n");
  591. };
  592. void Fl_PSfile_Device::yxline(int x, int y, int y1, int x2){
  593. fprintf(output, "GS\n");
  594. fprintf(output,"BP\n");
  595. fprintf(output, "%i %i MT\n", x , y);
  596. fprintf(output, "%i %i LT\n", x , y1);
  597. fprintf(output, "%i %i LT\n", x2 , y1);
  598. fprintf(output, "ELP\n");
  599. fprintf(output, "GR\n");
  600. };
  601. void Fl_PSfile_Device::yxline(int x, int y, int y1){
  602. fprintf(output, "GS\n");
  603. fprintf(output,"BP\n");
  604. fprintf(output, "%i %i MT\n", x , y);
  605. fprintf(output, "%i %i LT\n", x , y1);
  606. fprintf(output, "ELP\n");
  607. fprintf(output, "GR\n");
  608. };
  609. void Fl_PSfile_Device::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
  610. fprintf(output, "GS\n");
  611. fprintf(output,"BP\n");
  612. fprintf(output, "%i %i MT\n", x0 , y0);
  613. fprintf(output, "%i %i LT\n", x1 , y1);
  614. fprintf(output, "%i %i LT\n", x2 , y2);
  615. fprintf(output, "ECP\n");
  616. fprintf(output, "GR\n");
  617. }
  618. void Fl_PSfile_Device::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
  619. fprintf(output, "GS\n");
  620. fprintf(output,"BP\n");
  621. fprintf(output, "%i %i MT\n", x0 , y0);
  622. fprintf(output, "%i %i LT\n", x1 , y1);
  623. fprintf(output, "%i %i LT\n", x2 , y2);
  624. fprintf(output, "%i %i LT\n", x3 , y3);
  625. fprintf(output, "ECP\n");
  626. fprintf(output, "GR\n");
  627. }
  628. void Fl_PSfile_Device::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
  629. fprintf(output, "GS\n");
  630. fprintf(output,"BP\n");
  631. fprintf(output, "%i %i MT\n", x0 , y0);
  632. fprintf(output,"%i %i LT\n", x1 , y1);
  633. fprintf(output, "%i %i LT\n", x2 , y2);
  634. fprintf(output, "EFP\n");
  635. fprintf(output, "GR\n");
  636. }
  637. void Fl_PSfile_Device::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
  638. fprintf(output, "GS\n");
  639. fprintf(output,"BP\n");
  640. fprintf(output, "%i %i MT\n", x0 , y0 );
  641. fprintf(output, "%i %i LT\n", x1 , y1 );
  642. fprintf(output, "%i %i LT\n", x2 , y2 );
  643. fprintf(output, "%i %i LT\n", x3 , y3 );
  644. fprintf(output, "EFP\n");
  645. fprintf(output, "GR\n");
  646. }
  647. void Fl_PSfile_Device::point(int x, int y){
  648. rectf(x,y,1,1);
  649. }
  650. static int dashes_flat[5][7]={
  651. {-1,0,0,0,0,0,0},
  652. {3,1,-1,0,0,0,0},
  653. {1,1,-1,0,0,0,0},
  654. {3,1,1,1,-1,0,0},
  655. {3,1,1,1,1,1,-1}
  656. };
  657. //yeah, hack...
  658. static double dashes_cap[5][7]={
  659. {-1,0,0,0,0,0,0},
  660. {2,2,-1,0,0,0,0},
  661. {0.01,1.99,-1,0,0,0,0},
  662. {2,2,0.01,1.99,-1,0,0},
  663. {2,2,0.01,1.99,0.01,1.99,-1}
  664. };
  665. void Fl_PSfile_Device::line_style(int style, int width, char* dashes){
  666. //line_styled_=1;
  667. linewidth_=width;
  668. linestyle_=style;
  669. //dashes_= dashes;
  670. if(dashes){
  671. if(dashes != linedash_)
  672. strcpy(linedash_,dashes);
  673. }else
  674. linedash_[0]=0;
  675. char width0 = 0;
  676. if(!width){
  677. width=1; //for screen drawing compatability
  678. width0=1;
  679. }
  680. fprintf(output, "%i setlinewidth\n", width);
  681. if(!style && (!dashes || !(*dashes)) && width0) //system lines
  682. style = FL_CAP_SQUARE;
  683. int cap = (style &0xf00) >> 8;
  684. if(cap) cap--;
  685. fprintf(output,"%i setlinecap\n", cap);
  686. int join = (style & 0xf000) >> 12;
  687. if(join) join--;
  688. fprintf(output,"%i setlinejoin\n", join);
  689. fprintf(output, "[");
  690. if(dashes && *dashes){
  691. while(*dashes){
  692. fprintf(output, "%i ", *dashes);
  693. dashes++;
  694. }
  695. }else{
  696. int * ds;
  697. if(style & 0x200){ // round and square caps, dash length need to be adjusted
  698. double *dt = dashes_cap[style & 0xff];
  699. while (*dt >= 0){
  700. fprintf(output, "%g ",width * (*dt));
  701. dt++;
  702. }
  703. }else{
  704. ds = dashes_flat[style & 0xff];
  705. while (*ds >= 0){
  706. fprintf(output, "%i ",width * (*ds));
  707. ds++;
  708. }
  709. }
  710. }
  711. fprintf(output, "] 0 setdash\n");
  712. };
  713. static const char *_fontNames[] = {
  714. "Helvetica",
  715. "Helvetica-Bold",
  716. "Helvetica-Oblique",
  717. "Helvetica-BoldOblique",
  718. "Courier",
  719. "Courier-Bold",
  720. "Courier-Oblique",
  721. "Courier-BoldOblique",
  722. "Times",
  723. "Times-Bold",
  724. "Times-Italic",
  725. "Times-BoldItalic",
  726. "Symbol",
  727. "Courier",
  728. "Courier-Bold",
  729. "ZapfDingbats"
  730. };
  731. void Fl_PSfile_Device::font(int f, int s) {
  732. if (f >= FL_FREE_FONT)
  733. f = FL_COURIER;
  734. fprintf(output, "/%s SF\n" , _fontNames[f]);
  735. fprintf(output,"%i FS\n", s);
  736. Fl_Device::display_device()->font(f,s); // Use display fonts for font measurement
  737. font_ = f; size_ = s;
  738. };
  739. void Fl_PSfile_Device::color(Fl_Color c) {
  740. //colored_=1;
  741. color_=c;
  742. Fl::get_color(c, cr_, cg_, cb_);
  743. if (cr_==cg_ && cg_==cb_) {
  744. double gray = cr_/255.0;
  745. fprintf(output, "%g GL\n", gray);
  746. } else {
  747. double fr, fg, fb;
  748. fr = cr_/255.0;
  749. fg = cg_/255.0;
  750. fb = cb_/255.0;
  751. fprintf(output,"%g %g %g SRGB\n", fr , fg , fb);
  752. }
  753. }
  754. void Fl_PSfile_Device::color(unsigned char r, unsigned char g, unsigned char b) {
  755. //colored_=1;
  756. cr_=r;cg_=g;cb_=b;
  757. if (r==g && g==b) {
  758. double gray = r/255.0;
  759. fprintf(output, "%g GL\n", gray);
  760. } else {
  761. double fr, fg, fb;
  762. fr = r/255.0;
  763. fg = g/255.0;
  764. fb = b/255.0;
  765. fprintf(output, "%g %g %g SRGB\n", fr , fg , fb);
  766. }
  767. }
  768. void Fl_PSfile_Device::draw(int angle, const char *str, int n, int x, int y)
  769. {
  770. fprintf(output, "GS %d %d translate %d rotate\n", x, y, - angle);
  771. this->transformed_draw(str, n, 0, 0);
  772. fprintf(output, "GR\n");
  773. }
  774. void Fl_PSfile_Device::transformed_draw(const char* str, int n, double x, double y){
  775. if (!n || !str || !*str)return;
  776. fprintf(output,"%g (", fl_width(str, n));
  777. int i=1;
  778. for (int j=0;j<n;j++){
  779. if (i>240){
  780. fprintf(output, "\\\n");
  781. i=0;
  782. }
  783. i++;
  784. switch (*str) {
  785. case '(': case ')': case '\\' :
  786. putc('\\' , output);
  787. /* fallthrough */
  788. default:
  789. putc(*str , output);
  790. }
  791. str++;
  792. }
  793. fprintf(output, ") %g %g show_pos_width\n", x, y);
  794. }
  795. struct matrix {double a, b, c, d, x, y;};
  796. extern matrix * fl_matrix;
  797. void Fl_PSfile_Device::concat(){
  798. 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);
  799. }
  800. void Fl_PSfile_Device::reconcat(){
  801. 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);
  802. }
  803. ///////////////// transformed (double) drawings ////////////////////////////////
  804. void Fl_PSfile_Device::begin_points(){
  805. fprintf(output, "GS\n");
  806. concat();
  807. fprintf(output, "BP\n");
  808. gap_=1;
  809. shape_=POINTS;
  810. };
  811. void Fl_PSfile_Device::begin_line(){
  812. fprintf(output, "GS\n");
  813. concat();
  814. fprintf(output, "BP\n");
  815. gap_=1;
  816. shape_=LINE;
  817. };
  818. void Fl_PSfile_Device::begin_loop(){
  819. fprintf(output, "GS\n");
  820. concat();
  821. fprintf(output, "BP\n");
  822. gap_=1;
  823. shape_=LOOP;
  824. };
  825. void Fl_PSfile_Device::begin_polygon(){
  826. fprintf(output, "GS\n");
  827. concat();
  828. fprintf(output, "BP\n");
  829. gap_=1;
  830. shape_=POLYGON;
  831. };
  832. void Fl_PSfile_Device::vertex(double x, double y){
  833. if(shape_==POINTS){
  834. fprintf(output,"%g %g MT\n", x , y);
  835. gap_=1;
  836. return;
  837. }
  838. if(gap_){
  839. fprintf(output,"%g %g MT\n", x , y);
  840. gap_=0;
  841. }else
  842. fprintf(output, "%g %g LT\n", x , y);
  843. };
  844. void Fl_PSfile_Device::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3){
  845. if(shape_==NONE) return;
  846. if(gap_)
  847. fprintf(output,"%g %g MT\n", x , y);
  848. else
  849. fprintf(output, "%g %g LT\n", x , y);
  850. gap_=0;
  851. fprintf(output, "%g %g %g %g %g %g curveto \n", x1 , y1 , x2 , y2 , x3 , y3);
  852. };
  853. void Fl_PSfile_Device::circle(double x, double y, double r){
  854. if(shape_==NONE){
  855. fprintf(output, "GS\n");
  856. concat();
  857. // fprintf(output, "BP\n");
  858. fprintf(output,"%g %g %g 0 360 arc\n", x , y , r);
  859. reconcat();
  860. // fprintf(output, "ELP\n");
  861. fprintf(output, "GR\n");
  862. }else
  863. fprintf(output, "%g %g %g 0 360 arc\n", x , y , r);
  864. };
  865. void Fl_PSfile_Device::arc(double x, double y, double r, double start, double a){
  866. if(shape_==NONE) return;
  867. gap_=0;
  868. if(start>a)
  869. fprintf(output, "%g %g %g %g %g arc\n", x , y , r , -start, -a);
  870. else
  871. fprintf(output, "%g %g %g %g %g arcn\n", x , y , r , -start, -a);
  872. };
  873. void Fl_PSfile_Device::arc(int x, int y, int w, int h, double a1, double a2) {
  874. fprintf(output, "GS\n");
  875. //fprintf(output, "BP\n");
  876. begin_line();
  877. fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5);
  878. fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 );
  879. arc(0,0,1,a2,a1);
  880. // fprintf(output, "0 0 1 %g %g arc\n" , -a1 , -a2);
  881. fprintf(output, "%g %g SC\n", 2.0/(w-1) , 2.0/(h-1) );
  882. fprintf(output, "%g %g TR\n", -x - w/2.0 +0.5 , -y - h/2.0 +0.5);
  883. end_line();
  884. // fprintf(output, "%g setlinewidth\n", 2/sqrt(w*h));
  885. // fprintf(output, "ELP\n");
  886. // fprintf(output, 2.0/w , 2.0/w , " SC\n";
  887. // fprintf(output, (-x - w/2.0) , (-y - h/2) , " TR\n";
  888. fprintf(output, "GR\n");
  889. }
  890. void Fl_PSfile_Device::pie(int x, int y, int w, int h, double a1, double a2) {
  891. fprintf(output, "GS\n");
  892. fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5);
  893. fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 );
  894. begin_polygon();
  895. vertex(0,0);
  896. arc(0.0,0.0, 1, a2, a1);
  897. end_polygon();
  898. fprintf(output, "GR\n");
  899. }
  900. void Fl_PSfile_Device::end_points(){
  901. gap_=1;
  902. reconcat();
  903. fprintf(output, "ELP\n"); //??
  904. fprintf(output, "GR\n");
  905. shape_=NONE;
  906. }
  907. void Fl_PSfile_Device::end_line(){
  908. gap_=1;
  909. reconcat();
  910. fprintf(output, "ELP\n");
  911. fprintf(output, "GR\n");
  912. shape_=NONE;
  913. }
  914. void Fl_PSfile_Device::end_loop(){
  915. gap_=1;
  916. reconcat();
  917. fprintf(output, "ECP\n");
  918. fprintf(output, "GR\n");
  919. shape_=NONE;
  920. }
  921. void Fl_PSfile_Device::end_polygon(){
  922. gap_=1;
  923. reconcat();
  924. fprintf(output, "EFP\n");
  925. fprintf(output, "GR\n");
  926. shape_=NONE;
  927. }
  928. void Fl_PSfile_Device::transformed_vertex(double x, double y){
  929. reconcat();
  930. if(gap_){
  931. fprintf(output, "%g %g MT\n", x , y);
  932. gap_=0;
  933. }else
  934. fprintf(output, "%g %g LT\n", x , y);
  935. concat();
  936. };
  937. ///////////////////////////// Clipping /////////////////////////////////////////////
  938. void Fl_PSfile_Device::push_clip(int x, int y, int w, int h) {
  939. Clip * c=new Clip();
  940. clip_box(x,y,w,h,c->x,c->y,c->w,c->h);
  941. c->prev=clip_;
  942. clip_=c;
  943. fprintf(output, "CR\nCS\n");
  944. if(lang_level_<3)
  945. recover();
  946. fprintf(output, "%g %g %i %i CL\n", clip_->x-0.5 , clip_->y-0.5 , clip_->w , clip_->h);
  947. }
  948. void Fl_PSfile_Device::push_no_clip() {
  949. Clip * c = new Clip();
  950. c->prev=clip_;
  951. clip_=c;
  952. clip_->x = clip_->y = clip_->w = clip_->h = -1;
  953. fprintf(output, "CR\nCS\n");
  954. if(lang_level_<3)
  955. recover();
  956. }
  957. void Fl_PSfile_Device::pop_clip() {
  958. if(!clip_)return;
  959. Clip * c=clip_;
  960. clip_=clip_->prev;
  961. delete c;
  962. fprintf(output, "CR\nCS\n");
  963. if(clip_ && clip_->w >0)
  964. fprintf(output, "%g %g %i %i CL\n", clip_->x - 0.5, clip_->y - 0.5, clip_->w , clip_->h);
  965. // uh, -0.5 is to match screen clipping, for floats there should be something beter
  966. if(lang_level_<3)
  967. recover();
  968. }
  969. int Fl_PSfile_Device::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H){
  970. if(!clip_){
  971. X=x;Y=y;W=w;H=h;
  972. return 1;
  973. }
  974. if(clip_->w < 0){
  975. X=x;Y=y;W=w;H=h;
  976. return 1;
  977. }
  978. int ret=0;
  979. if (x > (X=clip_->x)) {X=x; ret=1;}
  980. if (y > (Y=clip_->y)) {Y=y; ret=1;}
  981. if ((x+w) < (clip_->x+clip_->w)) {
  982. W=x+w-X;
  983. ret=1;
  984. }else
  985. W = clip_->x + clip_->w - X;
  986. if(W<0){
  987. W=0;
  988. return 1;
  989. }
  990. if ((y+h) < (clip_->y+clip_->h)) {
  991. H=y+h-Y;
  992. ret=1;
  993. }else
  994. H = clip_->y + clip_->h - Y;
  995. if(H<0){
  996. W=0;
  997. H=0;
  998. return 1;
  999. }
  1000. return ret;
  1001. };
  1002. int Fl_PSfile_Device::not_clipped(int x, int y, int w, int h){
  1003. if(!clip_) return 1;
  1004. if(clip_->w < 0) return 1;
  1005. int X, Y, W, H;
  1006. clip_box(x, y, w, h, X, Y, W, H);
  1007. if(W) return 1;
  1008. return 0;
  1009. };
  1010. void Fl_PSfile_Device::margins(int *left, int *top, int *right, int *bottom) // to implement
  1011. {
  1012. if(left) *left = (int)(left_margin / scale_x + .5);
  1013. if(right) *right = (int)(left_margin / scale_x + .5);
  1014. if(top) *top = (int)(top_margin / scale_y + .5);
  1015. if(bottom) *bottom = (int)(top_margin / scale_y + .5);
  1016. }
  1017. int Fl_PSfile_Device::printable_rect(int *w, int *h)
  1018. //returns 0 iff OK
  1019. {
  1020. if(w) *w = (int)((pw_ - 2 * left_margin) / scale_x + .5);
  1021. if(h) *h = (int)((ph_ - 2 * top_margin) / scale_y + .5);
  1022. return 0;
  1023. }
  1024. void Fl_PSfile_Device::origin(int x, int y)
  1025. {
  1026. x_offset = x;
  1027. y_offset = y;
  1028. fprintf(output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n",
  1029. left_margin, top_margin, scale_x, scale_y, x, y, angle);
  1030. }
  1031. void Fl_PSfile_Device::scale (float s_x, float s_y)
  1032. {
  1033. scale_x = s_x;
  1034. scale_y = s_y;
  1035. fprintf(output, "GR GR GS %d %d TR %f %f SC %f rotate GS\n",
  1036. left_margin, top_margin, scale_x, scale_y, angle);
  1037. }
  1038. void Fl_PSfile_Device::rotate (float rot_angle)
  1039. {
  1040. angle = - rot_angle;
  1041. fprintf(output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n",
  1042. left_margin, top_margin, scale_x, scale_y, x_offset, y_offset, angle);
  1043. }
  1044. void Fl_PSfile_Device::translate(int x, int y)
  1045. {
  1046. fprintf(output, "GS %d %d translate GS\n", x, y);
  1047. }
  1048. void Fl_PSfile_Device::untranslate(void)
  1049. {
  1050. fprintf(output, "GR GR\n");
  1051. }
  1052. int Fl_PSfile_Device::start_page (void)
  1053. {
  1054. page(page_format_);
  1055. x_offset = 0;
  1056. y_offset = 0;
  1057. scale_x = scale_y = 1.;
  1058. angle = 0;
  1059. fprintf(output, "GR GR GS %d %d translate GS\n", left_margin, top_margin);
  1060. return 0;
  1061. }
  1062. int Fl_PSfile_Device::end_page (void)
  1063. {
  1064. return 0;
  1065. }
  1066. void Fl_PSfile_Device::end_job (void)
  1067. // finishes PostScript & closes file
  1068. {
  1069. if (nPages) { // for eps nPages is 0 so it is fine ....
  1070. fprintf(output, "CR\nGR\nGR\nGR\nSP\n restore\n");
  1071. if (!pages_){
  1072. fprintf(output, "%%%%Trailer\n");
  1073. fprintf(output, "%%%%Pages: %i\n" , nPages);
  1074. };
  1075. } else
  1076. fprintf(output, "GR\n restore\n");
  1077. fputs("%%EOF",output);
  1078. reset();
  1079. fflush(output);
  1080. if(ferror(output)) {
  1081. fl_alert ("Error during PostScript data output.");
  1082. }
  1083. #if ! (defined(__APPLE__) || defined(WIN32) )
  1084. if (print_pipe)
  1085. pclose(output);
  1086. else
  1087. fclose(output);
  1088. #else
  1089. fclose(output);
  1090. #endif
  1091. while (clip_){
  1092. Clip * c= clip_;
  1093. clip_= clip_->prev;
  1094. delete c;
  1095. }
  1096. if (close_cmd_) (*close_cmd_)(output);
  1097. Fl_Device::display_device()->set_current();
  1098. }
  1099. #if ! (defined(__APPLE__) || defined(WIN32) )
  1100. int Fl_Printer::start_job(int pages, int *firstpage, int *lastpage) {
  1101. enum Page_Format format;
  1102. enum Page_Layout layout;
  1103. // first test version for print dialog
  1104. if (!print_panel) make_print_panel();
  1105. print_load();
  1106. print_selection->deactivate();
  1107. print_all->setonly();
  1108. print_all->do_callback();
  1109. print_from->value("1");
  1110. { char tmp[10]; snprintf(tmp, sizeof(tmp), "%d", pages); print_to->value(tmp); }
  1111. print_panel->show(); // this is modal
  1112. while (print_panel->shown()) Fl::wait();
  1113. if (!print_start) // user clicked cancel
  1114. return 1;
  1115. // get options
  1116. format = print_page_size->value() ? A4 : LETTER;
  1117. { // page range choice
  1118. int from = 1, to = pages;
  1119. if (print_pages->value()) {
  1120. sscanf(print_from->value(), "%d", &from);
  1121. sscanf(print_to->value(), "%d", &to);
  1122. }
  1123. if (from < 1) from = 1;
  1124. if (to > pages) to = pages;
  1125. if (to < from) to = from;
  1126. if (firstpage) *firstpage = from;
  1127. if (lastpage) *lastpage = to;
  1128. pages = to - from + 1;
  1129. }
  1130. if (print_output_mode[0]->value()) layout = PORTRAIT;
  1131. else if (print_output_mode[1]->value()) layout = LANDSCAPE;
  1132. else if (print_output_mode[2]->value()) layout = PORTRAIT;
  1133. else layout = LANDSCAPE;
  1134. print_pipe = print_choice->value(); // 0 = print to file, >0 = printer (pipe)
  1135. const char *media = print_page_size->text(print_page_size->value());
  1136. const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data();
  1137. if (!print_pipe) printer = "<File>";
  1138. if (!print_pipe) // fall back to file printing
  1139. return Fl_PSfile_Device::start_job (pages, format, layout);
  1140. // Print: pipe the output into the lp command...
  1141. char command[1024];
  1142. snprintf(command, sizeof(command), "lp -s -d %s -n %d -t '%s' -o media=%s",
  1143. printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5),
  1144. "FLTK", media);
  1145. output = popen(command, "w");
  1146. if (!output) {
  1147. fl_alert("could not run command: %s\n",command);
  1148. return 1;
  1149. }
  1150. return Fl_PSfile_Device::start_postscript(pages, format, layout); // start printing
  1151. }
  1152. #endif // ! (defined(__APPLE__) || defined(WIN32) )
  1153. #endif // FL_DOXYGEN
  1154. //
  1155. // End of "$Id: Fl_PS_Printer.cxx 7522 2010-04-18 06:57:37Z manolo $".
  1156. //