changeset 27254:e3d886685813

Let graphics toolkit compute the extent of uicontrol text strings (bug #48446) * graphics-toolkit.h (base_graphics_toolkit::get_text_extent, graphics_toolkit::get_text_extent): New virtual methods. * Backend.h, Backend.cc (Backend::get_text_extent): Reimplement virtual method. Compute the extent based on the string property of uicontrol objects. * graphics.cc (uicontrol::properties::get_text_extent): Use toolkit method rather than a freetype text renderer. * genpropdoc.m: Document the uicontrol "extent" property.
author Pantxo Diribarne <pantxo.diribarne@gmail.com>
date Thu, 11 Jul 2019 15:46:18 +0200
parents 23523700b6b8
children 420611c61298
files doc/interpreter/genpropdoc.m libgui/graphics/Backend.cc libgui/graphics/Backend.h libinterp/corefcn/graphics-toolkit.h libinterp/corefcn/graphics.cc
diffstat 5 files changed, 71 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/genpropdoc.m	Mon Jul 15 13:04:31 2019 -0700
+++ b/doc/interpreter/genpropdoc.m	Thu Jul 11 15:46:18 2019 +0200
@@ -1683,6 +1683,11 @@
       case "cdata"
       case "enable"
       case "extent"
+        s.doc = "Size of the text string associated to the uicontrol \
+ returned in the form @code{[0 0 width height]} (the two first elements \
+are always zero).\n\n\
+For multi-line strings the returned @code{width} and @code{height} \
+indicate the size of the rectangle enclosing all lines.";
         s.valid = valid_4elvec;
         s.printdefault = false;
 
--- a/libgui/graphics/Backend.cc	Mon Jul 15 13:04:31 2019 -0700
+++ b/libgui/graphics/Backend.cc	Thu Jul 11 15:46:18 2019 +0200
@@ -27,6 +27,7 @@
 #include <cstdint>
 
 #include <QApplication>
+#include <QFontMetrics>
 #include <QThread>
 
 #include "Backend.h"
@@ -34,6 +35,7 @@
 #include "Object.h"
 #include "ObjectFactory.h"
 #include "ObjectProxy.h"
+#include "QtHandlesUtils.h"
 
 //#if INTPTR_MAX == INT32_MAX
 //# define OCTAVE_PTR_TYPE octave_uint32
@@ -234,6 +236,56 @@
     return retval;
   }
 
+  Matrix
+  Backend::get_text_extent (const graphics_object& go) const
+  {
+    Matrix ext (1, 4, 0.0);
+
+    if (go.isa ("uicontrol"))
+      {
+        octave_value str = go.get ("string");
+        if (! str.isempty ())
+          {
+            const uicontrol::properties& up =
+              dynamic_cast<const uicontrol::properties&> (go.get_properties ());
+            Matrix bb = up.get_boundingbox (false);
+            QFont font = Utils::computeFont<uicontrol> (up, bb(3));
+            QFontMetrics fm (font);
+
+            QString s;
+            QSize sz;
+
+            if (str.is_string ())
+              {
+                s = QString::fromStdString (str.string_value ());
+                sz = fm.size (Qt::TextSingleLine, s);
+                ext(2) = sz.width ();
+                ext(3) = sz.height ();
+              }
+            else if (str.iscellstr ())
+              {
+                string_vector sv = str.string_vector_value ();
+                double wd = 0.0;
+                double hg = 0.0;
+                for (octave_idx_type ii = 0; ii < sv.numel (); ii++)
+                  {
+                    s = QString::fromStdString (sv(ii));
+                    sz = fm.size (Qt::TextSingleLine, s);
+                    wd = std::max (wd, static_cast<double> (sz.width ()));
+                    hg = std::max (hg, static_cast<double> (sz.height ()));
+                  }
+
+                ext(2) = wd;
+                // FIXME: Find a better way to determine the height of e.g.
+                // listbox uicontrol objects
+                ext(3) = hg * sv.numel ();
+              }
+          }
+      }
+
+    return ext;
+  }
+
   Object*
   Backend::toolkitObject (const graphics_object& go)
   {
--- a/libgui/graphics/Backend.h	Mon Jul 15 13:04:31 2019 -0700
+++ b/libgui/graphics/Backend.h	Thu Jul 11 15:46:18 2019 +0200
@@ -63,6 +63,8 @@
 
     uint8NDArray get_pixels (const graphics_object& go) const;
 
+    Matrix get_text_extent (const graphics_object& go) const;
+
     static Object * toolkitObject (const graphics_object& go);
 
     static ObjectProxy * toolkitObjectProxy (const graphics_object& go);
--- a/libinterp/corefcn/graphics-toolkit.h	Mon Jul 15 13:04:31 2019 -0700
+++ b/libinterp/corefcn/graphics-toolkit.h	Thu Jul 11 15:46:18 2019 +0200
@@ -87,6 +87,12 @@
     return Matrix (1, 2, 0.0);
   }
 
+  virtual Matrix get_text_extent (const graphics_object&) const
+  {
+    gripe_if_tkit_invalid ("get_text_extent");
+    return Matrix ();
+  }
+
   // Callback function executed when the given graphics object
   // changes.  This allows the graphics toolkit to act on property
   // changes if needed.
@@ -198,6 +204,9 @@
   Matrix get_screen_size (void) const
   { return rep->get_screen_size (); }
 
+  Matrix get_text_extent (const graphics_object& go) const
+  { return rep->get_text_extent (go); }
+
   // Notifies graphics toolkit that object't property has changed.
   void update (const graphics_object& go, int id)
   { rep->update (go, id); }
--- a/libinterp/corefcn/graphics.cc	Mon Jul 15 13:04:31 2019 -0700
+++ b/libinterp/corefcn/graphics.cc	Thu Jul 11 15:46:18 2019 +0200
@@ -10535,32 +10535,10 @@
 void
 uicontrol::properties::update_text_extent (void)
 {
-  octave::text_element *elt;
-  octave::text_renderer txt_renderer;
-  Matrix box;
-
-  // FIXME: parsed content should be cached for efficiency
   // FIXME: support multiline text
-
-  elt = octave::text_parser::parse (get_string_string (), "none");
-
-  gh_manager::auto_lock guard;
-  txt_renderer.set_font (get_fontname (), get_fontweight (),
-                         get_fontangle (), get_fontsize ());
-
-  box = txt_renderer.get_extent (elt, 0);
-
-  delete elt;
-
-  Matrix ext (1, 4);
-
-  // FIXME: also handle left and bottom components
-
-  ext(0) = ext(1) = 1;
-  ext(2) = box(0);
-  ext(3) = box(1);
-
-  set_extent (ext);
+  graphics_object go = gh_manager::get_object (get___myhandle__ ());
+
+  set_extent (go.get_toolkit ().get_text_extent (go));
 }
 
 void