Details

    • Type: Enhancement
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 7u6
    • Fix Version/s: 8
    • Component/s: javafx

      Description

      com.sun.javafx.scene.control.skin.Utils has a method, computeClippedText, with the following loop:


                      for (int i = start; !done ; i += stepValue) {
                          index = i;
                          char c = text.charAt(index);
                          total = computeTextWidth(font,
                                                   (start == 0) ? text.substring(0, i + 1)
                                                                : text.substring(i, start + 1),
                                                   0);
                          if (Character.isWhitespace(c)) {
                              whitespaceIndex = index;
                          }
                          if (total > availableWidth) {
                              break;
                          }
                          done = start == 0? i >= end : i <= end;
                      }


      This loop is highly inefficient in that it both requires multiple substring calls and also because it invokes computeTextWidth repeatedly for each character position. computeTextWidth modifies a Text node, then gets its layout bounds:


          static double computeTextWidth(Font font, String text, double wrappingWidth) {
              helper.setText(text);
              helper.setFont(font);
              // Note that the wrapping width needs to be set to zero before
              // getting the text's real preferred width.
              helper.setWrappingWidth(0);
              double w = Math.min(helper.prefWidth(-1), wrappingWidth);
              helper.setWrappingWidth((int)Math.ceil(w));
              return Math.ceil(helper.getLayoutBounds().getWidth());
          }

      This code path is atrocious in terms of performance :-). For each character in a string, we are going to create a new String, make a method invocation, setup a Text node, ask for its preferred width, do a couple Math.ceil, and then get the layout bounds (creating a Bounds object). Do this in an interpreter and you get some hammered text performance.

      Now, in the case that a String is < the width, we don't get into this pathological case. Although I remember having seen times when the width was the same, and thus we did hit the pathological case, even though in the end the text fit fine. I believe this would happen because we sized the label to be the same size as the text node (that is, this is the preferred size) and so we end up going throughout he pathological case just to find out we don't need ellipses.

      The situation may have changed from the last time I looked, but I believe this to still be an issue

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                leifs Leif Samuelsson (Inactive)
                Reporter:
                rbair Richard Bair
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Due:
                  Created:
                  Updated:
                  Resolved:
                  Imported: