vul_psfile.cxx
Go to the documentation of this file.
1 // This is core/vul/vul_psfile.cxx
2 #include <cmath>
3 #include <iostream>
4 #include <iomanip>
5 #include <algorithm>
6 #include "vul_psfile.h"
7 //:
8 // \file
9 
10 #ifdef _MSC_VER
11 # include <vcl_msvc_warnings.h>
12 #endif
13 #include <cassert>
14 
15 #define RANGE(a,b,c) { if ((a) < (b)) (a) = b; if ((a) > (c)) (a) = c; }
16 #define in_range(a) ((a) < 0x100)
17 #define Hex4bit(a) ((char)(((a)<=9) ? ((a)+'0') : ((a) - 10 + 'a')))
18 
19 static const float PIX2INCH = 72.0f;
20 static bool debug = true;
21 
22 // sizes of pages in inches
23 static double paper_size[8][2] = {
24  { 8.500, 11.000}, // US NORMAL
25  { 8.268, 11.693}, // A4 210mm x 297mm
26  { 7.205, 10.118}, // B5 183mm x 257mm
27  {11.693, 16.535}, // A3 297mm x 420mm
28  { 8.500, 14.000}, // US LEGAL
29  {11.000, 17.000}, // B-size
30  { 3.875, 4.875}, // 4 by 5
31  { 0.945, 1.417} // 35mm (24x36)
32 };
33 
34 // size of l+r margin and t+b margin. image is centered
35 static double margins[8 ][2] = {
36  { 1.000, 1.000}, // US NORMAL
37  { 1.000, 1.000}, // A4
38  { 1.000, 1.000}, // B5
39  { 1.000, 1.000}, // A3
40  { 1.000, 1.000}, // US LEGAL
41  { 1.000, 1.000}, // B-size
42  { 0.275, 0.275}, // 4 by 5
43  { 0.078, 0.078} // 35mm (24x36)
44 };
45 
46 // min and max value for PostScript paper size
47 static float ps_minimum = 0.1f;
48 static float ps_maximum = 8.f;
49 
50 static const std::streampos HEADER_START(-1);
51 
52 //-----------------------------------------------------------------------------
53 //: Default constructor.
54 //-----------------------------------------------------------------------------
55 vul_psfile::vul_psfile(char const* f, bool dbg)
56  : output_filestream(f),
57  fg_r(0), fg_g(0), fg_b(0),
58  bg_r(1), bg_g(1), bg_b(1),
59  line_width_(1),
60  scale_x(1.f), scale_y(1.f),
61  ox(0), oy(0), iw(0), ih(0),
62  iwf(1.0), ihf(1.0),
63  psizex(8.5), psizey(11),
64  pos_inx(4.25), pos_iny(5.5),
65  width(0), height(0),
66  filename(f),
67  printer_paper_type(vul_psfile::US_NORMAL),
68  printer_paper_orientation(vul_psfile::PORTRAIT),
69  printer_paper_layout(vul_psfile::CENTER),
70  reduction_factor(1),
71  doneps(false),
72  min_x(1000), min_y(1000),
73  max_x(-1000), max_y(-1000),
74  box_width(0), box_height(0),
75  translate_pos(-1L),
76  sobj_t_pos(-1L),
77  header_pos(HEADER_START),
78  graphics_prolog_exists(false),
79  exist_image(false),
80  exist_objs (false)
81 {
82  debug = dbg;
83  if (debug) std::cout << "vul_psfile::vul_psfile\n";
85 }
86 
87 //-----------------------------------------------------------------------------
88 //: Destructor
89 //-----------------------------------------------------------------------------
91 {
92  if (debug) std::cout << "vul_psfile::~vul_psfile\n";
94  if (!doneps)
95  done();
96 }
97 
98 
99 //-----------------------------------------------------------------------------
100 //: Rewrite output bounding box parameters.
101 //-----------------------------------------------------------------------------
103 {
104  std::streampos temp_pos;
105  temp_pos = output_filestream.tellp();
106 
107  if (exist_image)
108  {
109  // for image part
112  }
113  if (exist_objs)
114  {
115  // For Object part.
118  }
119 
120  // reset Bounding Box parameters (the fourth line).
123  output_filestream.seekp(temp_pos);
124 }
126 //-----------------------------------------------------------------------------
127 //: Recalculate bounding box and scale x and y (if necessary).
128 //-----------------------------------------------------------------------------
130 {
131  box_width = max_x - min_x;
132  box_height = max_y - min_y;
133 
135  {
136  psizex = paper_size[printer_paper_type][1];
137  psizey = paper_size[printer_paper_type][0];
138  }
139  else
140  {
141  psizex = paper_size[printer_paper_type][0];
142  psizey = paper_size[printer_paper_type][1];
143  }
144 
146  {
147  double hsx = box_width / PIX2INCH * scale_x * .5;
148  double hsy = box_height / PIX2INCH * scale_y * .5;
149 
150  // from xv xvps.c subroutine: centerimage
151  pos_inx = psizex*.5 - hsx;
152  pos_iny = psizey*.5 - hsy;
153 
154  // make sure 'center' of image is still on page
155  RANGE(pos_inx, -hsx, psizex-hsx);
156  RANGE(pos_iny, -hsy, psizey-hsy);
157 
158  // round to integer .001ths of an inch
159  pos_inx = std::floor(pos_inx * 1000.0 + 0.5) * .001;
160  pos_iny = std::floor(pos_iny * 1000.0 + 0.5) * .001;
161  }
163  {
164  double hsx = psizex - margins[printer_paper_type][0];
165  double hsy = psizey - margins[printer_paper_type][1];
166 
167  // avoid division by 0:
168  if (box_width == 0) box_width = 1;
169  if (box_height == 0) box_height = 1;
170 
171  // choose the smaller scaling factor
172  scale_x = scale_y = (float)std::min(hsx/box_width, hsy/box_height) * PIX2INCH;
173 
174  RANGE(scale_x,ps_minimum,ps_maximum);
175  RANGE(scale_y,ps_minimum,ps_maximum);
176 
177  pos_inx = psizex*.5 - box_width / PIX2INCH * scale_x *.5;
178  pos_iny = psizey*.5 - box_height/ PIX2INCH * scale_y *.5;
179 
180  // round to integer .001ths of an inch
181  pos_inx = std::floor(pos_inx * 1000.0 + 0.5) * .001;
182  pos_iny = std::floor(pos_iny * 1000.0 + 0.5) * .001;
183  }
184 
185  // printed image will have size iw,ih (in picas)
186  if (exist_image)
187  {
188  iwf = width * scale_x; iw = int(iwf + 0.5);
189  ihf = height * scale_y; ih = int(ihf + 0.5);
190  }
191  if (exist_objs)
192  {
193  iw = int(box_width * scale_x + 0.5);
194  ih = int(box_height * scale_y + 0.5);
195  }
196 
197  // compute offset to bottom-left of image (in picas)
198  ox = int(pos_inx*PIX2INCH+0.5);
199  oy = int(pos_iny*PIX2INCH+0.5);
200 
201  if (debug) std::cout << "vul_psfile::compute_bounding_box, box_width = "
202  << box_width << ", box_height = " << box_height << '\n';
203 }
204 
205 //-----------------------------------------------------------------------------
206 //: Set Bounding Box Min and Max x, y.
207 //-----------------------------------------------------------------------------
208 void vul_psfile::set_min_max_xy(float xx, float yy)
209 {
210  int x = int(xx + 0.5);
211  int y = int(yy + 0.5);
212  if (x < min_x) min_x = x;
213  if (y < min_y) min_y = y;
214  if (x > max_x) max_x = x;
215  if (y > max_y) max_y = y;
216 }
217 
218 //-----------------------------------------------------------------------------
219 //: Set Bounding Box Min and Max x, y.
220 //-----------------------------------------------------------------------------
221 void vul_psfile::set_min_max_xy(int x, int y)
222 {
223  if (x < min_x) min_x = x;
224  if (y < min_y) min_y = y;
225  if (x > max_x) max_x = x;
226  if (y > max_y) max_y = y;
227 }
228 
229 //-----------------------------------------------------------------------------
230 //: Write 8 bit grey scale image.
231 //-----------------------------------------------------------------------------
232 void vul_psfile::print_greyscale_image(const unsigned char* buffer, int sizex, int sizey)
233 {
234  if (debug)
235  std::cout << "vul_psfile::print_greyscale_image, width = " << sizex
236  << ", height = " << sizey << ", reduction_factor = "
237  << reduction_factor << '\n';
238 
239  exist_image = true;
240  width = sizex;
241  height = sizey;
242  set_parameters(sizex,sizey);
244 
245  // reduction factor should not be an expansion factor ...
246  if (reduction_factor < 1)
247  reduction_factor = 1;
248 
249  int new_width = (int)std::ceil(sizex/(double)reduction_factor); // round up
250  int new_height= (int)std::ceil(sizey/(double)reduction_factor);
251 
253  << "\n%%Page: 1 1\n\n% remember original state\n/origstate save def\n"
254  << "\n% build a temporary dictionary\n20 dict begin\n\n"
255  << "% define string to hold a scanline's worth of data\n"
256  << "/pix " << new_width << " string def\n";
257 
260  << "% print in landscape mode\n90 rotate 0 " << int(-psizey*PIX2INCH) << " translate\n\n";
261  output_filestream << "% lower left corner\n";
264 
266  << new_width << ' ' << new_height << " 8 % dimensions of data\n"
267  << '[' << new_width << " 0 0 -" << new_height << " 0 " << new_height
268  << "] % mapping matrix\n{currentfile pix readhexstring pop}\nimage\n\n";
269  constexpr int linesize = 72;
270 
271  // write image data to output PostScript file
272  for (int j=0; j<new_height; j++)
273  {
274  int countrow = 0;
275  for (int i = 0; i < new_width; i++)
276  {
277  int index;
278 
279  if (reduction_factor == 1)
280  index = int(*(buffer + width * j + i));
281  else // Reduce resolution of image if necessary
282  {
283  int pixel_number= (width * j + i) * reduction_factor;
284  index=0;
285  int number_of_pixels_sampled=0;
286  for (int m=0; m < reduction_factor;m++)
287  for (int n=0; n < reduction_factor;n++)
288  if (i*reduction_factor+m < width && j*reduction_factor+n < height)
289  {
290  index += int(*(buffer + (pixel_number+m+n*width)));
291  ++number_of_pixels_sampled;
292  }
293  if(number_of_pixels_sampled == 0)
294  {
295  std::cerr << "ERROR: Division by 0! " << __FILE__ << __LINE__ << std::endl;
296  throw 0;
297  }
298  index/=number_of_pixels_sampled; // Average the pixel intensity value.
299  }
300 
301  // write hex pixel value
302  if (in_range(index))
303  {
304  char pixel[3];
305  auto low4 = (unsigned char) (index & 0x000f);
306  auto high4 = (unsigned char) ((index & 0x00f0) >> 4);
307  pixel[0] = Hex4bit(high4);
308  pixel[1] = Hex4bit(low4);
309  pixel[2] = '\0';
310  output_filestream << pixel;
311  }
312  else
313  std::cout << " index out of range: " << index << '\n';
314 
315  countrow+=2;
316  if (countrow >= linesize)
317  {
318  countrow = 0;
319  output_filestream << '\n';
320  }
321  }
322  output_filestream << '\n';
323  }
324  output_filestream << "% stop using temporary dictionary\nend\n\n"
325  << "% restore original state\norigstate restore\n\n";
326 }
327 
328 //-----------------------------------------------------------------------------
329 //: Write 24 bit colour image.
330 //-----------------------------------------------------------------------------
331 void vul_psfile::print_color_image(const unsigned char* data, int sizex, int sizey)
332 {
333  if (debug)
334  std::cout << "vul_psfile::print_color_image, width = " << sizex
335  << ", height = " << sizey << ", reduction_factor = "
336  << reduction_factor << '\n';
337 
338  constexpr int bytes_per_pixel = 3;
339  exist_image = true;
340  width = sizex;
341  height = sizey;
342  set_parameters(sizex,sizey);
344 
345  // reduction factor should not be an expansion factor ...
346  if (reduction_factor < 1)
347  reduction_factor = 1;
348 
349  int new_width = (int)std::ceil(sizex/(double)reduction_factor); // round up
350  int new_height= (int)std::ceil(sizey/(double)reduction_factor);
351 
352  // This part uses xv outfile as a reference:
354  << "\n%%Page: 1 1\n\n"
355  << "% remember original state\n"
356  << "/origstate save def\n\n"
357  << "% build a temporary dictionary\n"
358  << "20 dict begin\n\n"
359  << "% define string to hold a scanline's worth of data\n"
360  << "/pix " << 3 * new_width << " string def\n\n"
361  << "% define space for color conversions\n"
362  << "/grays " << new_width << " string def % space for gray scale line\n"
363  << "/npixls 0 def\n"
364  << "/rgbindx 0 def\n\n";
365 
368  << "% print in landscape mode\n90 rotate 0 " << int(-psizey*PIX2INCH) << " translate\n\n";
369  output_filestream << "% lower left corner\n";
372 
374  << "\n% define 'colorimage' if it isn't defined\n"
375  << "% ('colortogray' and 'mergeprocs' come from xwd2ps via xgrab)\n"
376  << "/colorimage where % do we know about 'colorimage'?\n"
377  << " { pop } % yes: pop off the 'dict' returned\n"
378  << " { % no: define one\n"
379  << " /colortogray { % define an RGB->I function\n"
380  << " /rgbdata exch store % call input 'rgbdata'\n"
381  << " rgbdata length 3 idiv\n"
382  << " /npixls exch store\n"
383  << " /rgbindx 0 store\n"
384  << " 0 1 npixls 1 sub {\n"
385  << " grays exch\n"
386  << " rgbdata rgbindx get 20 mul % Red\n"
387  << " rgbdata rgbindx 1 add get 32 mul % Green\n"
388  << " rgbdata rgbindx 2 add get 12 mul % Blue\n"
389  << " add add 64 idiv % I = .3125 R + .5 G + .1875 B\n"
390  << " put\n"
391  << " /rgbindx rgbindx 3 add store\n"
392  << " } for\n"
393  << " grays 0 npixls getinterval\n"
394  << " } bind def\n\n"
395  << " % Utility procedure for colorimage operator.\n"
396  << " % This procedure takes two procedures off the stack and merges them into a single procedure.\n\n"
397  << " /mergeprocs {\n"
398  << " dup length\n"
399  << " 3 -1 roll\n"
400  << " dup\n"
401  << " length\n"
402  << " dup\n"
403  << " 5 1 roll\n"
404  << " 3 -1 roll\n"
405  << " add\n"
406  << " array cvx\n"
407  << " dup\n"
408  << " 3 -1 roll\n"
409  << " 0 exch\n"
410  << " putinterval\n"
411  << " dup\n"
412  << " 4 2 roll\n"
413  << " putinterval\n"
414  << " } bind def\n\n"
415  << " /colorimage {\n"
416  << " pop pop % remove 'false 3' operands\n"
417  << " {colortogray} mergeprocs\n"
418  << " image\n"
419  << " } bind def\n"
420  << " } ifelse % end of 'false' case\n\n"
421  << new_width << ' ' << new_height << " 8 % dimensions of data\n"
422  << '[' << new_width << " 0 0 -" << new_height << " 0 " << new_height << "] % mapping matrix\n"
423  << "{currentfile pix readhexstring pop}\n"
424  << "false 3 colorimage\n\n";
425 
426  // write image data into PostScript file.
427  constexpr int linesize = 72;
428 
429  // extract RGB data from pixel value and write it to output file
430  for (int j = 0; j < new_height;j++)
431  {
432  int countrow = 0;
433  for (int i = 0; i < new_width; i++)
434  {
435  for (int c = 0; c < bytes_per_pixel; ++c)
436  {
437  // get RGB hex index.
438  int index;
439 
440  if (reduction_factor == 1)
441  index = int(*(data + (sizex*j+i) * bytes_per_pixel + c));
442  else // Reduce image if necessary
443  {
444  int pixel_number= (sizex*j+i) * bytes_per_pixel * reduction_factor + c;
445  index=0;
446  int number_of_pixels_sampled=0;
447  for (int m=0; m < reduction_factor;m++)
448  for (int n=0; n < reduction_factor;n++)
449  if (i*reduction_factor+m < sizex && j*reduction_factor+n < sizey)
450  {
451  index += int(*(data+(pixel_number+(m+n*sizex)*bytes_per_pixel)));
452  ++number_of_pixels_sampled;
453  }
454  if(number_of_pixels_sampled == 0)
455  {
456  std::cerr << "ERROR: Division by 0! " << __FILE__ << __LINE__ << std::endl;
457  throw 0;
458  }
459  index/=number_of_pixels_sampled; // average the pixel intensity
460  }
461 
462  // write RGC hex.
463  if (in_range(index))
464  {
465  char pixel[3];
466  auto low4 = (unsigned char) (index & 0x000f);
467  auto high4 = (unsigned char) ((index & 0x00f0) >> 4);
468  pixel[0] = Hex4bit(high4);
469  pixel[1] = Hex4bit(low4);
470  pixel[2] = '\0';
471  output_filestream << pixel;
472  }
473  else
474  std::cout << " index out of range: " << index << '\n';
475 
476  countrow+=2;
477  if (countrow >= linesize)
478  {
479  countrow = 0;
480  output_filestream << '\n';
481  }
482  }
483  }
484  output_filestream << '\n';
485  }
486 
487  output_filestream << "% stop using temporary dictionary\nend\n\n"
488  << "% restore original state\norigstate restore\n\n";
489 }
490 
491 //-----------------------------------------------------------------------------
492 //: Set graphic coordinate (translate and rotate to local coordinate).
493 //-----------------------------------------------------------------------------
495 {
497  output_filestream << "% print in landscape mode\n90 rotate 0 "
498  << int(-psizey*PIX2INCH) << " translate\n\n";
499 
501  // save streampos so we can come back and modify it.
502  sobj_t_pos = output_filestream.tellp();
503  // move relative coordinate to local origin and set up scale factor.
505 }
506 
507 //-----------------------------------------------------------------------------
508 //: Set Image translate and scale.
509 //-----------------------------------------------------------------------------
511 {
512  int scale_height = int(height* scale_y);
513  int scale_min_x = int(min_x * scale_x);
514  int scale_max_y = int(max_y * scale_y);
515 
516  if (debug)
517  std::cout << "vul_psfile::image_translate_and_scale, scale_height= "
518  << scale_height << ", scale_min_x = " << scale_min_x
519  << ", scale_max_y = " << scale_max_y << '\n';
521  output_filestream << std::setw(6) << ox - scale_min_x << ' '
522  << std::setw(6) << oy + scale_max_y - scale_height << " translate\n"
523  << "\n% size of image (on paper, in 1/72inch coordinates)\n"
524  << std::setw(9) << iwf << ' '
525  << std::setw(9) << ihf << " scale\n\n";
526 }
527 
528 //-----------------------------------------------------------------------------
529 //: Set object translate and scale.
530 //-----------------------------------------------------------------------------
532 {
533  int scale_height = int(box_height * scale_y);
534  int scale_min_x = int(min_x * scale_x);
535  int scale_min_y = int(min_y * scale_y);
536  // round to integer .01ths
537  scale_x = std::floor(scale_x * 100.0f + 0.5f) * .01f;
538  scale_y = std::floor(scale_y * 100.0f + 0.5f) * .01f;
539 
540  // move origin
541  output_filestream << std::setw(6) << ox - scale_min_x << ' '
542  << std::setw(6) << oy + scale_height + scale_min_y << " translate\n"
543  << std::setw(9) << scale_x << ' ' << std::setw(9) << -scale_y << " scale\n\n"
544  << "/originalCTM matrix currentmatrix def\n";
545 }
546 
547 //-----------------------------------------------------------------------------
548 //: Set ox, oy , iw, ih, iwf, ihf parameters for PostScript file use.
549 //-----------------------------------------------------------------------------
550 bool vul_psfile::set_parameters(int sizex,int sizey)
551 {
552  width = sizex;
553  height = sizey;
554  // avoid division by 0 or other fancy things later on:
555  assert (width > 0 && height > 0);
556 
557  set_min_max_xy(0,0);
560 
561  return true;
562 }
563 
564 //-----------------------------------------------------------------------------
565 //: PostScript file header.
566 //-----------------------------------------------------------------------------
568 {
569  if (header_pos != HEADER_START)
570  {
571  std::cerr << "vul_psfile: Header already set to " << long(header_pos) << '\n';
572  return;
573  }
574 
576  << "%!PS-Adobe-2.0 EPSF-2.0\n%%Title: " << filename.c_str()
577  << "\n%%Creator: vul_psfile\n%%BoundingBox: ";
578 
579  header_pos = output_filestream.tellp();
581 }
582 
583 
584 //-----------------------------------------------------------------------------
585 //: Reset PostScript header file
586 //-----------------------------------------------------------------------------
588 {
591  << std::setw(6) << int(pos_iny*PIX2INCH+0.5) << ' '
592  << std::setw(6) << int(pos_inx*PIX2INCH+0.5) << ' '
593  << std::setw(6) << int(pos_iny*PIX2INCH+0.5)+ih << ' '
594  << std::setw(6) << int(pos_inx*PIX2INCH+0.5)+iw << '\n';
595  else
597  << std::setw(6) << ox << ' '
598  << std::setw(6) << oy << ' '
599  << std::setw(6) << ox+iw << ' '
600  << std::setw(6) << oy+ih << '\n';
601  output_filestream << "%%Pages: 1\n%%DocumentFonts:\n%%EndComments\n";
602 }
603 
604 //-----------------------------------------------------------------------------
605 //: Utility program used in point(), line(), ellipse() and circle()
606 //-----------------------------------------------------------------------------
607 void vul_psfile::sobj_rgb_params(char const* obj_str, bool filled)
608 {
611  << "\nBegin %I " << obj_str << "\n2 0 0 [] 0 SetB\n"
612  << fg_r << ' ' << fg_g << ' ' << fg_b << " SetCFg\n"
613  << bg_r << ' ' << bg_g << ' ' << bg_b << " SetCBg\n"
614  << line_width_ << " setlinewidth\n"
615  << (filled ? "0": "none") << " SetP %I p n\n";
616 }
617 
618 //-----------------------------------------------------------------------------
619 //: Add a line between the given points to the Postscript file.
620 //-----------------------------------------------------------------------------
621 void vul_psfile::line(float x1, float y1, float x2, float y2)
622 {
623  // set up bounding box.
624  set_min_max_xy(x1,y1);
625  set_min_max_xy(x2,y2);
627 
629  sobj_rgb_params("Line", false);
630 
631  output_filestream << int(x1) << ' ' << int(y1) << ' '
632  << int(x2) << ' ' << int(y2) << " Line\nEnd\n";
633 }
634 
635 //-----------------------------------------------------------------------------
636 //: Add a point at the given coordinates to the Postscript file.
637 //-----------------------------------------------------------------------------
638 void vul_psfile::point(float x, float y, float point_size)
639 {
641  set_min_max_xy(x,y);
643 
644  this->sobj_rgb_params("Point", true);
645 
646  point_size /= 2;
647  output_filestream << x << ' ' << y << ' ' << point_size << ' ' << point_size << " Elli\nEnd\n";
648 }
649 
650 //-----------------------------------------------------------------------------
651 //: Add an ellipse to the Postscript file.
652 //-----------------------------------------------------------------------------
653 void vul_psfile::ellipse(float x, float y, float a_axis, float b_axis, int angle)
654 {
655  #ifndef PI // should already be defined in math.h - PVR
656  #define PI 3.14159265358979323846
657  #endif
658  const double radsperdeg = PI/180.0;
659 
660  set_min_max_xy(int(x+a_axis*std::cos(angle*radsperdeg) + 0.5),
661  int(y+a_axis*std::sin(angle*radsperdeg) + 0.5) );
662  set_min_max_xy(int(x-a_axis*std::cos(angle*radsperdeg) + 0.5),
663  int(y-a_axis*std::sin(angle*radsperdeg) + 0.5) );
665 
667  sobj_rgb_params("Ellipse", false);
668  if (angle)
669  output_filestream << (int)x << ' ' << (int)y << " translate\n"
670  << -angle << " rotate\n0 0 " << (int)a_axis << ' '
671  << (int)b_axis << " Elli\nEnd\n";
672  else
673  output_filestream << (int)x << ' ' << (int)y << ' '
674  << (int)a_axis << ' ' << (int)b_axis << " Elli\nEnd\n";
675 }
676 
677 //-----------------------------------------------------------------------------
678 //: Add a circle with the given centre point and radius to the Postscript file.
679 //-----------------------------------------------------------------------------
680 void vul_psfile::circle(float x, float y, float radius)
681 {
682  // set up bounding box
683  set_min_max_xy(x+radius,y);
684  set_min_max_xy(x-radius,y);
685  set_min_max_xy(x,y+radius);
686  set_min_max_xy(x,y-radius);
688 
690  sobj_rgb_params("Circle", false);
691  ellipse(x,y,radius,radius);
692  output_filestream << "End\n";
693 }
694 
695 //-----------------------------------------------------------------------------
696 //: the defined procedure for PostScript script use.
697 //-----------------------------------------------------------------------------
699 {
701  return;
702  exist_objs = true;
704  << "\n\n%%BeginTargetjrPrologue\n"
705  << "/arrowhead {\n"
706  << " 0 begin\n"
707  << " transform originalCTM itransform\n"
708  << " /taily exch def\n"
709  << " /tailx exch def\n"
710  << " transform originalCTM itransform\n"
711  << " /tipy exch def\n"
712  << " /tipx exch def\n"
713  << " /dy tipy taily sub def\n"
714  << " /dx tipx tailx sub def\n"
715  << " /angle dx 0 ne dy 0 ne or { dy dx atan } { 90 } ifelse def\n"
716  << " gsave\n"
717  << " originalCTM setmatrix\n"
718  << " tipx tipy translate\n"
719  << " angle rotate\n"
720  << " newpath\n"
721  << " arrowHeight neg arrowWidth 2 div moveto\n"
722  << " 0 0 lineto\n"
723  << " arrowHeight neg arrowWidth 2 div neg lineto\n"
724  << " patternNone not {\n"
725  << " originalCTM setmatrix\n"
726  << " /padtip arrowHeight 2 exp 0.25 arrowWidth 2 exp mul add sqrt brushWidth mul\n"
727  << " arrowWidth div def\n"
728  << " /padtail brushWidth 2 div def\n"
729  << " tipx tipy translate\n"
730  << " angle rotate\n"
731  << " padtip 0 translate\n"
732  << " arrowHeight padtip add padtail add arrowHeight div dup scale\n"
733  << " arrowheadpath\n"
734  << " ifill\n"
735  << " } if\n"
736  << " brushNone not {\n"
737  << " originalCTM setmatrix\n"
738  << " tipx tipy translate\n"
739  << " angle rotate\n"
740  << " arrowheadpath\n"
741  << " istroke\n"
742  << " } if\n"
743  << " grestore\n"
744  << " end\n"
745  << "} dup 0 9 dict put def\n\n"
746  << "/arrowheadpath {\n"
747  << " newpath\n"
748  << " arrowHeight neg arrowWidth 2 div moveto\n"
749  << " 0 0 lineto\n"
750  << " arrowHeight neg arrowWidth 2 div neg lineto\n"
751  << "} def\n\n"
752  << "/leftarrow {\n"
753  << " 0 begin\n"
754  << " y exch get /taily exch def\n"
755  << " x exch get /tailx exch def\n"
756  << " y exch get /tipy exch def\n"
757  << " x exch get /tipx exch def\n"
758  << " brushLeftArrow { tipx tipy tailx taily arrowhead } if\n"
759  << " end\n"
760  << "} dup 0 4 dict put def\n\n"
761  << "/rightarrow {\n"
762  << " 0 begin\n"
763  << " y exch get /tipy exch def\n"
764  << " x exch get /tipx exch def\n"
765  << " y exch get /taily exch def\n"
766  << " x exch get /tailx exch def\n"
767  << " brushRightArrow { tipx tipy tailx taily arrowhead } if\n"
768  << " end\n"
769  << "} dup 0 4 dict put def\n\n"
770  << "%%EndTargetjrPrologue\n\n"
771  << "/arrowHeight 10 def\n"
772  << "/arrowWidth 5 def\n\n"
773  << "/TargetjrDict 50 dict def\n"
774  << "TargetjrDict begin\n\n"
775  << "/none null def\n"
776  << "/numGraphicParameters 17 def\n"
777  << "/stringLimit 65535 def\n\n"
778  << "/Begin { save numGraphicParameters dict begin } def\n\n"
779  << "/End { end restore } def\n\n"
780  << "/SetB { % width leftarrow rightarrow DashArray DashOffset SetB\n"
781  << " dup type /nulltype eq {\n"
782  << " pop\n"
783  << " false /brushRightArrow idef\n"
784  << " false /brushLeftArrow idef\n"
785  << " true /brushNone idef\n"
786  << " } {\n"
787  << " /brushDashOffset idef\n"
788  << " /brushDashArray idef\n"
789  << " 0 ne /brushRightArrow idef\n"
790  << " 0 ne /brushLeftArrow idef\n"
791  << " /brushWidth idef\n"
792  << " false /brushNone idef\n"
793  << " } ifelse\n"
794  << "} def\n\n"
795  << "/SetCFg { /fgblue idef /fggreen idef /fgred idef } def\n\n"
796  << "/SetCBg { /bgblue idef /bggreen idef /bgred idef } def\n\n"
797  << "/SetF { /printSize idef /printFont idef } def\n\n"
798  << "/SetP { % string -1 SetP OR gray SetP\n"
799  << " dup type /nulltype eq { pop true /patternNone idef }\n"
800  << " {\n"
801  << " dup -1 eq { /patternGrayLevel idef /patternString idef }\n"
802  << " { /patternGrayLevel idef } ifelse\n"
803  << " false /patternNone idef\n"
804  << " } ifelse\n"
805  << "} def\n\n"
806  << "/BSpl {\n"
807  << " 0 begin\n"
808  << " storexyn\n"
809  << " newpath\n"
810  << " n 1 gt {\n"
811  << " 0 0 0 0 0 0 1 1 true subspline\n"
812  << " n 2 gt {\n"
813  << " 0 0 0 0 1 1 2 2 false subspline\n"
814  << " 1 1 n 3 sub { /i exch def i 1 sub dup i dup i 1 add dup i 2 add dup false subspline } for\n"
815  << " n 3 sub dup n 2 sub dup n 1 sub dup 2 copy false subspline\n"
816  << " } if\n"
817  << " n 2 sub dup n 1 sub dup 2 copy 2 copy false subspline\n"
818  << " patternNone not brushLeftArrow not brushRightArrow not and and { ifill } if\n"
819  << " brushNone not { istroke } if\n"
820  << " 0 0 1 1 leftarrow\n"
821  << " n 2 sub dup n 1 sub dup rightarrow\n"
822  << " } if\n"
823  << " end\n"
824  << "} dup 0 4 dict put def\n\n"
825  << "/Circ { newpath 0 360 arc patternNone not { ifill } if brushNone not { istroke } if } def\n\n"
826  << "/CBSpl {\n"
827  << " 0 begin\n"
828  << " dup 2 gt {\n"
829  << " storexyn\n"
830  << " newpath\n"
831  << " n 1 sub dup 0 0 1 1 2 2 true subspline\n"
832  << " 1 1 n 3 sub { /i exch def i 1 sub dup i dup i 1 add dup i 2 add dup false subspline } for\n"
833  << " n 3 sub dup n 2 sub dup n 1 sub dup 0 0 false subspline\n"
834  << " n 2 sub dup n 1 sub dup 0 0 1 1 false subspline\n"
835  << " patternNone not { ifill } if\n"
836  << " brushNone not { istroke } if\n"
837  << " } { Poly } ifelse\n"
838  << " end\n"
839  << "} dup 0 4 dict put def\n"
840  << "/Elli {\n"
841  << " 0 begin\n"
842  << " newpath 4 2 roll translate scale\n"
843  << " 0 0 1 0 360 arc\n"
844  << " patternNone not { ifill } if\n"
845  << " brushNone not { istroke } if\n"
846  << " end\n"
847  << "} dup 0 1 dict put def\n\n"
848  << "/Line {\n"
849  << " 0 begin\n"
850  << " 2 storexyn\n"
851  << " newpath\n"
852  << " x 0 get y 0 get moveto\n"
853  << " x 1 get y 1 get lineto\n"
854  << " brushNone not { istroke } if\n"
855  << " 0 0 1 1 leftarrow\n"
856  << " 0 0 1 1 rightarrow\n"
857  << " end\n"
858  << "} dup 0 4 dict put def\n\n"
859  << "/MLine {\n"
860  << " 0 begin\n"
861  << " storexyn\n"
862  << " newpath\n"
863  << " n 1 gt {\n"
864  << " x 0 get y 0 get moveto\n"
865  << " 1 1 n 1 sub { /i exch def x i get y i get lineto } for\n"
866  << " patternNone not brushLeftArrow not brushRightArrow not and and { ifill } if\n"
867  << " brushNone not { istroke } if\n"
868  << " 0 0 1 1 leftarrow\n"
869  << " n 2 sub dup n 1 sub dup rightarrow\n"
870  << " } if\n"
871  << " end\n"
872  << "} dup 0 4 dict put def\n\n"
873  << "/Poly {\n"
874  << " 3 1 roll\n"
875  << " newpath moveto -1 add { lineto } repeat closepath\n"
876  << " patternNone not { ifill } if\n"
877  << " brushNone not { istroke } if\n"
878  << "} def\n\n"
879  << "/Rect {\n"
880  << " 0 begin\n"
881  << " /t exch def\n"
882  << " /r exch def\n"
883  << " /b exch def\n"
884  << " /l exch def\n"
885  << " newpath\n"
886  << " l b moveto\n"
887  << " l t lineto\n"
888  << " r t lineto\n"
889  << " r b lineto\n"
890  << " closepath\n"
891  << " patternNone not { ifill } if\n"
892  << " brushNone not { istroke } if\n"
893  << " end\n"
894  << "} dup 0 4 dict put def\n\n"
895  << "/Text { ishow } def\n\n"
896  << "/idef { dup where { pop pop pop } { exch def } ifelse } def\n\n"
897  << "/ifill {\n"
898  << " 0 begin\n"
899  << " gsave\n"
900  << " patternGrayLevel -1 ne {\n"
901  << " fgred bgred fgred sub patternGrayLevel mul add\n"
902  << " fggreen bggreen fggreen sub patternGrayLevel mul add\n"
903  << " fgblue bgblue fgblue sub patternGrayLevel mul add setrgbcolor\n"
904  << " eofill\n"
905  << " } {\n"
906  << " eoclip\n"
907  << " originalCTM setmatrix\n"
908  << " pathbbox /t exch def /r exch def /b exch def /l exch def\n"
909  << " /w r l sub ceiling cvi def\n"
910  << " /h t b sub ceiling cvi def\n"
911  << " /imageByteWidth w 8 div ceiling cvi def\n"
912  << " /imageHeight h def\n"
913  << " bgred bggreen bgblue setrgbcolor\n"
914  << " eofill\n"
915  << " fgred fggreen fgblue setrgbcolor\n"
916  << " w 0 gt h 0 gt and { l w add b translate w neg h scale w h true [w 0 0 h neg 0 h] { patternproc } imagemask } if\n"
917  << " } ifelse\n"
918  << " grestore\n"
919  << " end\n"
920  << "} dup 0 8 dict put def\n\n"
921  << "/istroke {\n"
922  << " gsave\n"
923  << " brushDashOffset -1 eq { [] 0 setdash 1 setgray }\n"
924  << " { brushDashArray brushDashOffset setdash fgred fggreen fgblue setrgbcolor } ifelse\n"
925  << " originalCTM setmatrix\n"
926  << " stroke\n"
927  << " grestore\n"
928  << "} def\n\n"
929  << "/ishow {\n"
930  << " 0 begin\n"
931  << " gsave\n"
932  << " fgred fggreen fgblue setrgbcolor\n"
933  << " /fontDict printFont printSize scalefont dup setfont def\n"
934  << " /descender fontDict begin 0 [FontBBox] 1 get FontMatrix end\n"
935  << " transform exch pop def\n"
936  << " /vertoffset 1 printSize sub descender sub def\n"
937  << " { 0 vertoffset moveto show /vertoffset vertoffset printSize sub def } forall\n"
938  << " grestore\n"
939  << " end\n"
940  << "} dup 0 3 dict put def\n"
941  << "/patternproc {\n"
942  << " 0 begin\n"
943  << " /patternByteLength patternString length def\n"
944  << " /patternHeight patternByteLength 8 mul sqrt cvi def\n"
945  << " /patternWidth patternHeight def\n"
946  << " /patternByteWidth patternWidth 8 idiv def\n"
947  << " /imageByteMaxLength imageByteWidth imageHeight mul\n"
948  << " stringLimit patternByteWidth sub min def\n"
949  << " /imageMaxHeight imageByteMaxLength imageByteWidth idiv patternHeight idiv\n"
950  << " patternHeight mul patternHeight max def\n"
951  << " /imageHeight imageHeight imageMaxHeight sub store\n"
952  << " /imageString imageByteWidth imageMaxHeight mul patternByteWidth add string def\n"
953  << " 0 1 imageMaxHeight 1 sub {\n"
954  << " /y exch def\n"
955  << " /patternRow y patternByteWidth mul patternByteLength mod def\n"
956  << " /patternRowString patternString patternRow patternByteWidth getinterval def\n"
957  << " /imageRow y imageByteWidth mul def\n"
958  << " 0 patternByteWidth imageByteWidth 1 sub { /x exch def imageString imageRow x add patternRowString putinterval } for\n"
959  << " } for\n"
960  << " imageString\n"
961  << " end\n"
962  << "} dup 0 12 dict put def\n\n"
963  << "/min { dup 3 2 roll dup 4 3 roll lt { exch } if pop } def\n\n"
964  << "/max { dup 3 2 roll dup 4 3 roll gt { exch } if pop } def\n\n"
965  << "/midpoint {\n"
966  << " 0 begin\n"
967  << " /y1 exch def\n"
968  << " /x1 exch def\n"
969  << " /y0 exch def\n"
970  << " /x0 exch def\n"
971  << " x0 x1 add 2 div\n"
972  << " y0 y1 add 2 div\n"
973  << " end\n"
974  << "} dup 0 4 dict put def\n\n"
975  << "/thirdpoint {\n"
976  << " 0 begin\n"
977  << " /y1 exch def\n"
978  << " /x1 exch def\n"
979  << " /y0 exch def\n"
980  << " /x0 exch def\n"
981  << " x0 2 mul x1 add 3 div\n"
982  << " y0 2 mul y1 add 3 div\n"
983  << " end\n"
984  << "} dup 0 4 dict put def\n\n"
985  << "/subspline {\n"
986  << " 0 begin\n"
987  << " /movetoNeeded exch def\n"
988  << " y exch get /y3 exch def\n"
989  << " x exch get /x3 exch def\n"
990  << " y exch get /y2 exch def\n"
991  << " x exch get /x2 exch def\n"
992  << " y exch get /y1 exch def\n"
993  << " x exch get /x1 exch def\n"
994  << " y exch get /y0 exch def\n"
995  << " x exch get /x0 exch def\n"
996  << " x1 y1 x2 y2 thirdpoint\n"
997  << " /p1y exch def\n"
998  << " /p1x exch def\n"
999  << " x2 y2 x1 y1 thirdpoint\n"
1000  << " /p2y exch def\n"
1001  << " /p2x exch def\n"
1002  << " x1 y1 x0 y0 thirdpoint\n"
1003  << " p1x p1y midpoint\n"
1004  << " /p0y exch def\n"
1005  << " /p0x exch def\n"
1006  << " x2 y2 x3 y3 thirdpoint\n"
1007  << " p2x p2y midpoint\n"
1008  << " /p3y exch def\n"
1009  << " /p3x exch def\n"
1010  << " movetoNeeded { p0x p0y moveto } if\n"
1011  << " p1x p1y p2x p2y p3x p3y curveto\n"
1012  << " end\n"
1013  << "} dup 0 17 dict put def\n\n"
1014  << "/storexyn {\n"
1015  << " /n exch def\n"
1016  << " /y n array def\n"
1017  << " /x n array def\n"
1018  << " n 1 sub -1 0 { /i exch def y i 3 2 roll put x i 3 2 roll put } for\n"
1019  << "} def\n\n"
1020  << "/SSten { fgred fggreen fgblue setrgbcolor dup true exch 1 0 0 -1 0 6 -1 roll matrix astore } def\n\n"
1021  << "/FSten {\n"
1022  << " dup 3 -1 roll dup 4 1 roll exch\n"
1023  << " newpath\n"
1024  << " 0 0 moveto\n"
1025  << " dup 0 exch lineto\n"
1026  << " exch dup 3 1 roll exch lineto\n"
1027  << " 0 lineto\n"
1028  << " closepath\n"
1029  << " bgred bggreen bgblue setrgbcolor\n"
1030  << " eofill\n"
1031  << " SSten\n"
1032  << "} def\n\n"
1033  << "/Rast { exch dup 3 1 roll 1 0 0 -1 0 6 -1 roll matrix astore } def\n\n";
1034 
1035  // For scale and translate ..
1036  graphic_header();
1037 
1038  graphics_prolog_exists = true;
1039 }
1040 
1041 void vul_psfile::done()
1042 {
1043  if (debug) std::cout << "vul_psfile::done\n";
1044  doneps = true;
1046  output_filestream << "end % TargetjrDict\n";
1047 
1048  output_filestream << "showpage\n%%Trailer\n";
1049 }
float bg_b
Definition: vul_psfile.h:100
std::streampos header_pos
Definition: vul_psfile.h:122
std::streampos sobj_t_pos
Definition: vul_psfile.h:121
std::string filename
Definition: vul_psfile.h:108
float fg_r
Definition: vul_psfile.h:99
void reset_bounding_box()
Rewrite output bounding box parameters.
Definition: vul_psfile.cxx:99
double pos_iny
Definition: vul_psfile.h:106
void point(float x, float y, float point_size=0)
Add a point at the given coordinates to the Postscript file.
Definition: vul_psfile.cxx:621
void circle(float x, float y, float radius)
Add a circle with the given centre point and radius to the Postscript file.
Definition: vul_psfile.cxx:661
std::streampos translate_pos
Definition: vul_psfile.h:120
void line(float x1, float y1, float x2, float y2)
Add a line between the given points to the Postscript file.
Definition: vul_psfile.cxx:605
double ihf
Definition: vul_psfile.h:104
bool graphics_prolog_exists
Definition: vul_psfile.h:124
#define in_range(a)
Definition: vul_psfile.cxx:16
float fg_b
Definition: vul_psfile.h:99
float scale_x
Definition: vul_psfile.h:102
paper_type printer_paper_type
Definition: vul_psfile.h:109
int box_height
Definition: vul_psfile.h:116
float scale_y
Definition: vul_psfile.h:102
void graphic_header()
Set graphic coordinate (translate and rotate to local coordinate).
Definition: vul_psfile.cxx:485
bool exist_image
Definition: vul_psfile.h:125
double psizey
Definition: vul_psfile.h:105
paper_orientation printer_paper_orientation
Definition: vul_psfile.h:110
void print_greyscale_image(const unsigned char *data, int sizex, int sizey)
Write 8 bit grey scale image.
Definition: vul_psfile.cxx:225
constexpr bool debug
void sobj_rgb_params(char const *str, bool filled)
Utility program used in point(), line(), ellipse() and circle().
Definition: vul_psfile.cxx:592
void print_graphics_prolog()
the defined procedure for PostScript script use.
Definition: vul_psfile.cxx:678
void compute_bounding_box()
Recalculate bounding box and scale x and y (if necessary).
Definition: vul_psfile.cxx:125
float fg_g
Definition: vul_psfile.h:99
Write a PostScript file.
Definition: vul_psfile.h:22
float bg_g
Definition: vul_psfile.h:100
bool set_parameters(int sizex, int sizey)
Set ox, oy , iw, ih, iwf, ihf parameters for PostScript file use.
Definition: vul_psfile.cxx:538
void object_translate_and_scale()
Set object translate and scale.
Definition: vul_psfile.cxx:520
void reset_postscript_header()
Reset PostScript header file.
Definition: vul_psfile.cxx:573
#define Hex4bit(a)
Definition: vul_psfile.cxx:17
float line_width_
Definition: vul_psfile.h:101
float bg_r
Definition: vul_psfile.h:100
double psizex
Definition: vul_psfile.h:105
void ellipse(float x, float y, float a_axis, float b_axis, int angle=0)
Add an ellipse to the Postscript file.
Definition: vul_psfile.cxx:635
vul_psfile(char const *filename, bool debug_output=false)
Default constructor.
Definition: vul_psfile.cxx:54
double pos_inx
Definition: vul_psfile.h:106
~vul_psfile() override
Destructor.
Definition: vul_psfile.cxx:88
#define RANGE(a, b, c)
Definition: vul_psfile.cxx:15
void image_translate_and_scale()
Set Image translate and scale.
Definition: vul_psfile.cxx:500
int reduction_factor
Definition: vul_psfile.h:112
void postscript_header()
PostScript file header. Automatically called by the constructor.
Definition: vul_psfile.cxx:554
int box_width
Definition: vul_psfile.h:116
void set_min_max_xy(float x, float y)
Set Bounding Box Min and Max x, y.
Definition: vul_psfile.cxx:203
#define PI
std::ofstream output_filestream
Definition: vul_psfile.h:97
paper_layout printer_paper_layout
Definition: vul_psfile.h:111
bool doneps
Definition: vul_psfile.h:113
void print_color_image(const unsigned char *data, int sizex, int sizey)
Write 24 bit colour image.
Definition: vul_psfile.cxx:323
bool exist_objs
Definition: vul_psfile.h:126
write out images, points, lines, circles and/or ellipses to PostScript
double iwf
Definition: vul_psfile.h:104