|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: Fl_PostScript.cxx 8190 2011-01-05 10:21:45Z manolo $" 00003 // 00004 // PostScript device support for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems to: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00028 #include <FL/Fl.H> 00029 #include <FL/fl_ask.H> 00030 #include <FL/fl_draw.H> 00031 #include <stdio.h> 00032 #include <FL/Fl_PostScript.H> 00033 #include <FL/Fl_Native_File_Chooser.H> 00034 00035 const char *Fl_PostScript_Graphics_Driver::class_id = "Fl_PostScript_Graphics_Driver"; 00036 const char *Fl_PostScript_File_Device::class_id = "Fl_PostScript_File_Device"; 00038 const char *Fl_PostScript_File_Device::file_chooser_title = "Select a .ps file"; 00039 00043 Fl_PostScript_Graphics_Driver::Fl_PostScript_Graphics_Driver(void) 00044 { 00045 close_cmd_ = 0; 00046 //lang_level_ = 3; 00047 lang_level_ = 2; 00048 mask = 0; 00049 ps_filename_ = NULL; 00050 class_name(class_id); 00051 scale_x = scale_y = 1.; 00052 bg_r = bg_g = bg_b = 255; 00053 } 00054 00056 Fl_PostScript_Graphics_Driver::~Fl_PostScript_Graphics_Driver() { 00057 if(ps_filename_) free(ps_filename_); 00058 } 00059 00063 Fl_PostScript_File_Device::Fl_PostScript_File_Device(void) 00064 { 00065 class_name(class_id); 00066 #ifdef __APPLE__ 00067 gc = fl_gc; // the display context is used by fl_text_extents() 00068 #endif 00069 Fl_Surface_Device::driver( new Fl_PostScript_Graphics_Driver() ); 00070 } 00071 00075 Fl_PostScript_Graphics_Driver *Fl_PostScript_File_Device::driver() 00076 { 00077 return (Fl_PostScript_Graphics_Driver*)Fl_Surface_Device::driver(); 00078 } 00079 00080 00090 int Fl_PostScript_File_Device::start_job (int pagecount, enum Fl_Paged_Device::Page_Format format, 00091 enum Fl_Paged_Device::Page_Layout layout) 00092 { 00093 Fl_Native_File_Chooser fnfc; 00094 fnfc.title(Fl_PostScript_File_Device::file_chooser_title); 00095 fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); 00096 fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM); 00097 fnfc.filter("PostScript\t*.ps\n"); 00098 // Show native chooser 00099 if ( fnfc.show() ) return 1; 00100 Fl_PostScript_Graphics_Driver *ps = driver(); 00101 ps->output = fopen(fnfc.filename(), "w"); 00102 if(ps->output == NULL) return 2; 00103 ps->ps_filename_ = strdup(fnfc.filename()); 00104 ps->start_postscript(pagecount, format, layout); 00105 this->set_current(); 00106 return 0; 00107 } 00108 00109 static int dont_close(FILE *f) 00110 { 00111 return 0; 00112 } 00113 00124 int Fl_PostScript_File_Device::start_job (FILE *ps_output, int pagecount, 00125 enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) 00126 { 00127 Fl_PostScript_Graphics_Driver *ps = driver(); 00128 ps->output = ps_output; 00129 ps->ps_filename_ = NULL; 00130 ps->start_postscript(pagecount, format, layout); 00131 ps->close_command(dont_close); // so that end_job() doesn't close the file 00132 this->set_current(); 00133 return 0; 00134 } 00135 00139 Fl_PostScript_File_Device::~Fl_PostScript_File_Device() { 00140 Fl_PostScript_Graphics_Driver *ps = driver(); 00141 if (ps) delete ps; 00142 } 00143 00144 #ifndef FL_DOXYGEN 00145 00146 #if ! (defined(__APPLE__) || defined(WIN32) ) 00147 #include "print_panel.cxx" 00148 #endif 00149 00150 // Prolog string 00151 00152 static const char * prolog = 00153 "%%BeginProlog\n" 00154 "/L { /y2 exch def\n" 00155 "/x2 exch def\n" 00156 "/y1 exch def\n" 00157 "/x1 exch def\n" 00158 "newpath x1 y1 moveto x2 y2 lineto\n" 00159 "stroke}\n" 00160 "bind def\n" 00161 00162 00163 "/R { /dy exch def\n" 00164 "/dx exch def\n" 00165 "/y exch def\n" 00166 "/x exch def\n" 00167 "newpath\n" 00168 "x y moveto\n" 00169 "dx 0 rlineto\n" 00170 "0 dy rlineto\n" 00171 "dx neg 0 rlineto\n" 00172 "closepath stroke\n" 00173 "} bind def\n" 00174 00175 "/CL {\n" 00176 "/dy exch def\n" 00177 "/dx exch def\n" 00178 "/y exch def\n" 00179 "/x exch def\n" 00180 "newpath\n" 00181 "x y moveto\n" 00182 "dx 0 rlineto\n" 00183 "0 dy rlineto\n" 00184 "dx neg 0 rlineto\n" 00185 "closepath\n" 00186 "clip\n" 00187 "} bind def\n" 00188 00189 "/FR { /dy exch def\n" 00190 "/dx exch def\n" 00191 "/y exch def\n" 00192 "/x exch def\n" 00193 "currentlinewidth 0 setlinewidth newpath\n" 00194 "x y moveto\n" 00195 "dx 0 rlineto\n" 00196 "0 dy rlineto\n" 00197 "dx neg 0 rlineto\n" 00198 "closepath fill setlinewidth\n" 00199 "} bind def\n" 00200 00201 "/GS { gsave } bind def\n" 00202 "/GR { grestore } bind def\n" 00203 00204 "/SP { showpage } bind def\n" 00205 "/LW { setlinewidth } bind def\n" 00206 "/CF /Courier def\n" 00207 "/SF { /CF exch def } bind def\n" 00208 "/fsize 12 def\n" 00209 "/FS { /fsize exch def fsize CF findfont exch scalefont setfont }def \n" 00210 00211 00212 "/GL { setgray } bind def\n" 00213 "/SRGB { setrgbcolor } bind def\n" 00214 00215 // color images 00216 00217 "/CI { GS /py exch def /px exch def /sy exch def /sx exch def\n" 00218 "translate \n" 00219 "sx sy scale px py 8 \n" 00220 "[ px 0 0 py neg 0 py ]\n" 00221 "currentfile /ASCIIHexDecode filter\n false 3" 00222 " colorimage GR\n" 00223 "} bind def\n" 00224 00225 // gray images 00226 00227 "/GI { GS /py exch def /px exch def /sy exch def /sx exch def \n" 00228 "translate \n" 00229 "sx sy scale px py 8 \n" 00230 00231 00232 "[ px 0 0 py neg 0 py ]\n" 00233 "currentfile /ASCIIHexDecode filter\n" 00234 "image GR\n" 00235 "} bind def\n" 00236 00237 // single-color bitmask 00238 00239 "/MI { GS /py exch def /px exch def /sy exch def /sx exch def \n" 00240 "translate \n" 00241 "sx sy scale px py true \n" 00242 "[ px 0 0 py neg 0 py ]\n" 00243 "currentfile /ASCIIHexDecode filter\n" 00244 "imagemask GR\n" 00245 "} bind def\n" 00246 00247 00248 // path 00249 00250 "/BFP { newpath moveto } def\n" 00251 "/BP { newpath } bind def \n" 00252 "/PL { lineto } bind def \n" 00253 "/PM { moveto } bind def \n" 00254 "/MT { moveto } bind def \n" 00255 "/LT { lineto } bind def \n" 00256 "/EFP { closepath fill } bind def\n" //was:stroke 00257 "/ELP { stroke } bind def\n" 00258 "/ECP { closepath stroke } bind def\n" // Closed (loop) 00259 "/LW { setlinewidth } bind def\n" 00260 00261 // ////////////////////////// misc //////////////// 00262 "/TR { translate } bind def\n" 00263 "/CT { concat } bind def\n" 00264 "/RCT { matrix invertmatrix concat} bind def\n" 00265 "/SC { scale } bind def\n" 00266 //"/GPD { currentpagedevice /PageSize get} def\n" 00267 00268 // show at position with desired width 00269 // usage: 00270 // width (string) x y show_pos_width 00271 "/show_pos_width {GS moveto dup dup stringwidth pop exch length exch 3 index exch sub exch " 00272 "div 0 2 index 1 -1 scale ashow pop pop GR} bind def\n" // spacing altered to match desired width 00273 //"/show_pos_width {GS moveto dup stringwidth pop 3 2 roll exch div -1 matrix scale concat " 00274 //"show GR } bind def\n" // horizontally scaled text to match desired width 00275 00276 ; 00277 00278 00279 static const char * prolog_2 = // prolog relevant only if lang_level >1 00280 00281 // color image dictionaries 00282 "/CII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n" 00283 "translate \n" 00284 "sx sy scale\n" 00285 "/DeviceRGB setcolorspace\n" 00286 "/IDD 8 dict def\n" 00287 "IDD begin\n" 00288 "/ImageType 1 def\n" 00289 "/Width px def\n" 00290 "/Height py def\n" 00291 "/BitsPerComponent 8 def\n" 00292 "/Interpolate inter def\n" 00293 "/DataSource currentfile /ASCIIHexDecode filter def\n" 00294 "/MultipleDataSources false def\n" 00295 "/ImageMatrix [ px 0 0 py neg 0 py ] def\n" 00296 "/Decode [ 0 1 0 1 0 1 ] def\n" 00297 "end\n" 00298 "IDD image GR} bind def\n" 00299 00300 // gray image dict 00301 "/GII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n" 00302 "translate \n" 00303 "sx sy scale\n" 00304 "/DeviceGray setcolorspace\n" 00305 "/IDD 8 dict def\n" 00306 "IDD begin\n" 00307 "/ImageType 1 def\n" 00308 "/Width px def\n" 00309 "/Height py def\n" 00310 "/BitsPerComponent 8 def\n" 00311 00312 "/Interpolate inter def\n" 00313 "/DataSource currentfile /ASCIIHexDecode filter def\n" 00314 "/MultipleDataSources false def\n" 00315 "/ImageMatrix [ px 0 0 py neg 0 py ] def\n" 00316 "/Decode [ 0 1 ] def\n" 00317 "end\n" 00318 "IDD image GR} bind def\n" 00319 00320 // Create a custom PostScript font derived from PostScript standard text fonts 00321 // The encoding of this custom font is as follows: 00322 // 0000-00FF coincides with Unicode, that is to ASCII + Latin-1 00323 // 0100-017F coincides with Unicode, that is to Latin Extended-A 00324 // 0180-01A6 encodes miscellaneous characters present in PostScript standard text fonts 00325 00326 // use ISOLatin1Encoding for all text fonts 00327 "/ToISO { dup findfont dup length dict copy begin /Encoding ISOLatin1Encoding def currentdict end definefont pop } def\n" 00328 "/Helvetica ToISO /Helvetica-Bold ToISO /Helvetica-Oblique ToISO /Helvetica-BoldOblique ToISO \n" 00329 "/Courier ToISO /Courier-Bold ToISO /Courier-Oblique ToISO /Courier-BoldOblique ToISO \n" 00330 "/Times-Roman ToISO /Times-Bold ToISO /Times-Italic ToISO /Times-BoldItalic ToISO \n" 00331 00332 // define LatinExtA, the encoding of Latin-extended-A + some additional characters 00333 // see http://www.adobe.com/devnet/opentype/archives/glyphlist.txt for their names 00334 "/LatinExtA \n" 00335 "[ " 00336 " /Amacron /amacron /Abreve /abreve /Aogonek /aogonek\n" // begin of Latin Extended-A code page 00337 " /Cacute /cacute /Ccircumflex /ccircumflex /Cdotaccent /cdotaccent /Ccaron /ccaron \n" 00338 " /Dcaron /dcaron /Dcroat /dcroat\n" 00339 " /Emacron /emacron /Ebreve /ebreve /Edotaccent /edotaccent /Eogonek /eogonek /Ecaron /ecaron\n" 00340 " /Gcircumflex /gcircumflex /Gbreve /gbreve /Gdotaccent /gdotaccent /Gcommaaccent /gcommaaccent \n" 00341 " /Hcircumflex /hcircumflex /Hbar /hbar \n" 00342 " /Itilde /itilde /Imacron /imacron /Ibreve /ibreve /Iogonek /iogonek /Idotaccent /dotlessi \n" 00343 " /IJ /ij /Jcircumflex /jcircumflex\n" 00344 " /Kcommaaccent /kcommaaccent /kgreenlandic \n" 00345 " /Lacute /lacute /Lcommaaccent /lcommaaccent /Lcaron /lcaron /Ldotaccent /ldotaccent /Lslash /lslash \n" 00346 " /Nacute /nacute /Ncommaaccent /ncommaaccent /Ncaron /ncaron /napostrophe /Eng /eng \n" 00347 " /Omacron /omacron /Obreve /obreve /Ohungarumlaut /ohungarumlaut /OE /oe \n" 00348 " /Racute /racute /Rcommaaccent /rcommaaccent /Rcaron /rcaron \n" 00349 " /Sacute /sacute /Scircumflex /scircumflex /Scedilla /scedilla /Scaron /scaron \n" 00350 " /Tcommaaccent /tcommaaccent /Tcaron /tcaron /Tbar /tbar \n" 00351 " /Utilde /utilde /Umacron /umacron /Ubreve /ubreve /Uring /uring /Uhungarumlaut /uhungarumlaut /Uogonek /uogonek \n" 00352 " /Wcircumflex /wcircumflex /Ycircumflex /ycircumflex /Ydieresis \n" 00353 " /Zacute /zacute /Zdotaccent /zdotaccent /Zcaron /zcaron \n" 00354 " /longs \n" // end of Latin Extended-A code page 00355 " /florin /circumflex /caron /breve /dotaccent /ring \n" // remaining characters from PostScript standard text fonts 00356 " /ogonek /tilde /hungarumlaut /endash /emdash \n" 00357 " /quoteleft /quoteright /quotesinglbase /quotedblleft /quotedblright \n" 00358 " /quotedblbase /dagger /daggerdbl /bullet /ellipsis \n" 00359 " /perthousand /guilsinglleft /guilsinglright /fraction /Euro \n" 00360 " /trademark /partialdiff /Delta /summation /radical \n" 00361 " /infinity /notequal /lessequal /greaterequal /lozenge \n" 00362 " /fi /fl /apple \n" 00363 " ] def \n" 00364 // deal with alternative PostScript names of some characters 00365 " /mycharstrings /Helvetica findfont /CharStrings get def\n" 00366 " /PSname2 { dup mycharstrings exch known {LatinExtA 3 -1 roll 3 -1 roll put}{pop pop} ifelse } def \n" 00367 " 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" 00368 00369 // proc that gives LatinExtA encoding to a font 00370 "/ToLatinExtA { findfont dup length dict copy begin /Encoding LatinExtA def currentdict end definefont pop } def\n" 00371 // create Ext-versions of standard fonts that use LatinExtA encoding \n" 00372 "/HelveticaExt /Helvetica ToLatinExtA \n" 00373 "/Helvetica-BoldExt /Helvetica-Bold ToLatinExtA /Helvetica-ObliqueExt /Helvetica-Oblique ToLatinExtA \n" 00374 "/Helvetica-BoldObliqueExt /Helvetica-BoldOblique ToLatinExtA \n" 00375 "/CourierExt /Courier ToLatinExtA /Courier-BoldExt /Courier-Bold ToLatinExtA \n" 00376 "/Courier-ObliqueExt /Courier-Oblique ToLatinExtA /Courier-BoldObliqueExt /Courier-BoldOblique ToLatinExtA \n" 00377 "/Times-RomanExt /Times-Roman ToLatinExtA /Times-BoldExt /Times-Bold ToLatinExtA \n" 00378 "/Times-ItalicExt /Times-Italic ToLatinExtA /Times-BoldItalicExt /Times-BoldItalic ToLatinExtA \n" 00379 00380 // proc to create a Type 0 font with 2-byte encoding 00381 // that merges a text font with ISO encoding + same font with LatinExtA encoding 00382 "/To2byte { 6 dict begin /FontType 0 def \n" 00383 "/FDepVector 3 1 roll findfont exch findfont 2 array astore def \n" 00384 "/FontMatrix [1 0 0 1 0 0] def /FMapType 6 def /Encoding [ 0 1 0 ] def\n" 00385 // 100: Hexa count of ISO array; A7: hexa count of LatinExtA array 00386 "/SubsVector < 01 0100 00A7 > def\n" 00387 "currentdict end definefont pop } def\n" 00388 // create Type 0 versions of standard fonts 00389 "/Helvetica2B /HelveticaExt /Helvetica To2byte \n" 00390 "/Helvetica-Bold2B /Helvetica-BoldExt /Helvetica-Bold To2byte \n" 00391 "/Helvetica-Oblique2B /Helvetica-ObliqueExt /Helvetica-Oblique To2byte \n" 00392 "/Helvetica-BoldOblique2B /Helvetica-BoldObliqueExt /Helvetica-BoldOblique To2byte \n" 00393 "/Courier2B /CourierExt /Courier To2byte \n" 00394 "/Courier-Bold2B /Courier-BoldExt /Courier-Bold To2byte \n" 00395 "/Courier-Oblique2B /Courier-ObliqueExt /Courier-Oblique To2byte \n" 00396 "/Courier-BoldOblique2B /Courier-BoldObliqueExt /Courier-BoldOblique To2byte \n" 00397 "/Times-Roman2B /Times-RomanExt /Times-Roman To2byte \n" 00398 "/Times-Bold2B /Times-BoldExt /Times-Bold To2byte \n" 00399 "/Times-Italic2B /Times-ItalicExt /Times-Italic To2byte \n" 00400 "/Times-BoldItalic2B /Times-BoldItalicExt /Times-BoldItalic To2byte \n" 00401 ; 00402 00403 static const char * prolog_2_pixmap = // prolog relevant only if lang_level == 2 for pixmaps/masked color images 00404 "/pixmap_mat {[ pixmap_sx 0 0 pixmap_sy neg 0 pixmap_sy ]} bind def\n" 00405 00406 "/pixmap_dict {" 00407 "<< /PatternType 1 " 00408 "/PaintType 1 " 00409 "/TilingType 2 " 00410 "/BBox [0 0 pixmap_sx pixmap_sy] " 00411 "/XStep pixmap_sx " 00412 "/YStep pixmap_sy\n" 00413 "/PaintProc " 00414 "{ begin " 00415 "pixmap_w pixmap_h scale " 00416 "pixmap_sx pixmap_sy 8 " 00417 "pixmap_mat " 00418 "currentfile /ASCIIHexDecode filter " 00419 "false 3 " 00420 "colorimage " 00421 "end " 00422 "} bind " 00423 ">>\n" 00424 "} bind def\n" 00425 00426 "/pixmap_plot {" 00427 "GS " 00428 "/pixmap_sy exch def /pixmap_sx exch def\n" 00429 "/pixmap_h exch def /pixmap_w exch def\n" 00430 "translate\n" 00431 "pixmap_dict matrix makepattern setpattern\n" 00432 "pixmap_w pixmap_h scale\n" 00433 "pixmap_sx pixmap_sy\n" 00434 "true\n" 00435 "pixmap_mat\n" 00436 "currentfile /ASCIIHexDecode filter\n" 00437 "imagemask\n" 00438 "GR\n" 00439 "} bind def\n" 00440 ; 00441 00442 static const char * prolog_3 = // prolog relevant only if lang_level >2 00443 00444 // masked color images 00445 "/CIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n" 00446 "translate \n" 00447 "sx sy scale\n" 00448 "/DeviceRGB setcolorspace\n" 00449 00450 "/IDD 8 dict def\n" 00451 00452 "IDD begin\n" 00453 "/ImageType 1 def\n" 00454 "/Width px def\n" 00455 "/Height py def\n" 00456 "/BitsPerComponent 8 def\n" 00457 "/Interpolate inter def\n" 00458 "/DataSource currentfile /ASCIIHexDecode filter def\n" 00459 "/MultipleDataSources false def\n" 00460 "/ImageMatrix [ px 0 0 py neg 0 py ] def\n" 00461 00462 "/Decode [ 0 1 0 1 0 1 ] def\n" 00463 "end\n" 00464 00465 "/IMD 8 dict def\n" 00466 "IMD begin\n" 00467 "/ImageType 1 def\n" 00468 "/Width mx def\n" 00469 "/Height my def\n" 00470 "/BitsPerComponent 1 def\n" 00471 // "/Interpolate inter def\n" 00472 "/ImageMatrix [ mx 0 0 my neg 0 my ] def\n" 00473 "/Decode [ 1 0 ] def\n" 00474 "end\n" 00475 00476 "<<\n" 00477 "/ImageType 3\n" 00478 "/InterleaveType 2\n" 00479 "/MaskDict IMD\n" 00480 "/DataDict IDD\n" 00481 ">> image GR\n" 00482 "} bind def\n" 00483 00484 00485 // masked gray images 00486 "/GIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n" 00487 "translate \n" 00488 "sx sy scale\n" 00489 "/DeviceGray setcolorspace\n" 00490 00491 "/IDD 8 dict def\n" 00492 00493 "IDD begin\n" 00494 "/ImageType 1 def\n" 00495 "/Width px def\n" 00496 "/Height py def\n" 00497 "/BitsPerComponent 8 def\n" 00498 "/Interpolate inter def\n" 00499 "/DataSource currentfile /ASCIIHexDecode filter def\n" 00500 "/MultipleDataSources false def\n" 00501 "/ImageMatrix [ px 0 0 py neg 0 py ] def\n" 00502 00503 "/Decode [ 0 1 ] def\n" 00504 "end\n" 00505 00506 "/IMD 8 dict def\n" 00507 00508 "IMD begin\n" 00509 "/ImageType 1 def\n" 00510 "/Width mx def\n" 00511 "/Height my def\n" 00512 "/BitsPerComponent 1 def\n" 00513 "/ImageMatrix [ mx 0 0 my neg 0 my ] def\n" 00514 "/Decode [ 1 0 ] def\n" 00515 "end\n" 00516 00517 "<<\n" 00518 "/ImageType 3\n" 00519 "/InterleaveType 2\n" 00520 "/MaskDict IMD\n" 00521 "/DataDict IDD\n" 00522 ">> image GR\n" 00523 "} bind def\n" 00524 00525 00526 "\n" 00527 ; 00528 00529 // end prolog 00530 00531 int Fl_PostScript_Graphics_Driver::start_postscript (int pagecount, 00532 enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) 00533 //returns 0 iff OK 00534 { 00535 int w, h, x; 00536 if (format == Fl_Paged_Device::A4) { 00537 left_margin = 18; 00538 top_margin = 18; 00539 } 00540 else { 00541 left_margin = 12; 00542 top_margin = 12; 00543 } 00544 page_format_ = (enum Fl_Paged_Device::Page_Format)(format | layout); 00545 00546 fputs("%!PS-Adobe-3.0\n", output); 00547 fputs("%%Creator: FLTK\n", output); 00548 if (lang_level_>1) 00549 fprintf(output, "%%%%LanguageLevel: %i\n" , lang_level_); 00550 if ((pages_ = pagecount)) 00551 fprintf(output, "%%%%Pages: %i\n", pagecount); 00552 else 00553 fputs("%%Pages: (atend)\n", output); 00554 fprintf(output, "%%%%BeginFeature: *PageSize %s\n", Fl_Paged_Device::page_formats[format].name ); 00555 w = Fl_Paged_Device::page_formats[format].width; 00556 h = Fl_Paged_Device::page_formats[format].height; 00557 if (lang_level_ == 3 && (layout & Fl_Paged_Device::LANDSCAPE) ) { x = w; w = h; h = x; } 00558 fprintf(output, "<</PageSize[%d %d]>>setpagedevice\n", w, h ); 00559 fputs("%%EndFeature\n", output); 00560 fputs("%%EndComments\n", output); 00561 fputs(prolog, output); 00562 if (lang_level_ > 1) { 00563 fputs(prolog_2, output); 00564 } 00565 if (lang_level_ == 2) { 00566 fputs(prolog_2_pixmap, output); 00567 } 00568 if (lang_level_ > 2) 00569 fputs(prolog_3, output); 00570 if (lang_level_ >= 3) { 00571 fputs("/CS { clipsave } bind def\n", output); 00572 fputs("/CR { cliprestore } bind def\n", output); 00573 } else { 00574 fputs("/CS { GS } bind def\n", output); 00575 fputs("/CR { GR } bind def\n", output); 00576 } 00577 page_policy_ = 1; 00578 00579 00580 fputs("%%EndProlog\n",output); 00581 if (lang_level_ >= 2) 00582 fprintf(output,"<< /Policies << /Pagesize 1 >> >> setpagedevice\n"); 00583 00584 reset(); 00585 nPages=0; 00586 return 0; 00587 } 00588 00589 void Fl_PostScript_Graphics_Driver::recover(){ 00590 color(cr_,cg_,cb_); 00591 line_style(linestyle_,linewidth_,linedash_); 00592 font(font_,size_); 00593 } 00594 00595 void Fl_PostScript_Graphics_Driver::reset(){ 00596 gap_=1; 00597 clip_=0; 00598 cr_=cg_=cb_=0; 00599 font_=FL_HELVETICA; 00600 size_=12; 00601 linewidth_=0; 00602 linestyle_=FL_SOLID; 00603 strcpy(linedash_,""); 00604 Clip *c=clip_; 00605 00606 while(c){ 00607 clip_=clip_->prev; 00608 delete c; 00609 c=clip_; 00610 } 00611 00612 } 00613 00614 void Fl_PostScript_Graphics_Driver::page_policy(int p){ 00615 page_policy_ = p; 00616 if(lang_level_>=2) 00617 fprintf(output,"<< /Policies << /Pagesize %i >> >> setpagedevice\n", p); 00618 } 00619 00620 // //////////////////// paging ////////////////////////////////////////// 00621 00622 00623 00624 void Fl_PostScript_Graphics_Driver::page(double pw, double ph, int media) { 00625 00626 if (nPages){ 00627 fprintf(output, "CR\nGR\nGR\nGR\nSP\nrestore\n"); 00628 } 00629 ++nPages; 00630 fprintf(output, "%%%%Page: %i %i\n" , nPages , nPages); 00631 if (pw>ph){ 00632 fprintf(output, "%%%%PageOrientation: Landscape\n"); 00633 }else{ 00634 fprintf(output, "%%%%PageOrientation: Portrait\n"); 00635 } 00636 00637 fprintf(output, "%%%%BeginPageSetup\n"); 00638 if((media & Fl_Paged_Device::MEDIA) &&(lang_level_>1)){ 00639 int r = media & Fl_Paged_Device::REVERSED; 00640 if(r) r = 2; 00641 fprintf(output, "<< /PageSize [%i %i] /Orientation %i>> setpagedevice\n", (int)(pw+.5), (int)(ph+.5), r); 00642 } 00643 fprintf(output, "%%%%EndPageSetup\n"); 00644 00645 pw_ = pw; 00646 ph_ = ph; 00647 reset(); 00648 00649 fprintf(output, "save\n"); 00650 fprintf(output, "GS\n"); 00651 fprintf(output, "%g %g TR\n", (double)0 /*lm_*/ , ph_ /* - tm_*/); 00652 fprintf(output, "1 -1 SC\n"); 00653 line_style(0); 00654 fprintf(output, "GS\n"); 00655 00656 if (!((media & Fl_Paged_Device::MEDIA) &&(lang_level_>1))){ 00657 if (pw > ph) { 00658 if(media & Fl_Paged_Device::REVERSED) { 00659 fprintf(output, "-90 rotate %i 0 translate\n", int(-pw)); 00660 } 00661 else { 00662 fprintf(output, "90 rotate -%i -%i translate\n", (lang_level_ == 2 ? int(pw - ph) : 0), int(ph)); 00663 } 00664 } 00665 else { 00666 if(media & Fl_Paged_Device::REVERSED) 00667 fprintf(output, "180 rotate %i %i translate\n", int(-pw), int(-ph)); 00668 } 00669 } 00670 fprintf(output, "GS\nCS\n"); 00671 } 00672 00673 void Fl_PostScript_Graphics_Driver::page(int format){ 00674 00675 00676 if(format & Fl_Paged_Device::LANDSCAPE){ 00677 ph_=Fl_Paged_Device::page_formats[format & 0xFF].width; 00678 pw_=Fl_Paged_Device::page_formats[format & 0xFF].height; 00679 }else{ 00680 pw_=Fl_Paged_Device::page_formats[format & 0xFF].width; 00681 ph_=Fl_Paged_Device::page_formats[format & 0xFF].height; 00682 } 00683 page(pw_,ph_,format & 0xFF00);//,orientation only; 00684 } 00685 00686 void Fl_PostScript_Graphics_Driver::rect(int x, int y, int w, int h) { 00687 // Commented code does not work, i can't find the bug ;-( 00688 // fprintf(output, "GS\n"); 00689 // fprintf(output, "%i, %i, %i, %i R\n", x , y , w, h); 00690 // fprintf(output, "GR\n"); 00691 fprintf(output, "GS\n"); 00692 fprintf(output,"BP\n"); 00693 fprintf(output, "%i %i MT\n", x , y); 00694 fprintf(output, "%i %i LT\n", x+w-1 , y); 00695 fprintf(output, "%i %i LT\n", x+w-1 , y+h-1); 00696 fprintf(output, "%i %i LT\n", x , y+h-1); 00697 fprintf(output, "ECP\n"); 00698 fprintf(output, "GR\n"); 00699 } 00700 00701 void Fl_PostScript_Graphics_Driver::rectf(int x, int y, int w, int h) { 00702 fprintf(output, "%g %g %i %i FR\n", x-0.5, y-0.5, w, h); 00703 } 00704 00705 void Fl_PostScript_Graphics_Driver::line(int x1, int y1, int x2, int y2) { 00706 fprintf(output, "GS\n"); 00707 fprintf(output, "%i %i %i %i L\n", x1 , y1, x2 ,y2); 00708 fprintf(output, "GR\n"); 00709 } 00710 00711 void Fl_PostScript_Graphics_Driver::line(int x0, int y0, int x1, int y1, int x2, int y2) { 00712 fprintf(output, "GS\n"); 00713 fprintf(output,"BP\n"); 00714 fprintf(output, "%i %i MT\n", x0 , y0); 00715 fprintf(output, "%i %i LT\n", x1 , y1); 00716 fprintf(output, "%i %i LT\n", x2 , y2); 00717 fprintf(output, "ELP\n"); 00718 fprintf(output, "GR\n"); 00719 } 00720 00721 void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3){ 00722 fprintf(output, "GS\n"); 00723 fprintf(output,"BP\n"); 00724 fprintf(output, "%i %i MT\n", x , y ); 00725 fprintf(output, "%i %i LT\n", x1 , y ); 00726 fprintf(output, "%i %i LT\n", x1 , y2); 00727 fprintf(output,"%i %i LT\n", x3 , y2); 00728 fprintf(output, "ELP\n"); 00729 fprintf(output, "GR\n"); 00730 } 00731 00732 00733 void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2){ 00734 00735 fprintf(output, "GS\n"); 00736 fprintf(output,"BP\n"); 00737 fprintf(output, "%i %i MT\n", x , y); 00738 fprintf(output,"%i %i LT\n", x1 , y); 00739 fprintf(output, "%i %i LT\n", x1 , y2 ); 00740 fprintf(output, "ELP\n"); 00741 fprintf(output, "GR\n"); 00742 } 00743 00744 void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1){ 00745 fprintf(output, "GS\n"); 00746 fprintf(output,"BP\n"); 00747 fprintf(output, "%i %i MT\n", x , y); 00748 fprintf(output, "%i %i LT\n", x1 , y ); 00749 fprintf(output, "ELP\n"); 00750 00751 fprintf(output, "GR\n"); 00752 } 00753 00754 void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3){ 00755 fprintf(output, "GS\n"); 00756 00757 fprintf(output,"BP\n"); 00758 fprintf(output,"%i %i MT\n", x , y); 00759 fprintf(output, "%i %i LT\n", x , y1 ); 00760 fprintf(output, "%i %i LT\n", x2 , y1 ); 00761 fprintf(output , "%i %i LT\n", x2 , y3); 00762 fprintf(output, "ELP\n"); 00763 fprintf(output, "GR\n"); 00764 } 00765 00766 void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2){ 00767 fprintf(output, "GS\n"); 00768 fprintf(output,"BP\n"); 00769 fprintf(output, "%i %i MT\n", x , y); 00770 fprintf(output, "%i %i LT\n", x , y1); 00771 fprintf(output, "%i %i LT\n", x2 , y1); 00772 fprintf(output, "ELP\n"); 00773 fprintf(output, "GR\n"); 00774 } 00775 00776 void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1){ 00777 fprintf(output, "GS\n"); 00778 fprintf(output,"BP\n"); 00779 fprintf(output, "%i %i MT\n", x , y); 00780 fprintf(output, "%i %i LT\n", x , y1); 00781 fprintf(output, "ELP\n"); 00782 fprintf(output, "GR\n"); 00783 } 00784 00785 void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { 00786 fprintf(output, "GS\n"); 00787 fprintf(output,"BP\n"); 00788 fprintf(output, "%i %i MT\n", x0 , y0); 00789 fprintf(output, "%i %i LT\n", x1 , y1); 00790 fprintf(output, "%i %i LT\n", x2 , y2); 00791 fprintf(output, "ECP\n"); 00792 fprintf(output, "GR\n"); 00793 } 00794 00795 void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { 00796 fprintf(output, "GS\n"); 00797 fprintf(output,"BP\n"); 00798 fprintf(output, "%i %i MT\n", x0 , y0); 00799 fprintf(output, "%i %i LT\n", x1 , y1); 00800 fprintf(output, "%i %i LT\n", x2 , y2); 00801 fprintf(output, "%i %i LT\n", x3 , y3); 00802 fprintf(output, "ECP\n"); 00803 fprintf(output, "GR\n"); 00804 } 00805 00806 void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { 00807 fprintf(output, "GS\n"); 00808 fprintf(output,"BP\n"); 00809 fprintf(output, "%i %i MT\n", x0 , y0); 00810 fprintf(output,"%i %i LT\n", x1 , y1); 00811 fprintf(output, "%i %i LT\n", x2 , y2); 00812 fprintf(output, "EFP\n"); 00813 fprintf(output, "GR\n"); 00814 } 00815 00816 void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { 00817 fprintf(output, "GS\n"); 00818 fprintf(output,"BP\n"); 00819 fprintf(output, "%i %i MT\n", x0 , y0 ); 00820 fprintf(output, "%i %i LT\n", x1 , y1 ); 00821 fprintf(output, "%i %i LT\n", x2 , y2 ); 00822 fprintf(output, "%i %i LT\n", x3 , y3 ); 00823 00824 fprintf(output, "EFP\n"); 00825 fprintf(output, "GR\n"); 00826 } 00827 00828 void Fl_PostScript_Graphics_Driver::point(int x, int y){ 00829 rectf(x,y,1,1); 00830 } 00831 00832 static int dashes_flat[5][7]={ 00833 {-1,0,0,0,0,0,0}, 00834 {3,1,-1,0,0,0,0}, 00835 {1,1,-1,0,0,0,0}, 00836 {3,1,1,1,-1,0,0}, 00837 {3,1,1,1,1,1,-1} 00838 }; 00839 00840 00841 //yeah, hack... 00842 static double dashes_cap[5][7]={ 00843 {-1,0,0,0,0,0,0}, 00844 {2,2,-1,0,0,0,0}, 00845 {0.01,1.99,-1,0,0,0,0}, 00846 {2,2,0.01,1.99,-1,0,0}, 00847 {2,2,0.01,1.99,0.01,1.99,-1} 00848 }; 00849 00850 00851 void Fl_PostScript_Graphics_Driver::line_style(int style, int width, char* dashes){ 00852 //line_styled_=1; 00853 00854 linewidth_=width; 00855 linestyle_=style; 00856 //dashes_= dashes; 00857 if(dashes){ 00858 if(dashes != linedash_) 00859 strcpy(linedash_,dashes); 00860 00861 }else 00862 linedash_[0]=0; 00863 char width0 = 0; 00864 if(!width){ 00865 width=1; //for screen drawing compatability 00866 width0=1; 00867 } 00868 00869 fprintf(output, "%i setlinewidth\n", width); 00870 00871 if(!style && (!dashes || !(*dashes)) && width0) //system lines 00872 style = FL_CAP_SQUARE; 00873 00874 int cap = (style &0xf00) >> 8; 00875 if(cap) cap--; 00876 fprintf(output,"%i setlinecap\n", cap); 00877 00878 int join = (style & 0xf000) >> 12; 00879 00880 if(join) join--; 00881 fprintf(output,"%i setlinejoin\n", join); 00882 00883 00884 fprintf(output, "["); 00885 if(dashes && *dashes){ 00886 while(*dashes){ 00887 fprintf(output, "%i ", *dashes); 00888 dashes++; 00889 } 00890 }else{ 00891 int * ds; 00892 if(style & 0x200){ // round and square caps, dash length need to be adjusted 00893 double *dt = dashes_cap[style & 0xff]; 00894 while (*dt >= 0){ 00895 fprintf(output, "%g ",width * (*dt)); 00896 dt++; 00897 } 00898 }else{ 00899 00900 ds = dashes_flat[style & 0xff]; 00901 while (*ds >= 0){ 00902 fprintf(output, "%i ",width * (*ds)); 00903 ds++; 00904 } 00905 } 00906 } 00907 fprintf(output, "] 0 setdash\n"); 00908 } 00909 00910 static const char *_fontNames[] = { 00911 "Helvetica2B", 00912 "Helvetica-Bold2B", 00913 "Helvetica-Oblique2B", 00914 "Helvetica-BoldOblique2B", 00915 "Courier2B", 00916 "Courier-Bold2B", 00917 "Courier-Oblique2B", 00918 "Courier-BoldOblique2B", 00919 "Times-Roman2B", 00920 "Times-Bold2B", 00921 "Times-Italic2B", 00922 "Times-BoldItalic2B", 00923 "Symbol", 00924 "Courier2B", 00925 "Courier-Bold2B", 00926 "ZapfDingbats" 00927 }; 00928 00929 void Fl_PostScript_Graphics_Driver::font(int f, int s) { 00930 if (f >= FL_FREE_FONT) 00931 f = FL_COURIER; 00932 fprintf(output, "/%s SF\n" , _fontNames[f]); 00933 fprintf(output,"%i FS\n", s); 00934 Fl_Display_Device::display_device()->driver()->font(f,s); // Use display fonts for font measurement 00935 font_ = f; size_ = s; 00936 } 00937 00938 void Fl_PostScript_Graphics_Driver::color(Fl_Color c) { 00939 Fl::get_color(c, cr_, cg_, cb_); 00940 color(cr_, cg_, cb_); 00941 } 00942 00943 void Fl_PostScript_Graphics_Driver::color(unsigned char r, unsigned char g, unsigned char b) { 00944 fl_color_ = fl_rgb_color(r, g, b); 00945 cr_ = r; cg_ = g; cb_ = b; 00946 if (r == g && g == b) { 00947 double gray = r/255.0; 00948 fprintf(output, "%g GL\n", gray); 00949 } else { 00950 double fr, fg, fb; 00951 fr = r/255.0; 00952 fg = g/255.0; 00953 fb = b/255.0; 00954 fprintf(output, "%g %g %g SRGB\n", fr , fg , fb); 00955 } 00956 } 00957 00958 void Fl_PostScript_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) 00959 { 00960 fprintf(output, "GS %d %d translate %d rotate\n", x, y, - angle); 00961 this->transformed_draw(str, n, 0, 0); 00962 fprintf(output, "GR\n"); 00963 } 00964 00965 00966 // computes the mask for the RGB image img of all pixels with color != bg 00967 static uchar *calc_mask(uchar *img, int w, int h, Fl_Color bg) 00968 { 00969 uchar red, green, blue, r, g, b; 00970 uchar bit, byte, *q; 00971 Fl::get_color(bg, red, green, blue); 00972 int W = (w+7)/8; // width of mask 00973 uchar* mask = new uchar[W * h]; 00974 q = mask; 00975 while (h-- > 0) { // for each row 00976 bit = 0x80; // byte with last bit set 00977 byte = 0; // next mask byte to compute 00978 for (int j = 0; j < w; j++) { // for each column 00979 r = *img++; // the pixel color components 00980 g = *img++; 00981 b = *img++; 00982 // if pixel doesn't have bg color, put it in mask 00983 if (r != red || g != green || b != blue) byte |= bit; 00984 bit = bit>>1; // shift bit one step to the right 00985 if (bit == 0) { // single set bit has fallen out 00986 *q++ = byte; // enter byte in mask 00987 byte = 0; // reset next mask byte to zero 00988 bit = 0x80; // and this byte 00989 } 00990 } 00991 if (bit != 0x80) *q++ = byte; // enter last columns' byte in mask 00992 } 00993 return mask; 00994 } 00995 00996 // write to PostScript a bitmap image of a UTF8 string 00997 static void transformed_draw_extra(const char* str, int n, double x, double y, int w, FILE *output) { 00998 const float scale = 3; // scale for bitmask computation 00999 Fl_Fontsize old_size = fl_size(); 01000 fl_font(fl_font(), (Fl_Fontsize)(scale * old_size) ); 01001 w = (int)(w *scale + 0.5); 01002 int h = fl_height(); 01003 // create an offscreen image of the string 01004 Fl_Color text_color = fl_color(); 01005 Fl_Color bg_color = fl_contrast(FL_WHITE, text_color); 01006 Fl_Offscreen off = fl_create_offscreen(w+2, (int)(h+3*scale) ); 01007 fl_begin_offscreen(off); 01008 fl_color(bg_color); 01009 // color offscreen background with a shade contrasting with the text color 01010 fl_rectf(0, 0, w+2, (int)(h+3*scale) ); 01011 fl_color(text_color); 01012 fl_draw(str, n, 1, (int)(h * 0.8) ); // draw string in offscreen 01013 // read (most of) the offscreen image 01014 uchar *img = fl_read_image(NULL, 1, 1, w, h, 0); 01015 fl_end_offscreen(); 01016 fl_font(fl_font(), old_size); 01017 fl_delete_offscreen(off); 01018 // compute the mask of what is not the background 01019 uchar *mask = calc_mask(img, w, h, bg_color); 01020 delete img; 01021 // write the string image to PostScript as a scaled bitmask 01022 fprintf(output, "%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w/scale, h/scale, w, h); 01023 uchar *di; 01024 int wmask = (w+7)/8; 01025 for (int j = h - 1; j >= 0; j--){ 01026 di = mask + j * wmask; 01027 for (int i = 0; i < wmask; i++){ 01028 //if (!(i%80)) fprintf(output, "\n"); // don't have lines longer than 255 chars 01029 fprintf(output, "%2.2x", *di ); 01030 di++; 01031 } 01032 fprintf(output,"\n"); 01033 } 01034 fprintf(output,">\n"); 01035 delete mask; 01036 } 01037 01038 static int is_in_table(unsigned utf) { 01039 unsigned i; 01040 static unsigned extra_table_roman[] = { // unicodes/*names*/ of other characters from PostScript standard fonts 01041 0x192/*florin*/, 0x2C6/*circumflex*/, 0x2C7/*caron*/, 01042 0x2D8/*breve*/, 0x2D9/*dotaccent*/, 0x2DA/*ring*/, 0x2DB/*ogonek*/, 0x2DC/*tilde*/, 0x2DD/*hungarumlaut*/, 01043 0x2013/*endash*/, 0x2014/*emdash*/, 0x2018/*quoteleft*/, 0x2019/*quoteright*/, 01044 0x201A/*quotesinglbase*/, 0x201C/*quotedblleft*/, 0x201D/*quotedblright*/, 0x201E/*quotedblbase*/, 01045 0x2020/*dagger*/, 0x2021/*daggerdbl*/, 0x2022/*bullet*/, 01046 0x2026/*ellipsis*/, 0x2030/*perthousand*/, 0x2039/*guilsinglleft*/, 0x203A/*guilsinglright*/, 01047 0x2044/*fraction*/, 0x20AC/*Euro*/, 0x2122/*trademark*/, 01048 0x2202/*partialdiff*/, 0x2206/*Delta*/, 0x2211/*summation*/, 0x221A/*radical*/, 01049 0x221E/*infinity*/, 0x2260/*notequal*/, 0x2264/*lessequal*/, 01050 0x2265/*greaterequal*/, 01051 0x25CA/*lozenge*/, 0xFB01/*fi*/, 0xFB02/*fl*/, 01052 0xF8FF/*apple*/ 01053 }; 01054 for ( i = 0; i < sizeof(extra_table_roman)/sizeof(int); i++) { 01055 if (extra_table_roman[i] == utf) return i + 0x180; 01056 } 01057 return 0; 01058 } 01059 01060 // outputs in PostScript a UTF8 string using the same width in points as on display 01061 void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y) { 01062 int len, code; 01063 if (!n || !str || !*str) return; 01064 // compute display width of string 01065 int width = (int)fl_width(str, n); 01066 if (width == 0) return; 01067 fprintf(output, "%d <", width); 01068 // transforms UTF8 encoding to our custom PostScript encoding as follows: 01069 // extract each unicode character 01070 // if unicode <= 0x17F, unicode and PostScript codes are identical 01071 // if unicode is one of the values listed in extra_table_roman above 01072 // its PostScript code is 0x180 + the character's rank in extra_table_roman 01073 // if unicode is something else, draw all string as bitmap image 01074 01075 const char *last = str + n; 01076 const char *str2 = str; 01077 while (str2 < last) { 01078 // Extract each unicode character of string. 01079 unsigned utf = fl_utf8decode(str2, last, &len); 01080 str2 += len; 01081 if (utf <= 0x17F) { // until Latin Extended-A 01082 ; 01083 } 01084 else if ( (code = is_in_table(utf)) != 0) { // other handled characters 01085 utf = code; 01086 } 01087 else { // unhandled character: draw all string as bitmap image 01088 fprintf(output, "> pop pop\n"); // close and ignore the opened hex string 01089 transformed_draw_extra(str, n, x, y, width, output); 01090 return; 01091 } 01092 fprintf(output, "%4.4X", utf); 01093 } 01094 fprintf(output, "> %g %g show_pos_width\n", x, y); 01095 } 01096 01097 void Fl_PostScript_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) { 01098 const char *last = str + n; 01099 const char *str2 = str; 01100 unsigned int *unis = new unsigned int[n + 1]; 01101 char *out = new char[n + 1]; 01102 int u = 0, len; 01103 char *p = out; 01104 double w = fl_width(str, n); 01105 while (str2 < last) { 01106 unis[u++] = fl_utf8decode(str2, last, &len); 01107 str2 += len; 01108 } 01109 while (u > 0) { 01110 len = fl_utf8encode(unis[--u], p); 01111 p += len; 01112 } 01113 transformed_draw(out, p - out, x - w, y); 01114 delete [] unis; 01115 delete [] out; 01116 } 01117 01118 struct matrix {double a, b, c, d, x, y;}; 01119 extern matrix * fl_matrix; 01120 01121 void Fl_PostScript_Graphics_Driver::concat(){ 01122 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); 01123 } 01124 01125 void Fl_PostScript_Graphics_Driver::reconcat(){ 01126 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); 01127 } 01128 01130 01131 01132 void Fl_PostScript_Graphics_Driver::begin_points(){ 01133 fprintf(output, "GS\n"); 01134 concat(); 01135 01136 fprintf(output, "BP\n"); 01137 gap_=1; 01138 shape_=POINTS; 01139 } 01140 01141 void Fl_PostScript_Graphics_Driver::begin_line(){ 01142 fprintf(output, "GS\n"); 01143 concat(); 01144 fprintf(output, "BP\n"); 01145 gap_=1; 01146 shape_=LINE; 01147 } 01148 01149 void Fl_PostScript_Graphics_Driver::begin_loop(){ 01150 fprintf(output, "GS\n"); 01151 concat(); 01152 fprintf(output, "BP\n"); 01153 gap_=1; 01154 shape_=LOOP; 01155 } 01156 01157 void Fl_PostScript_Graphics_Driver::begin_polygon(){ 01158 fprintf(output, "GS\n"); 01159 concat(); 01160 fprintf(output, "BP\n"); 01161 gap_=1; 01162 shape_=POLYGON; 01163 } 01164 01165 void Fl_PostScript_Graphics_Driver::vertex(double x, double y){ 01166 if(shape_==POINTS){ 01167 fprintf(output,"%g %g MT\n", x , y); 01168 gap_=1; 01169 return; 01170 } 01171 if(gap_){ 01172 fprintf(output,"%g %g MT\n", x , y); 01173 gap_=0; 01174 }else 01175 fprintf(output, "%g %g LT\n", x , y); 01176 } 01177 01178 void Fl_PostScript_Graphics_Driver::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3){ 01179 if(shape_==NONE) return; 01180 if(gap_) 01181 fprintf(output,"%g %g MT\n", x , y); 01182 else 01183 fprintf(output, "%g %g LT\n", x , y); 01184 gap_=0; 01185 01186 fprintf(output, "%g %g %g %g %g %g curveto \n", x1 , y1 , x2 , y2 , x3 , y3); 01187 } 01188 01189 01190 void Fl_PostScript_Graphics_Driver::circle(double x, double y, double r){ 01191 if(shape_==NONE){ 01192 fprintf(output, "GS\n"); 01193 concat(); 01194 // fprintf(output, "BP\n"); 01195 fprintf(output,"%g %g %g 0 360 arc\n", x , y , r); 01196 reconcat(); 01197 // fprintf(output, "ELP\n"); 01198 fprintf(output, "GR\n"); 01199 }else 01200 01201 fprintf(output, "%g %g %g 0 360 arc\n", x , y , r); 01202 01203 } 01204 01205 void Fl_PostScript_Graphics_Driver::arc(double x, double y, double r, double start, double a){ 01206 if(shape_==NONE) return; 01207 gap_=0; 01208 if(start>a) 01209 fprintf(output, "%g %g %g %g %g arc\n", x , y , r , -start, -a); 01210 else 01211 fprintf(output, "%g %g %g %g %g arcn\n", x , y , r , -start, -a); 01212 01213 } 01214 01215 void Fl_PostScript_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) { 01216 fprintf(output, "GS\n"); 01217 //fprintf(output, "BP\n"); 01218 begin_line(); 01219 fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); 01220 fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); 01221 arc(0,0,1,a2,a1); 01222 // fprintf(output, "0 0 1 %g %g arc\n" , -a1 , -a2); 01223 fprintf(output, "%g %g SC\n", 2.0/(w-1) , 2.0/(h-1) ); 01224 fprintf(output, "%g %g TR\n", -x - w/2.0 +0.5 , -y - h/2.0 +0.5); 01225 end_line(); 01226 01227 // fprintf(output, "%g setlinewidth\n", 2/sqrt(w*h)); 01228 // fprintf(output, "ELP\n"); 01229 // fprintf(output, 2.0/w , 2.0/w , " SC\n"; 01230 // fprintf(output, (-x - w/2.0) , (-y - h/2) , " TR\n"; 01231 fprintf(output, "GR\n"); 01232 } 01233 01234 void Fl_PostScript_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) { 01235 01236 fprintf(output, "GS\n"); 01237 fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); 01238 fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); 01239 begin_polygon(); 01240 vertex(0,0); 01241 arc(0.0,0.0, 1, a2, a1); 01242 end_polygon(); 01243 fprintf(output, "GR\n"); 01244 } 01245 01246 void Fl_PostScript_Graphics_Driver::end_points(){ 01247 gap_=1; 01248 reconcat(); 01249 fprintf(output, "ELP\n"); //?? 01250 fprintf(output, "GR\n"); 01251 shape_=NONE; 01252 } 01253 01254 void Fl_PostScript_Graphics_Driver::end_line(){ 01255 gap_=1; 01256 reconcat(); 01257 fprintf(output, "ELP\n"); 01258 fprintf(output, "GR\n"); 01259 shape_=NONE; 01260 } 01261 void Fl_PostScript_Graphics_Driver::end_loop(){ 01262 gap_=1; 01263 reconcat(); 01264 fprintf(output, "ECP\n"); 01265 fprintf(output, "GR\n"); 01266 shape_=NONE; 01267 } 01268 01269 void Fl_PostScript_Graphics_Driver::end_polygon(){ 01270 01271 gap_=1; 01272 reconcat(); 01273 fprintf(output, "EFP\n"); 01274 fprintf(output, "GR\n"); 01275 shape_=NONE; 01276 } 01277 01278 void Fl_PostScript_Graphics_Driver::transformed_vertex(double x, double y){ 01279 reconcat(); 01280 if(gap_){ 01281 fprintf(output, "%g %g MT\n", x , y); 01282 gap_=0; 01283 }else 01284 fprintf(output, "%g %g LT\n", x , y); 01285 concat(); 01286 } 01287 01289 01290 void Fl_PostScript_Graphics_Driver::push_clip(int x, int y, int w, int h) { 01291 Clip * c=new Clip(); 01292 clip_box(x,y,w,h,c->x,c->y,c->w,c->h); 01293 c->prev=clip_; 01294 clip_=c; 01295 fprintf(output, "CR\nCS\n"); 01296 if(lang_level_<3) 01297 recover(); 01298 fprintf(output, "%g %g %i %i CL\n", clip_->x-0.5 , clip_->y-0.5 , clip_->w , clip_->h); 01299 01300 } 01301 01302 void Fl_PostScript_Graphics_Driver::push_no_clip() { 01303 Clip * c = new Clip(); 01304 c->prev=clip_; 01305 clip_=c; 01306 clip_->x = clip_->y = clip_->w = clip_->h = -1; 01307 fprintf(output, "CR\nCS\n"); 01308 if(lang_level_<3) 01309 recover(); 01310 } 01311 01312 void Fl_PostScript_Graphics_Driver::pop_clip() { 01313 if(!clip_)return; 01314 Clip * c=clip_; 01315 clip_=clip_->prev; 01316 delete c; 01317 fprintf(output, "CR\nCS\n"); 01318 if(clip_ && clip_->w >0) 01319 fprintf(output, "%g %g %i %i CL\n", clip_->x - 0.5, clip_->y - 0.5, clip_->w , clip_->h); 01320 // uh, -0.5 is to match screen clipping, for floats there should be something beter 01321 if(lang_level_<3) 01322 recover(); 01323 } 01324 01325 int Fl_PostScript_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H){ 01326 if(!clip_){ 01327 X=x;Y=y;W=w;H=h; 01328 return 1; 01329 } 01330 if(clip_->w < 0){ 01331 X=x;Y=y;W=w;H=h; 01332 return 1; 01333 } 01334 int ret=0; 01335 if (x > (X=clip_->x)) {X=x; ret=1;} 01336 if (y > (Y=clip_->y)) {Y=y; ret=1;} 01337 if ((x+w) < (clip_->x+clip_->w)) { 01338 W=x+w-X; 01339 01340 ret=1; 01341 01342 }else 01343 W = clip_->x + clip_->w - X; 01344 if(W<0){ 01345 W=0; 01346 return 1; 01347 } 01348 if ((y+h) < (clip_->y+clip_->h)) { 01349 H=y+h-Y; 01350 ret=1; 01351 }else 01352 H = clip_->y + clip_->h - Y; 01353 if(H<0){ 01354 W=0; 01355 H=0; 01356 return 1; 01357 } 01358 return ret; 01359 } 01360 01361 int Fl_PostScript_Graphics_Driver::not_clipped(int x, int y, int w, int h){ 01362 if(!clip_) return 1; 01363 if(clip_->w < 0) return 1; 01364 int X, Y, W, H; 01365 clip_box(x, y, w, h, X, Y, W, H); 01366 if(W) return 1; 01367 return 0; 01368 } 01369 01370 01371 void Fl_PostScript_File_Device::margins(int *left, int *top, int *right, int *bottom) // to implement 01372 { 01373 Fl_PostScript_Graphics_Driver *ps = driver(); 01374 if(left) *left = (int)(ps->left_margin / ps->scale_x + .5); 01375 if(right) *right = (int)(ps->left_margin / ps->scale_x + .5); 01376 if(top) *top = (int)(ps->top_margin / ps->scale_y + .5); 01377 if(bottom) *bottom = (int)(ps->top_margin / ps->scale_y + .5); 01378 } 01379 01380 int Fl_PostScript_File_Device::printable_rect(int *w, int *h) 01381 //returns 0 iff OK 01382 { 01383 Fl_PostScript_Graphics_Driver *ps = driver(); 01384 if(w) *w = (int)((ps->pw_ - 2 * ps->left_margin) / ps->scale_x + .5); 01385 if(h) *h = (int)((ps->ph_ - 2 * ps->top_margin) / ps->scale_y + .5); 01386 return 0; 01387 } 01388 01389 void Fl_PostScript_File_Device::origin(int x, int y) 01390 { 01391 x_offset = x; 01392 y_offset = y; 01393 Fl_PostScript_Graphics_Driver *ps = driver(); 01394 fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", 01395 ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x, y, ps->angle); 01396 } 01397 01398 void Fl_PostScript_File_Device::scale (float s_x, float s_y) 01399 { 01400 Fl_PostScript_Graphics_Driver *ps = driver(); 01401 ps->scale_x = s_x; 01402 ps->scale_y = s_y; 01403 fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %f rotate GS\n", 01404 ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, ps->angle); 01405 } 01406 01407 void Fl_PostScript_File_Device::rotate (float rot_angle) 01408 { 01409 Fl_PostScript_Graphics_Driver *ps = driver(); 01410 ps->angle = - rot_angle; 01411 fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", 01412 ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x_offset, y_offset, ps->angle); 01413 } 01414 01415 void Fl_PostScript_File_Device::translate(int x, int y) 01416 { 01417 fprintf(driver()->output, "GS %d %d translate GS\n", x, y); 01418 } 01419 01420 void Fl_PostScript_File_Device::untranslate(void) 01421 { 01422 fprintf(driver()->output, "GR GR\n"); 01423 } 01424 01425 int Fl_PostScript_File_Device::start_page (void) 01426 { 01427 Fl_PostScript_Graphics_Driver *ps = driver(); 01428 ps->page(ps->page_format_); 01429 x_offset = 0; 01430 y_offset = 0; 01431 ps->scale_x = ps->scale_y = 1.; 01432 ps->angle = 0; 01433 fprintf(ps->output, "GR GR GS %d %d translate GS\n", ps->left_margin, ps->top_margin); 01434 return 0; 01435 } 01436 01437 int Fl_PostScript_File_Device::end_page (void) 01438 { 01439 return 0; 01440 } 01441 01442 void Fl_PostScript_File_Device::end_job (void) 01443 // finishes PostScript & closes file 01444 { 01445 Fl_PostScript_Graphics_Driver *ps = driver(); 01446 if (ps->nPages) { // for eps nPages is 0 so it is fine .... 01447 fprintf(ps->output, "CR\nGR\nGR\nGR\nSP\n restore\n"); 01448 if (!ps->pages_){ 01449 fprintf(ps->output, "%%%%Trailer\n"); 01450 fprintf(ps->output, "%%%%Pages: %i\n" , ps->nPages); 01451 }; 01452 } else 01453 fprintf(ps->output, "GR\n restore\n"); 01454 fputs("%%EOF",ps->output); 01455 ps->reset(); 01456 fflush(ps->output); 01457 if(ferror(ps->output)) { 01458 fl_alert ("Error during PostScript data output."); 01459 } 01460 if (ps->close_cmd_) { 01461 (*ps->close_cmd_)(ps->output); 01462 } else { 01463 fclose(ps->output); 01464 } 01465 while (ps->clip_){ 01466 Fl_PostScript_Graphics_Driver::Clip * c= ps->clip_; 01467 ps->clip_= ps->clip_->prev; 01468 delete c; 01469 } 01470 Fl_Display_Device::display_device()->set_current(); 01471 } 01472 01473 #if ! (defined(__APPLE__) || defined(WIN32) ) 01474 int Fl_PostScript_Printer::start_job(int pages, int *firstpage, int *lastpage) { 01475 enum Fl_Paged_Device::Page_Format format; 01476 enum Fl_Paged_Device::Page_Layout layout; 01477 01478 // first test version for print dialog 01479 if (!print_panel) make_print_panel(); 01480 print_load(); 01481 print_selection->deactivate(); 01482 print_all->setonly(); 01483 print_all->do_callback(); 01484 print_from->value("1"); 01485 { char tmp[10]; snprintf(tmp, sizeof(tmp), "%d", pages); print_to->value(tmp); } 01486 print_panel->show(); // this is modal 01487 while (print_panel->shown()) Fl::wait(); 01488 01489 if (!print_start) // user clicked cancel 01490 return 1; 01491 01492 // get options 01493 01494 format = print_page_size->value() ? Fl_Paged_Device::A4 : Fl_Paged_Device::LETTER; 01495 { // page range choice 01496 int from = 1, to = pages; 01497 if (print_pages->value()) { 01498 sscanf(print_from->value(), "%d", &from); 01499 sscanf(print_to->value(), "%d", &to); 01500 } 01501 if (from < 1) from = 1; 01502 if (to > pages) to = pages; 01503 if (to < from) to = from; 01504 if (firstpage) *firstpage = from; 01505 if (lastpage) *lastpage = to; 01506 pages = to - from + 1; 01507 } 01508 01509 if (print_output_mode[0]->value()) layout = Fl_Paged_Device::PORTRAIT; 01510 else if (print_output_mode[1]->value()) layout = Fl_Paged_Device::LANDSCAPE; 01511 else if (print_output_mode[2]->value()) layout = Fl_Paged_Device::PORTRAIT; 01512 else layout = Fl_Paged_Device::LANDSCAPE; 01513 01514 int print_pipe = print_choice->value(); // 0 = print to file, >0 = printer (pipe) 01515 01516 const char *media = print_page_size->text(print_page_size->value()); 01517 const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); 01518 if (!print_pipe) printer = "<File>"; 01519 01520 if (!print_pipe) // fall back to file printing 01521 return Fl_PostScript_File_Device::start_job (pages, format, layout); 01522 01523 // Print: pipe the output into the lp command... 01524 01525 char command[1024]; 01526 snprintf(command, sizeof(command), "lp -s -d %s -n %d -t '%s' -o media=%s", 01527 printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5), 01528 "FLTK", media); 01529 01530 Fl_PostScript_Graphics_Driver *ps = driver(); 01531 ps->output = popen(command, "w"); 01532 if (!ps->output) { 01533 fl_alert("could not run command: %s\n",command); 01534 return 1; 01535 } 01536 ps->close_command(pclose); 01537 this->set_current(); 01538 return ps->start_postscript(pages, format, layout); // start printing 01539 } 01540 01541 #endif // ! (defined(__APPLE__) || defined(WIN32) ) 01542 01543 #endif // FL_DOXYGEN 01544 01545 // 01546 // End of "$Id: Fl_PostScript.cxx 8190 2011-01-05 10:21:45Z manolo $". 01547 //