# HG changeset patch
# User Pantxo Diribarne <pantxo.diribarne@gmail.com>
# Date 1500584367 -7200
#      Thu Jul 20 22:59:27 2017 +0200
# Node ID 7687af29be84f6048764bb50460463b3a4bbd112
# Parent  7a10975104393614b0c273fa3f3c854a2f2065e9
Fix regression introduced by cset 06805aabbdd1 (bug #50750)

* graphics.in.h(axes::properties::has3Dkids, axes::properties::set_has3Dkids): 
  new private attribute and corresponding setter
  (axes::properties::get_is2D): add bool argument to specify wether to include
  kids in the dimensionality check. Make use of new "has3Dkids" when necessary
* graphics.cc (axes::update_axis_limits): set has3Dkids attribute based on 
  z limits. Allow zlim to be checked (but unchanged) even when zlimmode is 
  manual and add a FIXME note.
* gl2ps-print.cc (gl2ps_renderer::has_2D_axes): new method to check all axes
  are 2D.
  (gl2ps_renderer::draw): choose sorting algorithm depending on has_2D_axes
* __opengl_print__.m: don't check dimensionality here.
* gl-render.cc (opengl_renderer::draw_axes): include children in dimensionality
  check

diff -r 7a1097510439 -r 7687af29be84 libinterp/corefcn/gl-render.cc
--- a/libinterp/corefcn/gl-render.cc	Mon Jul 24 16:48:03 2017 +0200
+++ b/libinterp/corefcn/gl-render.cc	Thu Jul 20 22:59:27 2017 +0200
@@ -2108,8 +2108,9 @@
 
     setup_opengl_transformation (props);
 
-    // For 2D axes, draw from back to front without depth sorting
-    bool is2D = props.get_is2D ();
+    // For 2D axes with only 2D primitives, draw from back to front without 
+    // depth sorting
+    bool is2D = props.get_is2D (true);
     if (is2D)
       glDisable (GL_DEPTH_TEST);
     else
diff -r 7a1097510439 -r 7687af29be84 libinterp/corefcn/gl2ps-print.cc
--- a/libinterp/corefcn/gl2ps-print.cc	Mon Jul 24 16:48:03 2017 +0200
+++ b/libinterp/corefcn/gl2ps-print.cc	Thu Jul 20 22:59:27 2017 +0200
@@ -201,6 +201,35 @@
     bool buffer_overflow;
   };
 
+  static bool
+  has_2D_axes (const graphics_handle& h)
+  {
+    bool retval = true;
+    graphics_object go = gh_manager::get_object (h);
+  
+    if (! go.valid_object ())
+      return retval;
+
+    if (go.isa ("figure") || go.isa ("uipanel"))
+      {
+        Matrix  children = go.get ("children").matrix_value ();
+        for (octave_idx_type ii = 0; ii < children.numel (); ii++)
+          {
+            retval = has_2D_axes (graphics_handle (children(ii)));
+            if (! retval)
+              break;
+          }
+      }
+    else if (go.isa ("axes"))
+      {
+        axes::properties& ap
+          = reinterpret_cast<axes::properties&> (go.get_properties ());
+        retval = ap.get_is2D (true);
+      }
+
+    return retval;
+  }
+
   void
   gl2ps_renderer::draw (const graphics_object& go, const std::string& print_cmd)
   {
@@ -240,10 +269,9 @@
         // Default sort order optimizes for 3D plots
         GLint gl2ps_sort = GL2PS_BSP_SORT;
 
-        // For 2D plots we can use a simpler Z-depth sorting algorithm
         // FIXME: gl2ps does not provide a way to change the sorting algorythm
         // on a viewport basis, we thus disable sorting only if all axes are 2D
-        if (term.find ("is2D") != std::string::npos)
+        if (has_2D_axes (go.get ("__myhandle__")))
           gl2ps_sort = GL2PS_NO_SORT;
 
         // Use a temporary file in case an overflow happens
diff -r 7a1097510439 -r 7687af29be84 libinterp/corefcn/graphics.cc
--- a/libinterp/corefcn/graphics.cc	Mon Jul 24 16:48:03 2017 +0200
+++ b/libinterp/corefcn/graphics.cc	Thu Jul 20 22:59:27 2017 +0200
@@ -7558,12 +7558,24 @@
 
           get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
 
+          xproperties.set_has3Dkids ((max_val - min_val) > 
+                                      std::numeric_limits<double>::epsilon ());
+
           limits = xproperties.get_axis_limits (min_val, max_val,
                                                 min_pos, max_neg,
                                                 xproperties.zscale_is ("log"));
 
           update_type = 'z';
         }
+      else
+        {
+          // FIXME: get_children_limits is only needed here in order to know 
+          // if there are 3D children. Is there a way to avoid this call?
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
+
+          xproperties.set_has3Dkids ((max_val - min_val) > 
+                                      std::numeric_limits<double>::epsilon ());
+        }
     }
   else if (axis_type == "cdata" || axis_type == "climmode"
            || axis_type == "cdatamapping" || axis_type == "climinclude"
@@ -7727,12 +7739,24 @@
         {
           get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
 
+          xproperties.set_has3Dkids ((max_val - min_val) > 
+                                      std::numeric_limits<double>::epsilon ());
+
           limits = xproperties.get_axis_limits (min_val, max_val,
                                                 min_pos, max_neg,
                                                 xproperties.zscale_is ("log"));
 
           update_type = 'z';
         }
+      else
+        {
+          // FIXME: get_children_limits is only needed here in order to know 
+          // if there are 3D children. Is there a way to avoid this call?
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
+
+          xproperties.set_has3Dkids ((max_val - min_val) > 
+                                      std::numeric_limits<double>::epsilon ());
+        }
     }
   else if (axis_type == "cdata" || axis_type == "climmode"
            || axis_type == "cdatamapping" || axis_type == "climinclude"
diff -r 7a1097510439 -r 7687af29be84 libinterp/corefcn/graphics.in.h
--- a/libinterp/corefcn/graphics.in.h	Mon Jul 24 16:48:03 2017 +0200
+++ b/libinterp/corefcn/graphics.in.h	Thu Jul 20 22:59:27 2017 +0200
@@ -3483,7 +3483,9 @@
     bool get_x2Dtop (void) const { return x2Dtop; }
     bool get_y2Dright (void) const { return y2Dright; }
     bool get_layer2Dtop (void) const { return layer2Dtop; }
-    bool get_is2D (void) const { return is2D; }
+    bool get_is2D (bool include_kids = false) const
+    { return (include_kids ? (is2D && ! has3Dkids) : is2D); }
+    void set_has3Dkids (bool val) { has3Dkids = val; }
     bool get_xySym (void) const { return xySym; }
     bool get_xyzSym (void) const { return xyzSym; }
     bool get_zSign (void) const { return zSign; }
@@ -3574,6 +3576,7 @@
     bool y2Dright = false;
     bool layer2Dtop = false;
     bool is2D = false;
+    bool has3Dkids = false;
     bool xySym = false;
     bool xyzSym = false;
     bool zSign = false;
diff -r 7a1097510439 -r 7687af29be84 scripts/plot/util/private/__opengl_print__.m
--- a/scripts/plot/util/private/__opengl_print__.m	Mon Jul 24 16:48:03 2017 +0200
+++ b/scripts/plot/util/private/__opengl_print__.m	Thu Jul 20 22:59:27 2017 +0200
@@ -148,17 +148,6 @@
 
   opts.pipeline = pipeline;
 
-  ## Tell gl2ps to use different rendering options for 2D plots
-  haxes = findall (opts.figure, "type", "axes");
-  vw = get (haxes, "view");
-  if (iscell (vw))
-    vw = vertcat (vw{:});
-  endif
-  is2D = all (abs (vw(:,2)) == 90);
-  if (is2D)
-    gl2ps_device{end} = [gl2ps_device{end}, "is2D"];
-  endif
-
   for n = 1:numel (pipeline)
     if (opts.debug)
       fprintf ("opengl-pipeline: '%s'\n", pipeline{n});
