11 # include <vcl_msvc_warnings.h> 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'))) 19 static const float PIX2INCH = 72.0f;
20 static bool debug =
true;
23 static double paper_size[8][2] = {
35 static double margins[8 ][2] = {
47 static float ps_minimum = 0.1f;
48 static float ps_maximum = 8.f;
50 static const std::streampos HEADER_START(-1);
56 : output_filestream(f),
57 fg_r(0), fg_g(0), fg_b(0),
58 bg_r(1), bg_g(1), bg_b(1),
60 scale_x(1.f), scale_y(1.f),
61 ox(0), oy(0), iw(0), ih(0),
63 psizex(8.5), psizey(11),
64 pos_inx(4.25), pos_iny(5.5),
68 printer_paper_orientation(
vul_psfile::PORTRAIT),
72 min_x(1000), min_y(1000),
73 max_x(-1000), max_y(-1000),
74 box_width(0), box_height(0),
77 header_pos(HEADER_START),
78 graphics_prolog_exists(false),
83 if (
debug) std::cout <<
"vul_psfile::vul_psfile\n";
92 if (
debug) std::cout <<
"vul_psfile::~vul_psfile\n";
104 std::streampos temp_pos;
201 if (
debug) std::cout <<
"vul_psfile::compute_bounding_box, box_width = " 210 int x = int(xx + 0.5);
211 int y = int(yy + 0.5);
235 std::cout <<
"vul_psfile::print_greyscale_image, width = " << sizex
236 <<
", height = " << sizey <<
", reduction_factor = " 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";
260 <<
"% print in landscape mode\n90 rotate 0 " << int(-
psizey*PIX2INCH) <<
" translate\n\n";
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;
272 for (
int j=0; j<new_height; j++)
275 for (
int i = 0; i < new_width; i++)
280 index = int(*(buffer +
width * j + i));
285 int number_of_pixels_sampled=0;
290 index += int(*(buffer + (pixel_number+m+n*
width)));
291 ++number_of_pixels_sampled;
293 if(number_of_pixels_sampled == 0)
295 std::cerr <<
"ERROR: Division by 0! " << __FILE__ << __LINE__ << std::endl;
298 index/=number_of_pixels_sampled;
305 auto low4 = (
unsigned char) (index & 0x000f);
306 auto high4 = (
unsigned char) ((index & 0x00f0) >> 4);
313 std::cout <<
" index out of range: " << index <<
'\n';
316 if (countrow >= linesize)
325 <<
"% restore original state\norigstate restore\n\n";
334 std::cout <<
"vul_psfile::print_color_image, width = " << sizex
335 <<
", height = " << sizey <<
", reduction_factor = " 338 constexpr
int bytes_per_pixel = 3;
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" 364 <<
"/rgbindx 0 def\n\n";
368 <<
"% print in landscape mode\n90 rotate 0 " << int(-
psizey*PIX2INCH) <<
" translate\n\n";
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" 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" 391 <<
" /rgbindx rgbindx 3 add store\n" 393 <<
" grays 0 npixls getinterval\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" 415 <<
" /colorimage {\n" 416 <<
" pop pop % remove 'false 3' operands\n" 417 <<
" {colortogray} mergeprocs\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";
427 constexpr
int linesize = 72;
430 for (
int j = 0; j < new_height;j++)
433 for (
int i = 0; i < new_width; i++)
435 for (
int c = 0; c < bytes_per_pixel; ++c)
441 index = int(*(data + (sizex*j+i) * bytes_per_pixel + c));
446 int number_of_pixels_sampled=0;
451 index += int(*(data+(pixel_number+(m+n*sizex)*bytes_per_pixel)));
452 ++number_of_pixels_sampled;
454 if(number_of_pixels_sampled == 0)
456 std::cerr <<
"ERROR: Division by 0! " << __FILE__ << __LINE__ << std::endl;
459 index/=number_of_pixels_sampled;
466 auto low4 = (
unsigned char) (index & 0x000f);
467 auto high4 = (
unsigned char) ((index & 0x00f0) >> 4);
474 std::cout <<
" index out of range: " << index <<
'\n';
477 if (countrow >= linesize)
488 <<
"% restore original state\norigstate restore\n\n";
498 << int(-
psizey*PIX2INCH) <<
" translate\n\n";
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';
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";
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";
571 std::cerr <<
"vul_psfile: Header already set to " << long(
header_pos) <<
'\n';
576 <<
"%!PS-Adobe-2.0 EPSF-2.0\n%%Title: " <<
filename.c_str()
577 <<
"\n%%Creator: vul_psfile\n%%BoundingBox: ";
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';
597 << std::setw(6) <<
ox <<
' ' 598 << std::setw(6) <<
oy <<
' ' 599 << std::setw(6) <<
ox+
iw <<
' ' 600 << std::setw(6) <<
oy+
ih <<
'\n';
611 <<
"\nBegin %I " << obj_str <<
"\n2 0 0 [] 0 SetB\n" 615 << (filled ?
"0":
"none") <<
" SetP %I p n\n";
632 << int(x2) <<
' ' << int(y2) <<
" Line\nEnd\n";
647 output_filestream << x <<
' ' << y <<
' ' << point_size <<
' ' << point_size <<
" Elli\nEnd\n";
655 #ifndef PI // should already be defined in math.h - PVR 656 #define PI 3.14159265358979323846 658 const double radsperdeg =
PI/180.0;
661 int(y+a_axis*std::sin(angle*radsperdeg) + 0.5) );
663 int(y-a_axis*std::sin(angle*radsperdeg) + 0.5) );
670 << -angle <<
" rotate\n0 0 " << (int)a_axis <<
' ' 671 << (
int)b_axis <<
" Elli\nEnd\n";
674 << (int)a_axis <<
' ' << (
int)b_axis <<
" Elli\nEnd\n";
704 <<
"\n\n%%BeginTargetjrPrologue\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" 717 <<
" originalCTM setmatrix\n" 718 <<
" tipx tipy translate\n" 721 <<
" arrowHeight neg arrowWidth 2 div moveto\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" 731 <<
" padtip 0 translate\n" 732 <<
" arrowHeight padtip add padtail add arrowHeight div dup scale\n" 733 <<
" arrowheadpath\n" 736 <<
" brushNone not {\n" 737 <<
" originalCTM setmatrix\n" 738 <<
" tipx tipy translate\n" 740 <<
" arrowheadpath\n" 745 <<
"} dup 0 9 dict put def\n\n" 746 <<
"/arrowheadpath {\n" 748 <<
" arrowHeight neg arrowWidth 2 div moveto\n" 750 <<
" arrowHeight neg arrowWidth 2 div neg lineto\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" 760 <<
"} dup 0 4 dict put def\n\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" 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" 783 <<
" false /brushRightArrow idef\n" 784 <<
" false /brushLeftArrow idef\n" 785 <<
" true /brushNone idef\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" 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" 801 <<
" dup -1 eq { /patternGrayLevel idef /patternString idef }\n" 802 <<
" { /patternGrayLevel idef } ifelse\n" 803 <<
" false /patternNone idef\n" 811 <<
" 0 0 0 0 0 0 1 1 true subspline\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" 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" 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" 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" 839 <<
"} dup 0 4 dict put def\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" 847 <<
"} dup 0 1 dict put def\n\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" 858 <<
"} dup 0 4 dict put def\n\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" 872 <<
"} dup 0 4 dict put def\n\n" 875 <<
" newpath moveto -1 add { lineto } repeat closepath\n" 876 <<
" patternNone not { ifill } if\n" 877 <<
" brushNone not { istroke } if\n" 891 <<
" patternNone not { ifill } if\n" 892 <<
" brushNone not { istroke } if\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" 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" 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" 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" 920 <<
"} dup 0 8 dict put def\n\n" 923 <<
" brushDashOffset -1 eq { [] 0 setdash 1 setgray }\n" 924 <<
" { brushDashArray brushDashOffset setdash fgred fggreen fgblue setrgbcolor } ifelse\n" 925 <<
" originalCTM setmatrix\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" 940 <<
"} dup 0 3 dict put def\n" 941 <<
"/patternproc {\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" 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" 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" 971 <<
" x0 x1 add 2 div\n" 972 <<
" y0 y1 add 2 div\n" 974 <<
"} dup 0 4 dict put def\n\n" 981 <<
" x0 2 mul x1 add 3 div\n" 982 <<
" y0 2 mul y1 add 3 div\n" 984 <<
"} dup 0 4 dict put def\n\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" 1013 <<
"} dup 0 17 dict put def\n\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" 1020 <<
"/SSten { fgred fggreen fgblue setrgbcolor dup true exch 1 0 0 -1 0 6 -1 roll matrix astore } def\n\n" 1022 <<
" dup 3 -1 roll dup 4 1 roll exch\n" 1025 <<
" dup 0 exch lineto\n" 1026 <<
" exch dup 3 1 roll exch lineto\n" 1029 <<
" bgred bggreen bgblue setrgbcolor\n" 1033 <<
"/Rast { exch dup 3 1 roll 1 0 0 -1 0 6 -1 roll matrix astore } def\n\n";
1043 if (
debug) std::cout <<
"vul_psfile::done\n";
std::streampos header_pos
std::streampos sobj_t_pos
void reset_bounding_box()
Rewrite output bounding box parameters.
void point(float x, float y, float point_size=0)
Add a point at the given coordinates to the Postscript file.
void circle(float x, float y, float radius)
Add a circle with the given centre point and radius to the Postscript file.
std::streampos translate_pos
void line(float x1, float y1, float x2, float y2)
Add a line between the given points to the Postscript file.
bool graphics_prolog_exists
paper_type printer_paper_type
void graphic_header()
Set graphic coordinate (translate and rotate to local coordinate).
paper_orientation printer_paper_orientation
void print_greyscale_image(const unsigned char *data, int sizex, int sizey)
Write 8 bit grey scale image.
void sobj_rgb_params(char const *str, bool filled)
Utility program used in point(), line(), ellipse() and circle().
void print_graphics_prolog()
the defined procedure for PostScript script use.
void compute_bounding_box()
Recalculate bounding box and scale x and y (if necessary).
bool set_parameters(int sizex, int sizey)
Set ox, oy , iw, ih, iwf, ihf parameters for PostScript file use.
void object_translate_and_scale()
Set object translate and scale.
void reset_postscript_header()
Reset PostScript header file.
void ellipse(float x, float y, float a_axis, float b_axis, int angle=0)
Add an ellipse to the Postscript file.
vul_psfile(char const *filename, bool debug_output=false)
Default constructor.
~vul_psfile() override
Destructor.
void image_translate_and_scale()
Set Image translate and scale.
void postscript_header()
PostScript file header. Automatically called by the constructor.
void set_min_max_xy(float x, float y)
Set Bounding Box Min and Max x, y.
std::ofstream output_filestream
paper_layout printer_paper_layout
void print_color_image(const unsigned char *data, int sizex, int sizey)
Write 24 bit colour image.
write out images, points, lines, circles and/or ellipses to PostScript