23 #if defined (HAVE_CONFIG_H) 31 #if defined (HAVE_GL2PS_H) && defined (HAVE_OPENGL) 69 gl2ps_renderer :
public opengl_renderer
73 gl2ps_renderer (FILE *_fp,
const std::string& _term)
74 : opengl_renderer () , fp (_fp), term (_term), fontsize (),
75 fontname (), buffer_overflow (
false)
78 ~gl2ps_renderer (
void) =
default;
92 double x,
double y,
double z,
93 int halign,
int valign,
double rotation = 0.0);
105 if (go.
isa (
"axes") || go.
isa (
"hggroup"))
115 else if (go.
isa (
"patch") || go.
isa (
"surface"))
130 glGetIntegerv (GL_VIEWPORT, vp);
131 gl2psBeginViewport (vp);
136 gl2psGetOptions (&opts);
137 if (has_alpha (props.get___myhandle__ ()))
139 opts &= ~GL2PS_OCCLUSION_CULL;
143 gl2psEnable (GL2PS_BLEND);
147 opts |= GL2PS_OCCLUSION_CULL;
148 gl2psDisable (GL2PS_BLEND);
151 gl2psSetOptions (opts);
159 GLint
state = gl2psEndViewport ();
160 if (
state == GL2PS_NO_FEEDBACK && props.is_visible ())
161 warning (
"gl2ps_renderer::draw_axes: empty feedback buffer and/or nothing else to print");
162 else if (
state == GL2PS_ERROR)
163 error (
"gl2ps_renderer::draw_axes: gl2psEndPage returned GL2PS_ERROR");
165 buffer_overflow |= (
state == GL2PS_OVERFLOW);
169 gl2psGetOptions (&opts);
170 opts &= ~GL2PS_DRAW_BACKGROUND;
171 gl2psSetOptions (opts);
176 void draw_pixels (
int w,
int h,
const float *data);
177 void draw_pixels (
int w,
int h,
const uint8_t *data);
178 void draw_pixels (
int w,
int h,
const uint16_t *data);
180 void init_marker (
const std::string& m,
double size,
float width)
186 if (m ==
"o" || m ==
"v" || m ==
"^" || m ==
">" || m ==
"<" || m ==
"h" 187 || m ==
"hexagram" || m ==
"p" || m ==
"pentagram")
189 set_linejoin (
"round");
190 set_linecap (
"round");
194 set_linejoin (
"miter");
195 set_linecap (
"square");
199 void set_linestyle (
const std::string&
s,
bool use_stipple =
false,
200 double linewidth = 0.5)
204 if (
s ==
"-" && ! use_stipple)
205 gl2psDisable (GL2PS_LINE_STIPPLE);
207 gl2psEnable (GL2PS_LINE_STIPPLE);
214 #if defined (HAVE_GL2PSLINEJOIN) 216 gl2psLineCap (GL2PS_LINE_CAP_BUTT);
217 else if (
s ==
"square")
218 gl2psLineCap (GL2PS_LINE_CAP_SQUARE);
219 else if (
s ==
"round")
220 gl2psLineCap (GL2PS_LINE_CAP_ROUND);
228 #if defined (HAVE_GL2PSLINEJOIN) 230 gl2psLineJoin (GL2PS_LINE_JOIN_ROUND);
231 else if (
s ==
"miter")
232 gl2psLineJoin (GL2PS_LINE_JOIN_MITER);
233 else if (
s ==
"chamfer")
234 gl2psLineJoin (GL2PS_LINE_JOIN_BEVEL);
238 void set_polygon_offset (
bool on,
float offset = 0.0
f)
243 gl2psEnable (GL2PS_POLYGON_OFFSET_FILL);
247 gl2psDisable (GL2PS_POLYGON_OFFSET_FILL);
252 void set_linewidth (
float w)
261 void fix_strlist_position (
double x,
double y,
double z,
263 std::list<text_renderer::string>& lst);
268 std::list<octave::text_renderer::string>& lst);
273 std::list<octave::text_renderer::string>& lst);
275 int alignment_to_mode (
int ha,
int va)
const;
280 bool buffer_overflow;
292 if (go.
isa (
"figure") || go.
isa (
"uipanel"))
302 else if (go.
isa (
"axes"))
315 static bool in_draw =
false;
317 static GLint buffsize;
321 unwind_protect
frame;
327 GLint gl2ps_term = GL2PS_PS;
328 if (term.find (
"eps") != std::string::npos)
329 gl2ps_term = GL2PS_EPS;
330 else if (term.find (
"pdf") != std::string::npos)
331 gl2ps_term = GL2PS_PDF;
332 else if (term.find (
"ps") != std::string::npos)
333 gl2ps_term = GL2PS_PS;
334 else if (term.find (
"svg") != std::string::npos)
335 gl2ps_term = GL2PS_SVG;
336 else if (term.find (
"pgf") != std::string::npos)
337 gl2ps_term = GL2PS_PGF;
338 else if (term.find (
"tex") != std::string::npos)
339 gl2ps_term = GL2PS_TEX;
341 warning (
"gl2ps_renderer::draw: Unknown terminal %s, using 'ps'",
344 GLint gl2ps_text = 0;
345 if (term.find (
"notxt") != std::string::npos)
346 gl2ps_text = GL2PS_NO_TEXT;
349 GLint gl2ps_sort = GL2PS_BSP_SORT;
353 if (has_2D_axes (go.
get (
"__myhandle__")))
354 gl2ps_sort = GL2PS_NO_SORT;
360 error (
"gl2ps_renderer::draw: couldn't open temporary file for printing");
365 if (term.find (
"tex") == std::string::npos)
366 buffsize = 2*1024*1024;
370 buffer_overflow =
true;
372 while (buffer_overflow)
374 buffer_overflow =
false;
388 size_t found_redirect = old_print_cmd.find (
'>');
390 if (found_redirect != std::string::npos)
391 include_graph = old_print_cmd.substr (found_redirect + 1);
393 include_graph = old_print_cmd;
395 size_t n_begin = include_graph.find_first_not_of (
' ');
397 if (n_begin != std::string::npos)
399 size_t n_end = include_graph.find_last_not_of (
' ');
400 include_graph = include_graph.substr (n_begin,
401 n_end - n_begin + 1);
404 include_graph =
"foobar-inc";
410 Matrix c = fprop.get_color_rgb ();
411 glClearColor (
c(0),
c(1),
c(2), 1);
414 GLint ret = gl2psBeginPage (
"gl2ps_renderer figure",
"Octave",
415 nullptr, gl2ps_term, gl2ps_sort,
418 | GL2PS_DRAW_BACKGROUND
419 | GL2PS_NO_PS3_SHADING
420 | GL2PS_USE_CURRENT_VIEWPORT),
421 GL_RGBA, 0,
nullptr, 0, 0, 0,
422 buffsize, tmpf, include_graph.c_str ());
423 if (ret == GL2PS_ERROR)
425 old_print_cmd.clear ();
426 error (
"gl2ps_renderer::draw: gl2psBeginPage returned GL2PS_ERROR");
432 warning (
"gl2ps_renderer::draw: retrying with buffer size: %.1E B\n",
double (2*buffsize));
434 if (! buffer_overflow)
435 old_print_cmd = print_cmd;
446 size_t nread, nwrite;
451 const char*
fcn =
"/SRX { gsave FCT moveto rotate xshow grestore } BD\n";
452 bool header_found = ! (term.find (
"eps") != std::string::npos
453 || term.find (
"svg") != std::string::npos);
455 while (! feof (tmpf) && nread)
457 if (! header_found && std::fgets (
str, 8192, tmpf))
460 nread = std::fread (
str, 1, 8192, tmpf);
472 error (
"gl2ps_renderer::draw: internal pipe error");
475 else if (! header_found
476 && term.find (
"svg") != std::string::npos)
483 size_t pos = srchstr.find (
"px");
484 if (pos != std::string::npos)
487 srchstr[pos+1] =
't';
489 pos = srchstr.find (
"px", pos);
490 srchstr[pos+1] =
't';
491 std::strcpy (
str, srchstr.c_str ());
495 nwrite = std::fwrite (
str, 1, nread, fp);
500 error (
"gl2ps_renderer::draw: internal pipe error");
510 gl2ps_renderer::alignment_to_mode (
int ha,
int va)
const 512 int gl2psa = GL2PS_TEXT_BL;
516 if (va == 0 || va == 3)
517 gl2psa=GL2PS_TEXT_BL;
519 gl2psa=GL2PS_TEXT_TL;
521 gl2psa=GL2PS_TEXT_CL;
525 if (va == 0 || va == 3)
526 gl2psa=GL2PS_TEXT_BR;
528 gl2psa=GL2PS_TEXT_TR;
530 gl2psa=GL2PS_TEXT_CR;
534 if (va == 0 || va == 3)
546 gl2ps_renderer::fix_strlist_position (
double x,
double y,
double z,
548 std::list<text_renderer::string>& lst)
550 for (
auto& txtobj : lst)
553 ColumnVector coord_pix = get_transform ().transform (
x,
y, z,
false);
556 double rot = rotation * 4.0 *
atan (1.0) / 180;
557 coord_pix(0) += (txtobj.get_x () +
box(0))*cos (rot)
558 - (txtobj.get_y () +
box(1))*sin (rot);
559 coord_pix(1) -= (txtobj.get_y () +
box(1))*cos (rot)
560 + (txtobj.get_x () +
box(0))*sin (rot);
563 glGetIntegerv (GL_VIEWPORT, vp);
565 txtobj.set_x (coord_pix(0));
566 txtobj.set_y (vp[3] - coord_pix(1));
567 txtobj.set_z (coord_pix(2));
572 code_to_symbol (uint32_t
code)
576 uint32_t idx =
code - 945;
590 else if (
code == 978)
592 else if (
code == 215)
594 else if (
code == 177)
596 else if (
code == 8501)
598 else if (
code == 8465)
600 else if (
code == 8242)
602 else if (
code == 8736)
604 else if (
code == 172)
606 else if (
code == 9829)
608 else if (
code == 8472)
610 else if (
code == 8706)
612 else if (
code == 8704)
614 else if (
code == 9827)
616 else if (
code == 9824)
618 else if (
code == 8476)
620 else if (
code == 8734)
622 else if (
code == 8730)
624 else if (
code == 8707)
626 else if (
code == 9830)
628 else if (
code == 8747)
630 else if (
code == 8727)
632 else if (
code == 8744)
634 else if (
code == 8855)
636 else if (
code == 8901)
638 else if (
code == 8728)
640 else if (
code == 8745)
642 else if (
code == 8743)
644 else if (
code == 8856)
646 else if (
code == 8729)
648 else if (
code == 8746)
650 else if (
code == 8853)
652 else if (
code == 8804)
654 else if (
code == 8712)
656 else if (
code == 8839)
658 else if (
code == 8801)
660 else if (
code == 8773)
662 else if (
code == 8834)
664 else if (
code == 8805)
666 else if (
code == 8715)
668 else if (
code == 8764)
670 else if (
code == 8733)
672 else if (
code == 8838)
674 else if (
code == 8835)
676 else if (
code == 8739)
678 else if (
code == 8776)
680 else if (
code == 8869)
682 else if (
code == 8656)
684 else if (
code == 8592)
686 else if (
code == 8658)
688 else if (
code == 8594)
690 else if (
code == 8596)
692 else if (
code == 8593)
694 else if (
code == 8595)
696 else if (
code == 8970)
698 else if (
code == 8971)
700 else if (
code == 10216)
702 else if (
code == 10217)
704 else if (
code == 8968)
706 else if (
code == 8969)
708 else if (
code == 8800)
710 else if (
code == 8230)
712 else if (
code == 176)
714 else if (
code == 8709)
716 else if (
code == 169)
726 select_font (
caseless_str fn,
bool isbold,
bool isitalic)
730 if (fn ==
"times" || fn ==
"times-roman")
732 if (isitalic && isbold)
733 fontname =
"Times-BoldItalic";
735 fontname =
"Times-Italic";
737 fontname =
"Times-Bold";
739 fontname =
"Times-Roman";
741 else if (fn ==
"courier")
743 if (isitalic && isbold)
744 fontname =
"Courier-BoldOblique";
746 fontname =
"Courier-Oblique";
748 fontname =
"Courier-Bold";
750 fontname =
"Courier";
752 else if (fn ==
"symbol")
754 else if (fn ==
"zapfdingbats")
755 fontname =
"ZapfDingbats";
758 if (isitalic && isbold)
759 fontname =
"Helvetica-BoldOblique";
761 fontname =
"Helvetica-Oblique";
763 fontname =
"Helvetica-Bold";
765 fontname =
"Helvetica";
773 std::size_t idx =
str.find (chr);
774 while (idx != std::string::npos)
776 str.insert (idx, 1,
'\\');
777 idx =
str.find (chr, idx + 2);
782 gl2ps_renderer::strlist_to_svg (
double x,
double y,
double z,
784 std::list<octave::text_renderer::string>& lst)
790 ColumnVector coord_pix = get_transform ().transform (
x,
y, z,
false);
792 std::ostringstream
os;
793 os <<
"<text xml:space=\"preserve\" ";
797 <<
"translate(" << coord_pix(0) +
box(0) <<
"," << coord_pix(1) -
box(1)
798 <<
") rotate(" << -rotation <<
"," << -
box(0) <<
"," <<
box(1)
802 auto p = lst.begin ();
806 double size =
p->get_size ();
808 os <<
"font-family=\"" <<
name <<
"\" " 809 <<
"font-weight=\"" << weight <<
"\" " 810 <<
"font-style=\"" << angle <<
"\" " 811 <<
"font-size=\"" << size <<
"\">";
815 for (
p = lst.begin ();
p != lst.end ();
p++)
819 if (
name.compare (
p->get_family ()))
820 os <<
"font-family=\"" <<
p->get_family () <<
"\" ";
822 if (weight.compare (
p->get_weight ()))
823 os <<
"font-weight=\"" <<
p->get_weight () <<
"\" ";
825 if (angle.compare (
p->get_angle ()))
826 os <<
"font-style=\"" <<
p->get_angle () <<
"\" ";
828 if (size !=
p->get_size ())
829 os <<
"font-size=\"" <<
p->get_size () <<
"\" ";
831 os <<
"y=\"" << -
p->get_y () <<
"\" ";
834 os <<
"fill=\"rgb(" << col(0)*255 <<
"," 835 << col(1)*255 <<
"," << col(2)*255 <<
")\" ";
839 std::vector<double> xdata =
p->get_xdata ();
840 for (
auto q = xdata.begin (); q != xdata.end (); q++)
848 os <<
"&#" <<
p->get_code () <<
";";
852 for (
auto q =
str.begin (); q !=
str.end (); q++)
854 std::stringstream chr;
856 if (chr.str () ==
"\"")
858 else if (chr.str () ==
"'")
860 else if (chr.str () ==
"&")
862 else if (chr.str () ==
"<")
864 else if (chr.str () ==
">")
878 gl2ps_renderer::strlist_to_ps (
double x,
double y,
double z,
880 std::list<octave::text_renderer::string>& lst)
883 fix_strlist_position (
x,
y, z,
box, rotation, lst);
884 Matrix prev_color (1, 3, -1);
886 std::ostringstream ss;
889 for (
const auto& txtobj : lst)
892 if (txtobj.get_color () != prev_color)
894 prev_color = txtobj.get_color ();
895 for (
int i = 0;
i < 3;
i++)
896 ss << prev_color(
i) <<
" ";
903 if (txtobj.get_code ())
906 str = code_to_symbol (txtobj.get_code ());
910 fontname = select_font (txtobj.get_name (),
911 txtobj.get_weight () ==
"bold",
912 txtobj.get_angle () ==
"italic");
913 str = txtobj.get_string ();
916 escape_character (
"(",
str);
917 escape_character (
")",
str);
919 ss <<
"(" <<
str <<
") [";
921 std::vector<double> xdata = txtobj.get_xdata ();
922 for (
size_t i = 1;
i < xdata.size ();
i++)
923 ss << xdata[
i] - xdata[
i-1] <<
" ";
925 ss <<
"10] " << rotation <<
" " << txtobj.get_x ()
926 <<
" " << txtobj.get_y () <<
" " << txtobj.get_size ()
927 <<
" /" << fontname <<
" SRX\n";
936 gl2ps_renderer::render_text (
const std::string& txt,
937 double x,
double y,
double z,
938 int ha,
int va,
double rotation)
943 return Matrix (1, 4, 0.0);
947 std::list<text_renderer::string> lst;
949 text_to_strlist (
str, lst, bbox, ha, va, rotation);
950 glRasterPos3d (
x,
y, z);
953 if (term.find (
"svg") != std::string::npos)
955 std::string elt = strlist_to_svg (
x,
y, z, bbox, rotation, lst);
957 gl2psSpecial (GL2PS_SVG, elt.c_str ());
959 else if (term.find (
"eps") != std::string::npos)
961 std::string elt = strlist_to_ps (
x,
y, z, bbox, rotation, lst);
963 gl2psSpecial (GL2PS_EPS, elt.c_str ());
967 gl2psTextOpt (
str.c_str (), fontname.c_str (), fontsize,
968 alignment_to_mode (ha, va), rotation);
970 fontname = saved_font;
992 fontname = select_font (fn, isbold, isitalic);
996 gl2ps_renderer::draw_pixels (
int w,
int h,
const float *data)
1001 for (
int i = 0;
i < 3*
h*
w;
i++)
1002 tmp_data[
i] = (data[
i] < 0.0
f ? 0.0
f : (data[
i] > 1.0
f ? 1.0
f : data[
i]));
1004 gl2psDrawPixels (
w,
h, 0, 0, GL_RGB, GL_FLOAT, tmp_data);
1008 gl2ps_renderer::draw_pixels (
int w,
int h,
const uint8_t *data)
1016 for (
int i = 0;
i < 3*
w*
h;
i++)
1017 tmp_data[
i] = data[
i] / maxval;
1019 draw_pixels (
w,
h, tmp_data);
1023 gl2ps_renderer::draw_pixels (
int w,
int h,
const uint16_t *data)
1031 for (
int i = 0;
i < 3*
w*
h;
i++)
1032 tmp_data[
i] = data[
i] / maxval;
1034 draw_pixels (
w,
h, tmp_data);
1040 if (props.get_string ().isempty ())
1043 draw_text_background (props,
true);
1049 set_color (props.get_color_rgb ());
1057 if (props.horizontalalignment_is (
"center"))
1059 else if (props.horizontalalignment_is (
"right"))
1062 if (props.verticalalignment_is (
"top"))
1064 else if (props.verticalalignment_is (
"baseline"))
1066 else if (props.verticalalignment_is (
"middle"))
1072 const Matrix pos = get_transform ().scale (props.get_data_position ());
1073 std::string str = props.get_string ().string_vector_value ().join (
"\n");
1075 render_text (
str, pos(0), pos(1), pos.
numel () > 2 ? pos(2) : 0.0,
1076 halign, valign, props.get_rotation ());
1091 #if defined (HAVE_GL2PS_H) && defined (HAVE_OPENGL) 1096 bool have_cmd =
stream.length () > 1 &&
stream[0] ==
'|';
1111 error (R
"(print: failed to open pipe "%s")", stream.c_str ()); 1119 fp = std::fopen (
stream.c_str (),
"w");
1122 error (R
"(gl2ps_print: failed to create file "%s")", stream.c_str ()); 1127 gl2ps_renderer rend (fp, term); 1130 rend.set_viewport (pos(2), pos(3));
1137 octave_unused_parameter (fig);
1138 octave_unused_parameter (
stream);
1139 octave_unused_parameter (term);
FILE * octave_popen(const char *command, const char *mode)
virtual void init_marker(const std::string &m, double size, float width)
std::string string_value(bool force=false) const
int octave_pclose(FILE *f)
virtual void set_polygon_offset(bool on, float offset=0.0f)
int octave_ftruncate_wrapper(int fd, off_t sz)
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
virtual void draw(const graphics_object &go, bool toplevel=true)
void add_fcn(void(*fcn)(void))
void error(const char *fmt,...)
Complex atan(const Complex &x)
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
void respond_to_pending_signals(void)
bool isa(const std::string &go_name) const
virtual void draw_axes(const axes::properties &props)
bool valid_object(void) const
nd deftypefn *std::string name
OCTAVE_EXPORT octave_value_list or both For fclose
static octave_value box(JNIEnv *jni_env, void *jobj, void *jcls_arg=nullptr)
virtual bool has_property(const caseless_str &) const
virtual octave_value get(const caseless_str &pname) const
octave_value get(bool all=false) const
std::complex< double > w(std::complex< double > z, double relerr=0)
void gl2ps_print(const graphics_object &fig, const std::string &stream, const std::string &term)
write the output to stdout if nargout otherwise return the output in a character string able ode tem append Append to the destination instead of overwriting tem ascii Save a matrix in a text file without a header or any other information The matrix must be D and only the real part of any complex value is written to the file Numbers are stored in single precision format and separated by spaces Additional options for the and gzip can also be used to convert the files for backward compatibility This option is only available if Octave was built with a link to the zlib libraries end table The list of variables to save may use wildcard patterns containing the following special characters
FILE * octave_tmpfile_wrapper(void)
base_properties & get_properties(void)
T::size_type strlen(const typename T::value_type *str)
virtual void set_linestyle(const std::string &s, bool stipple=false, double linewidth=0.5)
static uint32_t state[624]
void warning(const char *fmt,...)
octave::unwind_protect frame
octave_value xtolower(void) const
charNDArray max(char d, const charNDArray &m)
virtual void set_linejoin(const std::string &)
double double_value(bool frc_str_conv=false) const
the element is set to zero In other the statement xample y
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
static graphics_object get_object(double val)
ColumnVector transform(const Matrix &m, double x, double y, double z)
bool is_double_type(void) const
bool strncmp(const T &str_a, const T &str_b, const typename T::size_type n)
True if the first N characters are the same.
octave_idx_type numel(void) const
Number of elements in the array.
virtual void set_font(const base_properties &props)
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
bool get_is2D(bool include_kids=false) const
bool is_scalar_type(void) const
Matrix matrix_value(bool frc_str_conv=false) const
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x