PageRenderTime 61ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/source/src/Graphics/Renderer/printer.cpp

http://itexmacs.googlecode.com/
C++ | 883 lines | 718 code | 95 blank | 70 comment | 136 complexity | 9e7a474063351b66e1493fbe7ee280e8 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.0
  1. /******************************************************************************
  2. * MODULE : printer.cpp
  3. * DESCRIPTION: Renderer for printing post-script graphics
  4. * COPYRIGHT : (C) 1999 Joris van der Hoeven
  5. *******************************************************************************
  6. * This software falls under the GNU general public license version 3 or later.
  7. * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
  8. * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
  9. ******************************************************************************/
  10. #include "printer.hpp"
  11. #include "Metafont/tex_files.hpp"
  12. #include "Freetype/tt_file.hpp"
  13. #include "file.hpp"
  14. #include "image_files.hpp"
  15. #include "analyze.hpp"
  16. #include "iterator.hpp"
  17. #include "merge_sort.hpp"
  18. #include "scheme.hpp"
  19. #include "image_files.hpp"
  20. string PS_CLIP_PUSH ("gsave");
  21. string PS_CLIP_POP ("grestore");
  22. string PS_CLIP ("cl");
  23. string PS_LINE ("ln");
  24. string PS_FILL ("fl");
  25. string PS_ARC ("ac");
  26. string PS_FILL_ARC ("fac");
  27. string PS_STROKE ("st");
  28. string PS_POL_START ("sp");
  29. string PS_POL_NEXT ("np");
  30. string PS_POL_END ("ep");
  31. string PS1 ("u");
  32. string PS2 ("z");
  33. /******************************************************************************
  34. * constructors and destructors
  35. ******************************************************************************/
  36. printer_rep::printer_rep (
  37. url ps_file_name2, int dpi2, int nr_pages2,
  38. string page_type2, bool landscape2, double paper_w2, double paper_h2):
  39. ps_file_name (ps_file_name2), dpi (dpi2),
  40. nr_pages (nr_pages2), page_type (page_type2),
  41. landscape (landscape2), paper_w (paper_w2), paper_h (paper_h2),
  42. use_alpha (get_preference ("experimental alpha") == "on"),
  43. linelen (0), fg (-1), bg (-1), ncols (0),
  44. lw (-1), nwidths (0), cfn (""), nfonts (0),
  45. xpos (0), ypos (0), tex_flag (false),
  46. defs ("?"), tex_chars ("?"), tex_width ("?"),
  47. tex_fonts ("?"), tex_font_chars (array<int>(0))
  48. {
  49. string tex_pro, special_pro, color_pro, texps_pro;
  50. load_string ("$TEXMACS_PATH/misc/convert/tex.pro", tex_pro, true);
  51. load_string ("$TEXMACS_PATH/misc/convert/special.pro", special_pro, true);
  52. load_string ("$TEXMACS_PATH/misc/convert/color.pro", color_pro, true);
  53. load_string ("$TEXMACS_PATH/misc/convert/texps.pro", texps_pro, true);
  54. prologue << "%!PS-Adobe-2.0\n"
  55. << "%%Creator: TeXmacs-" TEXMACS_VERSION "\n"
  56. << "%%Title: " << as_string (tail (ps_file_name)) << "\n"
  57. << "%%Pages: " << as_string (nr_pages) << "\n"
  58. << "%%PageOrder: Ascend\n";
  59. if (page_type != "user")
  60. prologue << "%%DocumentPaperSizes: " << page_type << "\n";
  61. if (landscape)
  62. prologue << "%%BoundingBox: 0 0 "
  63. << as_string ((int) (28.36*paper_h+ 0.5)) << " "
  64. << as_string ((int) (28.36*paper_w+ 0.5)) << "\n"
  65. << "%%Orientation: Landscape\n";
  66. else
  67. prologue << "%%BoundingBox: 0 0 "
  68. << as_string ((int) (28.36*paper_w+ 0.5)) << " "
  69. << as_string ((int) (28.36*paper_h+ 0.5)) << "\n";
  70. prologue << "%%EndComments\n\n"
  71. << tex_pro << "\n"
  72. << special_pro << "\n"
  73. << texps_pro << "\n"
  74. << "TeXDict begin\n"
  75. << as_string ((int) (1864680.0*paper_w+ 0.5)) << " "
  76. << as_string ((int) (1864680.0*paper_h+ 0.5)) << " 1000 "
  77. << as_string (dpi) << " " << as_string (dpi)
  78. << " (TeXmacs) @start\n";
  79. define (PS_CLIP, string ("/pt4 X /pt3 X /pt2 X /pt1 X\n") *
  80. string ("newpath pt1 pt2 moveto pt3 pt2 lineto ") *
  81. string ("pt3 pt4 lineto pt1 pt4 lineto pt1 pt2 lineto clip"));
  82. define (PS_LINE, string ("/pt4 X /pt3 X /pt2 X /pt1 X\n") *
  83. string ("newpath pt1 pt2 moveto pt3 pt4 lineto stroke"));
  84. define (PS_FILL, string ("/pt4 X /pt3 X /pt2 X /pt1 X\n") *
  85. string ("newpath pt1 pt2 moveto pt3 pt2 lineto ") *
  86. string ("pt3 pt4 lineto pt1 pt4 lineto pt1 pt2 eofill stroke"));
  87. define (PS_ARC, string ("/a2 X /a1 X /r2 X /r1 X /pt2 X /pt1 X\n") *
  88. string ("newpath pt1 pt2 r1 r2 a1 a2 ellipse stroke"));
  89. define (PS_FILL_ARC, string ("/a2 X /a1 X /r2 X /r1 X /pt2 X /pt1 X\n") *
  90. string ("newpath pt1 pt2 r1 r2 a1 a2 ellipse eofill stroke"));
  91. define (PS_STROKE, string ("stroke"));
  92. define (PS_POL_START, string ("/pt2 X /pt1 X\n") *
  93. string ("newpath pt1 pt2 moveto"));
  94. define (PS_POL_NEXT, string ("/pt2 X /pt1 X\n") *
  95. string ("pt1 pt2 lineto"));
  96. define (PS_POL_END, string ("closepath eofill"));
  97. define (PS1, string ("gsave"));
  98. define (PS2, string ("1 -1 scale show grestore"));
  99. cur_page= 0;
  100. next_page ();
  101. }
  102. printer_rep::~printer_rep () {
  103. next_page ();
  104. body << "\n%%Trailer\n"
  105. << "end\n"
  106. << "userdict /end-hook known{end-hook} if\n"
  107. << "%%EOF\n";
  108. generate_tex_fonts ();
  109. prologue << "end\n"
  110. << "systemdict /pdfmark known{userdict /?pdfmark systemdict /exec get put}{userdict /?pdfmark systemdict /pop get put userdict /pdfmark systemdict /cleartomark get put}ifelse\n"
  111. << "%%EndProlog\n\n"
  112. << "%%BeginSetup\n"
  113. << "%%Feature: *Resolution " << as_string (dpi) << "dpi\n"
  114. << "TeXDict begin\n";
  115. if (page_type != "user") {
  116. prologue << "%%BeginPaperSize: " << page_type << "\n";
  117. prologue << page_type << "\n";
  118. prologue << "%%EndPaperSize\n";
  119. }
  120. if (landscape)
  121. prologue << "@landscape\n";
  122. prologue << "%%EndSetup\n";
  123. string ps_text= prologue * "\n" * body;
  124. save_string (ps_file_name, ps_text);
  125. }
  126. bool
  127. printer_rep::is_printer () {
  128. return true;
  129. }
  130. void
  131. printer_rep::next_page () {
  132. if (cur_page > 0) print ("eop\n");
  133. if (cur_page >= nr_pages) return;
  134. cur_page++;
  135. body << "\n%%Page: " << as_string (cur_page) << " "
  136. << as_string (cur_page) << "\n"
  137. << as_string (cur_page) << " "
  138. << as_string (cur_page-1) << " bop\n";
  139. set_clipping (0, (int) (-(dpi*PIXEL*paper_h)/2.54),
  140. (int) ((dpi*PIXEL*paper_w)/2.54), 0);
  141. fg = -1;
  142. bg = -1;
  143. lw = -1;
  144. cfn = "";
  145. xpos= 0;
  146. ypos= 0;
  147. }
  148. /******************************************************************************
  149. * subroutines for printing
  150. ******************************************************************************/
  151. void
  152. printer_rep::define (string s, string defn) {
  153. if (defs->contains (s)) return;
  154. defs (defn)= s;
  155. prologue << "/" << s << " {" << defn << "} N\n";
  156. }
  157. void
  158. printer_rep::sep () {
  159. if ((N(body) > 0) &&
  160. (body [N(body)-1] != ')') &&
  161. (body [N(body)-1] != '\n')) {
  162. body << " ";
  163. linelen++;
  164. tex_flag= false;
  165. }
  166. }
  167. void
  168. printer_rep::cr () {
  169. body << "\n";
  170. linelen= 0;
  171. tex_flag= false;
  172. }
  173. void
  174. printer_rep::print (string s) {
  175. if (N(s)==0) return;
  176. if ((linelen>0) && (linelen+N(s)>79)) {
  177. body << "\n";
  178. linelen= 0;
  179. tex_flag= false;
  180. }
  181. else if (s[0]!='(') sep ();
  182. if (tex_flag && (s[0]=='(')) {
  183. body->resize (N(body)-2);
  184. linelen -= 2;
  185. s= s (1,N(s));
  186. }
  187. body << s;
  188. linelen += N(s);
  189. tex_flag= false;
  190. }
  191. void
  192. printer_rep::print (SI x, SI y) {
  193. x += ox; y += oy;
  194. if (x>=0) x= x/PIXEL; else x= (x-PIXEL+1)/PIXEL;
  195. if (y>=0) y= y/PIXEL; else y= (y-PIXEL+1)/PIXEL;
  196. print (as_string (x-dpi));
  197. print (as_string (-y-dpi));
  198. }
  199. void
  200. printer_rep::move_to (SI x, SI y) {
  201. x += ox; y += oy;
  202. if (x>=0) x= x/PIXEL; else x= (x-PIXEL+1)/PIXEL;
  203. if (y>=0) y= y/PIXEL; else y= (y-PIXEL+1)/PIXEL;
  204. if (tex_flag && (xpos==x) && (ypos==y)) return;
  205. if (tex_flag && (ypos==y)) {
  206. body->resize (N(body)-1);
  207. linelen -= 1;
  208. tex_flag= false;
  209. int diff= x-xpos;
  210. if ((diff>=-4) && (diff<=4)) print (string ((char) ('p'+diff)));
  211. else {
  212. print (as_string (diff));
  213. print ("b");
  214. }
  215. xpos= x;
  216. return;
  217. }
  218. xpos= x; ypos= y;
  219. print (as_string (x-dpi));
  220. print (as_string (-y-dpi));
  221. print ("a");
  222. }
  223. string
  224. printer_rep::define_alpha (int a) {
  225. string aa= as_string (((double) a) / 255.0);
  226. string s= "[ /ca " * aa * " /CA " * aa * " /SetTransparency pdfmark";
  227. if (!defs->contains (s)) define ("A" * as_string (a), s);
  228. return defs[s];
  229. }
  230. void
  231. printer_rep::select_color (color c) {
  232. int r, g, b, a;
  233. get_rgb_color (c, r, g, b, a);
  234. r= 10000+ ((r*1000)/255);
  235. g= 10000+ ((g*1000)/255);
  236. b= 10000+ ((b*1000)/255);
  237. string rr= as_string (r); rr= rr(1,2) * "." * rr(2,5);
  238. string gg= as_string (g); gg= gg(1,2) * "." * gg(2,5);
  239. string bb= as_string (b); bb= bb(1,2) * "." * bb(2,5);
  240. string s = rr * " " * gg * " " * bb * " setrgbcolor";
  241. if (use_alpha) s= s * " " * define_alpha (a);
  242. if (!defs->contains (s)) {
  243. define ("C" * as_string (ncols), s);
  244. ncols++;
  245. }
  246. print (defs[s]);
  247. }
  248. void
  249. printer_rep::select_line_width (SI w) {
  250. w= w/PIXEL; if (w<1) w=1;
  251. string s = as_string (w) * " setlinewidth";
  252. if (!defs->contains (s)) {
  253. define ("W" * as_string (nwidths), s);
  254. nwidths++;
  255. }
  256. print (defs[s]);
  257. }
  258. /******************************************************************************
  259. * subroutines for fonts
  260. ******************************************************************************/
  261. static string
  262. prepare_text (string s) {
  263. int i;
  264. string r;
  265. for (i=0; i<N(s); i++) {
  266. int c= ((unsigned char) s[i]);
  267. if ((s[i]=='(') || (s[i]==')') || (s[i]=='\\'))
  268. r << '\\' << s[i];
  269. else if ((c <= 32) || (c >= 128)) {
  270. r << '\\';
  271. r << ('0' + (c >> 6));
  272. r << ('0' + ((c >> 3) & 7));
  273. r << ('0' + (c & 7));
  274. }
  275. else r << s[i];
  276. }
  277. return r;
  278. }
  279. void
  280. printer_rep::select_tex_font (string name) {
  281. if (cfn==name) return;
  282. cfn= name;
  283. print (tex_fonts [name]);
  284. }
  285. /******************************************************************************
  286. * make tex characters and fonts
  287. ******************************************************************************/
  288. static const char* hex_string= "0123456789ABCDEF";
  289. void
  290. printer_rep::make_tex_char (string name, unsigned char c, glyph gl) {
  291. // cout << "Make char " << (int) c << " of " << name << "\n";
  292. string char_name (name * "-" * as_string ((int) c));
  293. if (tex_chars->contains (char_name)) return;
  294. if (!tex_fonts->contains (name)) {
  295. tex_fonts (name)= "F" * as_string (nfonts);
  296. tex_font_chars (name)= array<int> (0);
  297. nfonts++;
  298. }
  299. tex_font_chars (name) << ((int) c);
  300. string hex_code;
  301. int i, j, count=0, cur= 0;
  302. for (j=0; j < gl->height; j++)
  303. for (i=0; i < ((gl->width+7) & (-8)); i++) {
  304. cur= cur << 1;
  305. if ((i<gl->width) && (gl->get_x(i,j)>0)) cur++;
  306. count++;
  307. if (count==4) {
  308. hex_code << hex_string[cur];
  309. cur = 0;
  310. count= 0;
  311. }
  312. }
  313. int d1= gl->width;
  314. int d2= gl->height;
  315. int d3= 130+ gl->xoff;
  316. int d4= 126+ gl->yoff;
  317. int d5= gl->lwidth;
  318. if ((d1<256) && (d2<256) && (d3<256) && (d4<256) && (d5<256)) {
  319. hex_code << as_hexadecimal (d1, 2) << as_hexadecimal (d2, 2)
  320. << as_hexadecimal (d3, 2) << as_hexadecimal (d4, 2)
  321. << as_hexadecimal (d5, 2);
  322. hex_code= "<" * hex_code * ">";
  323. }
  324. else {
  325. hex_code= "[<" * hex_code * ">";
  326. hex_code << as_string (d1) << " " << as_string (d2) << " "
  327. << as_string (d3) << " " << as_string (d4) << " "
  328. << as_string (d5) << " ";
  329. }
  330. tex_chars (char_name)= hex_code;
  331. tex_width (char_name)= as_string (d5);
  332. }
  333. static string
  334. find_ps_font_name (string name, string s) {
  335. int i, n= N(s);
  336. for (i=0; i<n; i++) {
  337. if (test (s, i, "/FontName /")) {
  338. i += 11;
  339. int start= i;
  340. while (i<n && s[i] != ' ') i++;
  341. return s (start, i);
  342. }
  343. while (i<n && s[i] != '\12' && s[i] != '\15') i++;
  344. }
  345. return name;
  346. }
  347. #define HEX_PER_LINE 30
  348. static SI parse_length (string pfb, int& pos) {
  349. QN c4= (QN) pfb[pos++];
  350. QN c3= (QN) pfb[pos++];
  351. QN c2= (QN) pfb[pos++];
  352. QI c1= (QI) pfb[pos++];
  353. return (((((((SI) c1)<<8)+ ((SI) c2))<<8)+ ((SI) c3))<<8)+ c4;
  354. }
  355. static string pfb_to_pfa (url file) {
  356. //cout << "pfb_to_pfa :" << file << LF;
  357. string pfb, pfa;
  358. QN magic, type = 0;
  359. SI length;
  360. (void) load_string (file, pfb, true);
  361. int pos = 0, size = N(pfb);
  362. while ((pos < size) && (type != 3)) {
  363. parse (pfb, pos, magic);
  364. //cout << "magic:" << as_hexadecimal(magic,2) << LF ;
  365. if (magic != 128) {
  366. FAILED ("Not a pfb file");
  367. }
  368. parse (pfb, pos, type);
  369. //cout << "type:" << as_hexadecimal(type,2) << LF;
  370. switch (type) {
  371. case 1 :
  372. // plain text
  373. length = parse_length (pfb, pos);
  374. // parse (pfb, pos, length);
  375. //cout << "plain text of size " << length << LF;
  376. for (int i=0; i <length; i++) {
  377. QI ch;
  378. parse(pfb, pos, ch);
  379. if (ch == '\r') pfa << "\n";
  380. else pfa << ch;
  381. }
  382. break;
  383. case 2 :
  384. // binary data
  385. length = parse_length (pfb, pos);
  386. // parse (pfb, pos, length);
  387. //cout << "binary data of size " << length << LF;
  388. for (int i=0; i <length; i++) {
  389. QI ch;
  390. parse(pfb, pos, ch);
  391. pfa << as_hexadecimal (ch, 2);
  392. if ((i+1) % HEX_PER_LINE == 0) pfa << "\n";
  393. }
  394. break;
  395. case 3 :
  396. //cout << "end of file" << LF;
  397. // end of file
  398. break;
  399. default :
  400. FAILED ("Unknown field type while reading PFB file");
  401. break;
  402. }
  403. }
  404. return pfa;
  405. }
  406. #undef HEX_PER_LINE
  407. void
  408. printer_rep::generate_tex_fonts () {
  409. hashset<string> done;
  410. iterator<string> it= iterate (tex_fonts);
  411. while (it->busy ()) {
  412. string fn_name= it->next ();
  413. array<int> a= tex_font_chars [fn_name];
  414. merge_sort (a);
  415. int i, d, l;
  416. string name = tex_fonts [fn_name], ttf;
  417. int pos = search_forwards (".", fn_name);
  418. string root = (pos==-1? fn_name: fn_name (0, pos));
  419. #ifndef OS_WIN32 // we need pfbtopfa
  420. if ((pos!=-1) && ends (fn_name, "tt")) {
  421. int pos2= search_backwards (":", fn_name);
  422. root= fn_name (0, pos2);
  423. url u= tt_font_find (root);
  424. if (suffix (u) == "pfb") {
  425. ttf = pfb_to_pfa (u);
  426. }
  427. }
  428. #endif
  429. if (ttf != "") {
  430. string ttf_name= find_ps_font_name (root, ttf);
  431. if (!done->contains (root)) {
  432. prologue << "%%BeginFont: " << root << "\n";
  433. prologue << ttf;
  434. prologue << "\n%%EndFont\n";
  435. done->insert (root);
  436. }
  437. array<string> cum;
  438. cum << "{}" * as_string (N(a));
  439. for (i=0; i<N(a); i++) {
  440. string w= tex_width [fn_name * "-" * as_string (a[i])];
  441. d= (i==0? a[0]: (a[i]-a[i-1]-1));
  442. if (d>0) cum << as_string (d) * "[";
  443. cum << w * " ";
  444. }
  445. d= 255-a[i-1];
  446. if (d>0) cum << as_string (d) * "[";
  447. int szpos = pos-1;
  448. while ((szpos>0) && is_numeric (fn_name[szpos-1])) szpos--;
  449. double sz = as_double (fn_name (szpos, pos));
  450. double dpi= as_double (fn_name (pos+1, N(fn_name)-2));
  451. string mag= as_string (83.022 * (sz/10.0) * (dpi/600.0));
  452. string fdef;
  453. for (i=N(cum)-1; i>=0; i--) fdef << cum[i];
  454. fdef= "/" * name * " " * fdef * " " * mag * " /" * ttf_name * " rf";
  455. for (i=0, l=0; i<N(fdef); i++, l++)
  456. if ((l<70) || (fdef[i]!=' ')) prologue << fdef[i];
  457. else { prologue << '\n'; l=-1; }
  458. prologue << "\n";
  459. }
  460. else {
  461. prologue << "/" << tex_fonts [fn_name]
  462. << " " << as_string (N(a))
  463. << " " << as_string (a[N(a)-1]+1) << " df\n";
  464. for (i=0; i<N(a); i++) {
  465. int end;
  466. string hex_code= tex_chars [fn_name * "-" * as_string (a[i])];
  467. for (end=1; end < N(hex_code); end++)
  468. if (hex_code[end-1]=='>') break;
  469. string after= hex_code (end, N(hex_code));
  470. if ((i>0) && (a[i]==(a[i-1]+1))) after << "I";
  471. else after << as_string (a[i]) << " D";
  472. if (i==(N(a)-1)) after << " E";
  473. hex_code= hex_code (0, end);
  474. int j, l, n= N(hex_code);
  475. for (j=0; j<n; j+=79) {
  476. if (n < (j+79)) prologue << hex_code (j, n);
  477. else prologue << hex_code (j, j+79) << "\n";
  478. }
  479. l= 79-(n%79);
  480. if (l<N(after)) prologue << "\n";
  481. prologue << after << "\n";
  482. }
  483. }
  484. }
  485. }
  486. /******************************************************************************
  487. * Clipping
  488. ******************************************************************************/
  489. void
  490. printer_rep::set_clipping (SI x1, SI y1, SI x2, SI y2, bool restore) {
  491. outer_round (x1, y1, x2, y2);
  492. renderer_rep::set_clipping (x1, y1, x2, y2);
  493. if (restore) {
  494. print (PS_CLIP_POP);
  495. cfn= "";
  496. }
  497. else {
  498. print (PS_CLIP_PUSH);
  499. print (x1, y1);
  500. print (x2, y2);
  501. print (PS_CLIP);
  502. }
  503. }
  504. /******************************************************************************
  505. * graphical routines
  506. ******************************************************************************/
  507. color
  508. printer_rep::get_color () {
  509. return fg;
  510. }
  511. color
  512. printer_rep::get_background () {
  513. return bg;
  514. }
  515. void
  516. printer_rep::set_color (color c) {
  517. if (fg==c) return;
  518. fg= c;
  519. select_color (c);
  520. }
  521. void
  522. printer_rep::set_background (color c) {
  523. if (bg==c) return;
  524. bg= c;
  525. }
  526. void
  527. printer_rep::draw (int ch, font_glyphs fn, SI x, SI y) {
  528. glyph gl= fn->get(ch);
  529. if (is_nil (gl)) return;
  530. string name= fn->res_name;
  531. unsigned char c= ch;
  532. if (ch >= 256) {
  533. name= name * "-" * as_string (ch / 256);
  534. c= (unsigned char) (ch & 255);
  535. }
  536. make_tex_char (name, c, gl);
  537. select_tex_font (name);
  538. move_to (x, y);
  539. print ("(" * prepare_text (string ((char) c)) * ")p");
  540. tex_flag= true;
  541. xpos += gl->lwidth;
  542. }
  543. void
  544. printer_rep::set_line_style (SI w, int type, bool round) {
  545. (void) type;
  546. (void) round;
  547. // if (lw == w) return;
  548. // FIXME: apparently, the line width can be overidden by some of
  549. // the graphical constructs (example file: newimpl.tm, in which
  550. // the second dag was not printed using the right width)
  551. lw= w;
  552. select_line_width (w);
  553. }
  554. void
  555. printer_rep::line (SI x1, SI y1, SI x2, SI y2) {
  556. print (x1, y1);
  557. print (x2, y2);
  558. print (PS_LINE);
  559. }
  560. void
  561. printer_rep::lines (array<SI> x, array<SI> y) {
  562. int i, n= N(x);
  563. if ((N(y) != n) || (n<1)) return;
  564. print (x[0], y[0]);
  565. print (PS_POL_START);
  566. for (i=1; i<n; i++) {
  567. print (x[i], y[i]);
  568. print (PS_POL_NEXT);
  569. }
  570. print (PS_STROKE);
  571. }
  572. void
  573. printer_rep::clear (SI x1, SI y1, SI x2, SI y2) {
  574. select_color (bg);
  575. print (x1, y1);
  576. print (x2, y2);
  577. print (PS_FILL);
  578. select_color (fg);
  579. }
  580. void
  581. printer_rep::fill (SI x1, SI y1, SI x2, SI y2) {
  582. if ((x1<x2) && (y1<y2)) {
  583. print (x1, y1);
  584. print (x2, y2);
  585. print (PS_FILL);
  586. }
  587. }
  588. void
  589. printer_rep::arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta) {
  590. print ((x1+x2)/2, (y1+y2)/2);
  591. print (as_string ((x2-x1)/(2*PIXEL)));
  592. print (as_string ((y1-y2)/(2*PIXEL)));
  593. print (as_string (((double) alpha)/64));
  594. print (as_string (((double) (alpha+delta))/64));
  595. print (PS_ARC);
  596. }
  597. void
  598. printer_rep::fill_arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta) {
  599. print ((x1+x2)/2, (y1+y2)/2);
  600. print (as_string ((x2-x1)/(2*PIXEL)));
  601. print (as_string ((y1-y2)/(2*PIXEL)));
  602. print (as_string (((double) alpha)/64));
  603. print (as_string (((double) (alpha+delta))/64));
  604. print (PS_FILL_ARC);
  605. }
  606. void
  607. printer_rep::polygon (array<SI> x, array<SI> y, bool convex) {
  608. (void) convex;
  609. int i, n= N(x);
  610. if ((N(y) != n) || (n<1)) return;
  611. print (x[0], y[0]);
  612. print (PS_POL_START);
  613. for (i=1; i<n; i++) {
  614. print (x[i], y[i]);
  615. print (PS_POL_NEXT);
  616. }
  617. print (PS_POL_END);
  618. }
  619. void
  620. printer_rep::xpm (url file_name, SI x, SI y) {
  621. (void) file_name; (void) x; (void) y;
  622. FAILED ("not yet implemented");
  623. }
  624. /*
  625. string
  626. incorporate_postscript (string s) {
  627. int i;
  628. string r;
  629. for (i=0; i<N(s); )
  630. if (s[i] == '%') {
  631. for (; (i<N(s)) && (s[i]!='\n'); i++);
  632. if (i<N(s)) i++;
  633. }
  634. else {
  635. for (; (i<N(s)) && (s[i]!='\n'); ) r << s[i++];
  636. if (i<N(s)) { r << s[i++]; }
  637. }
  638. return r;
  639. }
  640. */
  641. void
  642. printer_rep::image (
  643. url u, SI w, SI h, SI x, SI y,
  644. double cx1, double cy1, double cx2, double cy2, int alpha)
  645. {
  646. (void) alpha; // FIXME
  647. int bx1, by1, bx2, by2;
  648. ps_bounding_box (u, bx1, by1, bx2, by2);
  649. int x1= bx1 + (int) (cx1 * (bx2 - bx1) + 0.5);
  650. int y1= by1 + (int) (cy1 * (by2 - by1) + 0.5);
  651. int x2= bx1 + (int) (cx2 * (bx2 - bx1) + 0.5);
  652. int y2= by1 + (int) (cy2 * (by2 - by1) + 0.5);
  653. double sc_x= (72.0/dpi) * ((double) (w/PIXEL)) / ((double) (x2-x1));
  654. double sc_y= (72.0/dpi) * ((double) (h/PIXEL)) / ((double) (y2-y1));
  655. cr ();
  656. cr ();
  657. print (x, y);
  658. print ("a");
  659. print ("currentpoint");
  660. print ("currentpoint");
  661. print ("translate");
  662. print (as_string (sc_x));
  663. print (as_string (sc_y));
  664. print ("scale");
  665. print ("neg");
  666. print ("exch");
  667. print ("neg");
  668. print ("exch");
  669. print ("translate");
  670. print (x, y);
  671. print ("a");
  672. cr ();
  673. /* Black Black 248 3155 a currentpoint currentpoint translate
  674. 0.37114 0.37114 scale neg exch neg exch translate 248 3155 a */
  675. print ("@beginspecial");
  676. print (as_string (x1));
  677. print ("@llx");
  678. print (as_string (y1));
  679. print ("@lly");
  680. print (as_string (x2));
  681. print ("@urx");
  682. print (as_string (y2));
  683. print ("@ury");
  684. print (as_string (10*(x2-x1)));
  685. print ("@rwi");
  686. print ("@clip");
  687. print ("@setspecial");
  688. cr ();
  689. /* @beginspecial 0 @llx 0 @lly 613.291260 @urx 613.291260 @ury 6110 @rwi
  690. @clip @setspecial */
  691. string ps_image= ps_load (u);
  692. string imtext= is_ramdisc (u)? "inline image": as_string (u);
  693. body << "%%BeginDocument: " << imtext << "\n";
  694. body << ps_image; // incorporate_postscript (ps_image);
  695. body << "%%EndDocument";
  696. cr ();
  697. print ("@endspecial");
  698. print (x, y);
  699. print ("a");
  700. print ("currentpoint");
  701. print ("currentpoint");
  702. print ("translate");
  703. print (as_string (1/sc_x));
  704. print (as_string (1/sc_y));
  705. print ("scale");
  706. print ("neg");
  707. print ("exch");
  708. print ("neg");
  709. print ("exch");
  710. print ("translate");
  711. print (x, y);
  712. print ("a");
  713. cr ();
  714. cr ();
  715. /* @endspecial 248 3155 a currentpoint currentpoint translate
  716. 1 0.37114 div 1 0.37114 div scale neg exch neg exch translate
  717. 248 3155 a 660 3073 a ... */
  718. (void) w; (void) h;
  719. }
  720. void
  721. printer_rep::fetch (SI x1, SI y1, SI x2, SI y2, renderer ren, SI x, SI y) {
  722. (void) x1; (void) y1; (void) x2; (void) y2;
  723. (void) ren; (void) x; (void) y;
  724. }
  725. void
  726. printer_rep::new_shadow (renderer& ren) {
  727. (void) ren;
  728. }
  729. void
  730. printer_rep::delete_shadow (renderer& ren) {
  731. (void) ren;
  732. }
  733. void
  734. printer_rep::get_shadow (renderer ren, SI x1, SI y1, SI x2, SI y2) {
  735. (void) ren; (void) x1; (void) y1; (void) x2; (void) y2;
  736. }
  737. void
  738. printer_rep::put_shadow (renderer ren, SI x1, SI y1, SI x2, SI y2) {
  739. (void) ren; (void) x1; (void) y1; (void) x2; (void) y2;
  740. }
  741. void
  742. printer_rep::apply_shadow (SI x1, SI y1, SI x2, SI y2) {
  743. (void) x1; (void) y1; (void) x2; (void) y2;
  744. }
  745. void
  746. printer_rep::anchor (string label, SI x, SI y) {
  747. string s = "(";
  748. s = s << prepare_text (label) << ") cvn";
  749. if (linelen>0) cr ();
  750. print ("[ /Dest");
  751. print (s);
  752. print ("/View [/XYZ");
  753. print (x, y);
  754. print ("null] /DEST pdfmark");
  755. cr ();
  756. }
  757. void
  758. printer_rep::href (string label, SI x1, SI y1, SI x2, SI y2) {
  759. if (linelen>0) cr ();
  760. print ("[");
  761. if (starts (label, "#")) {
  762. print ("/Dest");
  763. print ("(" * prepare_text (label) * ") cvn");
  764. }
  765. else {
  766. print ("/Action");
  767. print ("<< /Subtype /URI /URI (" * prepare_text (label) * ") >>");
  768. }
  769. print ("/Rect [");
  770. print (x1 - 5*PIXEL, y1 - 10*PIXEL);
  771. print (x2 + 5*PIXEL, y2 + 10*PIXEL);
  772. print ("]");
  773. print ("/Border [16 16 1 [3 10]] /Color [0.75 0.5 1.0]");
  774. print ("/Subtype /Link");
  775. print ("/ANN pdfmark");
  776. cr ();
  777. }
  778. /******************************************************************************
  779. * user interface
  780. ******************************************************************************/
  781. renderer
  782. printer (url ps_file_name, int dpi, int nr_pages,
  783. string page_type, bool landscape, double paper_w, double paper_h)
  784. {
  785. page_type= as_string (call ("correct-paper-size", object (page_type)));
  786. return tm_new<printer_rep> (ps_file_name, dpi, nr_pages,
  787. page_type, landscape, paper_w, paper_h);
  788. }