diff libinterp/corefcn/gl-render.cc @ 25889:2da65009cc7f

Fix graphics object selection on high resolution screens (bug #49053) * gl-render.cc/h (opengl_renderer::set_device_pixel_ratio ()): New public method to set device pixel ratio independent of the actual __device_pixel_ratio__. (opengl_renderer::get_viewport_scaled): New convenience method for fetching the current viewport and scaling it (avoids code duplication). (opengl_renderer::setup_opengl_transformation, opengl_renderer::init_marker, opengl_renderer::draw_text_background): Make use of get_viewport_scaled. (opengl_renderer::draw_text_background): unscale the text bbox before computing background coordinates. * GLCanvas.cc (GLCanvas::selectFromAxes): Draw at scale 1 since mouse event return logical coordinates, not actual device pixels. * gl-select (opengl_selector::apply_pick_matrix): Make use of get_viewport_scaled. * Figure.cc (Figure::screenChanged): Force redraw after a screen change.
author Pantxo Diribarne <pantxo.diribarne@gmail.com>
date Thu, 20 Sep 2018 21:15:40 +0200
parents 4e108574385c
children c1cd5561d1dc
line wrap: on
line diff
--- a/libinterp/corefcn/gl-render.cc	Tue Sep 18 21:53:14 2018 +0200
+++ b/libinterp/corefcn/gl-render.cc	Thu Sep 20 21:15:40 2018 +0200
@@ -613,12 +613,11 @@
 #endif
 
   opengl_renderer::opengl_renderer (opengl_functions& glfcns)
-    : m_glfcns (glfcns), toolkit (), xform (), xmin (), xmax (),
-      ymin (), ymax (), zmin (), zmax (), xZ1 (), xZ2 (),
-      marker_id (), filled_marker_id (), camera_pos (), camera_dir (),
-      view_vector (), interpreter ("none"), txt_renderer (),
-      m_current_light (0), m_max_lights (0), selecting (false),
-      m_devpixratio (1.)
+    : m_glfcns (glfcns), toolkit (), xform (), xmin (), xmax (), ymin (),
+      ymax (), zmin (), zmax (), xZ1 (), xZ2 (), marker_id (),
+      filled_marker_id (), camera_pos (), camera_dir (), view_vector (),
+      interpreter ("none"), txt_renderer (), m_current_light (0),
+      m_max_lights (0), selecting (false), m_devpixratio (1.)
   {
     // This constructor will fail if we don't have OpenGL or if the data
     // types we assumed in our public interface aren't compatible with the
@@ -703,11 +702,8 @@
   void
   opengl_renderer::draw_figure (const figure::properties& props)
   {
-    // Current physical-pixel to toolkit-pixel factor
-    m_devpixratio = props.get___device_pixel_ratio__ ();
-    
     // Initialize OpenGL context
-    
+
     init_gl_context (props.is_graphicssmoothing (), props.get_color_rgb ());
 
 #if defined (HAVE_OPENGL)
@@ -1212,14 +1208,6 @@
     Matrix x_mat1 = props.get_opengl_matrix_1 ();
     Matrix x_mat2 = props.get_opengl_matrix_2 ();
 
-#if defined (HAVE_FRAMEWORK_OPENGL)
-    GLint vw[4];
-#else
-    int vw[4];
-#endif
-
-    m_glfcns.glGetIntegerv (GL_VIEWPORT, vw);
-
     m_glfcns.glMatrixMode (GL_MODELVIEW);
     m_glfcns.glLoadIdentity ();
     m_glfcns.glScaled (1, 1, -1);
@@ -1227,11 +1215,8 @@
     m_glfcns.glMatrixMode (GL_PROJECTION);
     m_glfcns.glLoadIdentity ();
 
-     // Use abstract Octave-pixels for transformation, not physical-pixels
-     vw[2] = octave::math::round (static_cast<float> (vw[2]) / m_devpixratio);
-     vw[3] = octave::math::round (static_cast<float> (vw[3]) / m_devpixratio);
-
-    m_glfcns.glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
+    Matrix vp = get_viewport_scaled ();
+    m_glfcns.glOrtho (0, vp(2), vp(3), 0, xZ1, xZ2);
     m_glfcns.glMultMatrixd (x_mat2.data ());
     m_glfcns.glMatrixMode (GL_MODELVIEW);
 
@@ -3678,28 +3663,17 @@
     if (bgcol.isempty () && ecol.isempty ())
       return;
 
-    Matrix pos = xform.scale (props.get_data_position ());
+    Matrix pos = props.get_data_position ();
     ColumnVector pixpos = get_transform ().transform (pos(0), pos(1),
-                                                      pos(2), false);
-    const Matrix bbox = props.get_extent_matrix ();
-
-#  if defined (HAVE_FRAMEWORK_OPENGL)
-    GLint vp[4];
-#  else
-    int vp[4];
-#  endif
-
-    m_glfcns.glGetIntegerv (GL_VIEWPORT, vp);
+                                                      pos(2), true);
 
     // Save current transform matrices and set orthogonal window coordinates
     m_glfcns.glMatrixMode (GL_PROJECTION);
     m_glfcns.glPushMatrix ();
     m_glfcns.glLoadIdentity ();
 
-    vp[2] = octave::math::round (static_cast<float> (vp[2]) / m_devpixratio);
-    vp[3] = octave::math::round (static_cast<float> (vp[3]) / m_devpixratio);
-
-    m_glfcns.glOrtho (0, vp[2], vp[3], 0, xZ1, xZ2);
+    Matrix vp = get_viewport_scaled ();
+    m_glfcns.glOrtho (0, vp(2), vp(3), 0, xZ1, xZ2);
     m_glfcns.glMatrixMode (GL_MODELVIEW);
     m_glfcns.glPushMatrix ();
     m_glfcns.glLoadIdentity ();
@@ -3716,10 +3690,11 @@
       m_glfcns.glRotated (-rotation, 0.0, 0.0, 1.0);
 
     double m = props.get_margin ();
-    double x0 = bbox (0) - m;
-    double x1 = x0 + bbox(2) + 2 * m;
-    double y0 = -(bbox (1) - m);
-    double y1 = y0 - (bbox(3) + 2 * m);
+    const Matrix bbox = props.get_extent_matrix ();
+    double x0 = bbox (0) / m_devpixratio - m;
+    double x1 = x0 + bbox(2) / m_devpixratio + 2 * m;
+    double y0 = -(bbox (1) / m_devpixratio - m);
+    double y1 = y0 - (bbox(3) / m_devpixratio + 2 * m);
 
     if (! bgcol.isempty ())
       {
@@ -3863,8 +3838,6 @@
       }
     else // clip to viewport
       {
-        GLfloat vp[4];
-        m_glfcns.glGetFloatv (GL_VIEWPORT, vp);
         // FIXME: actually add the code to do it!
       }
 
@@ -3997,6 +3970,35 @@
 #endif
   }
 
+  Matrix
+  opengl_renderer::get_viewport_scaled (void) const
+  {
+    Matrix retval (1, 4, 0.0);
+
+#if defined (HAVE_OPENGL)
+#if defined (HAVE_FRAMEWORK_OPENGL)
+    GLint vp[4];
+#else
+    int vp[4];
+#endif
+
+    m_glfcns.glGetIntegerv (GL_VIEWPORT, vp);
+
+    for (int i = 0; i < 4; i++)
+      retval(i) = static_cast<double> (vp[i]) / m_devpixratio;
+
+#else
+
+    // This shouldn't happen because construction of opengl_renderer
+    // objects is supposed to be impossible if OpenGL is not available.
+
+    panic_impossible ();
+
+#endif
+
+    return retval;
+  }
+
   void
   opengl_renderer::draw_pixels (int width, int height, const float *data)
   {
@@ -4083,7 +4085,7 @@
 
   void
   opengl_renderer::set_font (const base_properties& props)
-  {    
+  {
     txt_renderer.set_font (props.get ("fontname").string_value (),
                            props.get ("fontweight").string_value (),
                            props.get ("fontangle").string_value (),
@@ -4264,23 +4266,12 @@
   opengl_renderer::init_marker (const std::string& m, double size, float width)
   {
 #if defined (HAVE_OPENGL)
-
-#  if defined (HAVE_FRAMEWORK_OPENGL)
-    GLint vw[4];
-#  else
-    int vw[4];
-#  endif
-
-    m_glfcns.glGetIntegerv (GL_VIEWPORT, vw);
-
     m_glfcns.glMatrixMode (GL_PROJECTION);
     m_glfcns.glPushMatrix ();
     m_glfcns.glLoadIdentity ();
 
-    vw[2] = octave::math::round (static_cast<float> (vw[2]) / m_devpixratio);
-    vw[3] = octave::math::round (static_cast<float> (vw[3]) / m_devpixratio);
-
-    m_glfcns.glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
+    Matrix vp = get_viewport_scaled ();
+    m_glfcns.glOrtho (0, vp(2), vp(3), 0, xZ1, xZ2);
     m_glfcns.glMatrixMode (GL_MODELVIEW);
     m_glfcns.glPushMatrix ();