# HG changeset patch
# User Pantxo Diribarne <pantxo.diribarne@gmail.com>
# Date 1448578663 -3600
#      Thu Nov 26 23:57:43 2015 +0100
# Node ID 01e1a82227e8e7977d5ecffb3eb04a52b2f9658d
# Parent  5c5e085a1ae637137035c5f5f4dea585d6d0c15d
Fix overflowing feedback buffers (bug #46417)

* gl2ps-renderer.h (glps_renderer::glps_renderer): change interface, remove
    first argument. 
* gl2ps-renderer.h (glps_renderer::draw_axes): handle errors and warnings 
    after gl2psEndViewport.
* gl2ps-renderer.h (glps_renderer::buffer_overflow): new bool attribute.
* gl2ps-renderer.cc (glps_renderer::draw): make use of buffer_overflow to 
    detect overflows
* gl2ps-renderer.cc (glps_renderer::draw): open a new pipe before each trial
* gl2ps-renderer.cc (glps_renderer::draw): remove error checking after 
    gl2pEndPage

* __osmesa_print__.cc (F__osmesa_print__): simplify function and use gl2ps_print

diff -r 5c5e085a1ae6 -r 01e1a82227e8 libinterp/corefcn/gl2ps-renderer.cc
--- a/libinterp/corefcn/gl2ps-renderer.cc	Sun Nov 29 00:01:21 2015 +0100
+++ b/libinterp/corefcn/gl2ps-renderer.cc	Thu Nov 26 23:57:43 2015 +0100
@@ -39,6 +39,13 @@
 #include "gl2ps.h"
 #include "sysdep.h"
 
+static void
+safe_pclose (FILE *f)
+{
+  if (f)
+    octave_pclose (f);
+}
+
 void
 glps_renderer::draw (const graphics_object& go, const std::string& print_cmd)
 {
@@ -83,11 +90,21 @@
       if (term.find ("is2D") != std::string::npos)
         gl2ps_sort = GL2PS_SIMPLE_SORT;
 
-      GLint state = GL2PS_OVERFLOW;
       GLint buffsize = 0;
+      buffer_overflow = true;
 
-      while (state == GL2PS_OVERFLOW)
+      while (buffer_overflow)
         {
+          buffsize += 1024*1024;
+          buffer_overflow = false;
+
+          // Open pipe
+          FILE *fp = octave_popen (print_cmd.c_str (), "w");
+          if (fp)
+            frame.add_fcn (safe_pclose, fp);
+          else
+            error ("print: failed to open pipe for gl2ps renderer");
+
           // For LaTeX output the fltk print process uses 2 drawnow() commands.
           // The first one is for the pdf/ps/eps graph to be included.  The
           // print_cmd is saved as old_print_cmd.  Then the second drawnow()
@@ -114,8 +131,6 @@
           else
             include_graph = "foobar-inc";
 
-          buffsize += 1024*1024;
-
           // GL2PS_SILENT was removed to allow gl2ps printing errors on stderr
           GLint ret = gl2psBeginPage ("glps_renderer figure", "Octave", 0,
                                       gl2ps_term, gl2ps_sort,
@@ -138,21 +153,10 @@
 
           opengl_renderer::draw (go);
 
-          // Without glFinish () there may be primitives missing in the
-          // gl2ps output.
-          glFinish ();
+          if (buffer_overflow)
+            old_print_cmd.clear ();
 
-          state = gl2psEndPage ();
-
-          if (state == GL2PS_ERROR)
-            {
-              old_print_cmd.clear ();
-              error ("gl2ps-renderer::draw: gl2psEndPage returned GL2PS_ERROR");
-              return;
-            }
-
-          // Don't check state for GL2PS_UNINITIALIZED (should never happen)
-          // GL2PS_OVERFLOW (see while loop) or GL2PS_SUCCESS
+          gl2psEndPage ();
         }
     }
   else
@@ -618,13 +622,6 @@
                halign, valign, props.get_rotation ());
 }
 
-static void
-safe_pclose (FILE *f)
-{
-  if (f)
-    octave_pclose (f);
-}
-
 #endif
 
 void
@@ -633,20 +630,8 @@
 {
 #ifdef HAVE_GL2PS_H
 
-  FILE *fp = octave_popen (cmd.c_str (), "w");
-
-  if (fp)
-    {
-      unwind_protect frame;
-
-      frame.add_fcn (safe_pclose, fp);
-
-      glps_renderer rend (fp, term);
-
-      rend.draw (fig, cmd);
-    }
-  else
-    error ("print: failed to open pipe for gl2ps renderer");
+  glps_renderer rend (term);
+  rend.draw (fig, cmd);
 
 #else
 
diff -r 5c5e085a1ae6 -r 01e1a82227e8 libinterp/corefcn/gl2ps-renderer.h
--- a/libinterp/corefcn/gl2ps-renderer.h	Sun Nov 29 00:01:21 2015 +0100
+++ b/libinterp/corefcn/gl2ps-renderer.h	Thu Nov 26 23:57:43 2015 +0100
@@ -35,9 +35,9 @@
 glps_renderer : public opengl_renderer
 {
 public:
-  glps_renderer (FILE *_fp, const std::string& _term)
-    : opengl_renderer () , fp (_fp), term (_term), fontsize (),
-    fontname () { }
+  glps_renderer (const std::string& _term)
+    : opengl_renderer (), term (_term), fontsize (),
+    fontname (), buffer_overflow (false) { }
 
   ~glps_renderer (void) { }
 
@@ -66,7 +66,11 @@
     // Finalize viewport
     GLint state = gl2psEndViewport ();
     if (state == GL2PS_NO_FEEDBACK)
-      warning ("gl2ps-renderer::draw: empty feedback buffer and/or nothing else to print");
+      warning ("gl2ps-renderer::draw_axes: empty feedback buffer and/or nothing else to print");
+    else if (state == GL2PS_ERROR)
+      error ("gl2ps-renderer::draw_axes: gl2psEndViewport returned GL2PS_ERROR");
+    else 
+      buffer_overflow |= (state == GL2PS_OVERFLOW);
   }
 
   void draw_text (const text::properties& props);
@@ -111,10 +115,10 @@
 
 private:
   int alignment_to_mode (int ha, int va) const;
-  FILE *fp;
   caseless_str term;
   double fontsize;
   std::string fontname;
+  bool buffer_overflow;
 };
 
 #endif  // HAVE_GL2PS_H
diff -r 5c5e085a1ae6 -r 01e1a82227e8 libinterp/dldfcn/__osmesa_print__.cc
--- a/libinterp/dldfcn/__osmesa_print__.cc	Sun Nov 29 00:01:21 2015 +0100
+++ b/libinterp/dldfcn/__osmesa_print__.cc	Thu Nov 26 23:57:43 2015 +0100
@@ -43,11 +43,6 @@
 #endif
 
 #if defined (HAVE_OSMESA) && defined (HAVE_OPENGL)
-static void
-close_fcn (FILE *f)
-{
-  gnulib::fclose (f);
-}
 
 static void
 reset_visibility (figure::properties *fp)
@@ -185,36 +180,17 @@
       size_t pos_p = file.find_first_of ("|");
       size_t pos_c = file.find_first_not_of ("| ");
 
+      std::string cmd;
       if (pos_p == std::string::npos && pos_c == std::string::npos)
         error ("__osmesa_print__: empty output ''");
       else if (pos_c == std::string::npos)
         error ("__osmesa_print__: empty pipe '|'");
       else if (pos_p != std::string::npos && pos_p < pos_c)
-        {
-          // create process and pipe gl2ps output to it
-          std::string cmd = file.substr (pos_c);
-          gl2ps_print (fobj, cmd, term);
-        }
+        cmd = file.substr (pos_c);
       else
-        {
-          // write gl2ps output directly to file
-          FILE *filep = gnulib::fopen (file.substr (pos_c).c_str (), "w");
+        cmd = "cat > " + file.substr (pos_c);
 
-          if (filep)
-            {
-              unwind_protect frame;
-
-              frame.add_fcn (close_fcn, filep);
-
-              glps_renderer rend (filep, term);
-              rend.draw (fobj, "");
-
-              // Make sure buffered commands are finished!!!
-              glFinish ();
-            }
-          else
-            error ("__osmesa_print__: Couldn't create file \"%s\"", file.c_str ());
-        }
+      gl2ps_print (fobj, cmd, term);
 #endif
     }
   else
