Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6990683

Font system needs to better handle NULL returns on error conditions

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Not an Issue
    • Affects Version/s: 6u10, 6u17, 6u18, 7
    • Fix Version/s: tbd
    • Component/s: client-libs
    • Subcomponent:
      2d
    • CPU:
      generic, x86
    • OS:
      generic, windows_xp, windows_vista

      Description

      6921591 demonstrated a NPE as a result using a legitimate glyph
      of a standard JRE font. This was resolved under bug 6921593 so
      that NPE is no longer reproducible since that bug was fixed.
      However 6921591 has some discussion that is worth capturing in a
      new bug, to remove any confusion as to whether that NPE regression exists.

      The relevant discussion is based on notes from the eval of that bug.

      The issue is that on genuine errors in the underlying font, T2K may return
      null objects.

      The Java layer and the clients do not always handle this gracefully.
      Either the native T2K glue layer (in scalerMethods.c etc) needs to return
      some better default value, like a (0,0) point in the case of getGlyphPoint()
      or the calling layer needs to always check for "null" and do something similar.

      Also there was this series of comments below relating to a lack of robustness in
      the layout code. However I am not able to get to this exception using the
      test case below. JDk 7 b99 doesn't get past the NPE. Later builds work fine.
      May need a different test case.

      ---------------------------


      I am getting following exception with latest JDK7 (b99+):

      Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
              at java.awt.font.LineBreakMeasurer.nextOffset(LineBreakMeasurer.java:365)
              at java.awt.font.LineBreakMeasurer.nextOffset(LineBreakMeasurer.java:328)
              at sun.swing.SwingUtilities2.clipString(SwingUtilities2.java:467)
              at javax.swing.SwingUtilities.layoutCompoundLabelImpl(SwingUtilities.java:1017)
              at javax.swing.SwingUtilities.layoutCompoundLabel(SwingUtilities.java:886)
              at javax.swing.plaf.basic.BasicLabelUI.layoutCL(BasicLabelUI.java:94)
              at javax.swing.plaf.basic.BasicLabelUI.layout(BasicLabelUI.java:201)
              at javax.swing.plaf.basic.BasicLabelUI.paint(BasicLabelUI.java:164)
              at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
              at javax.swing.JComponent.paintComponent(JComponent.java:778)
              at Bug$1$1.setText(Bug.java:17)
              at Bug$1.run(Bug.java:22)
              at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
              at java.awt.EventQueue.dispatchEvent(EventQueue.java:649)
              at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:255)
              at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:170)
              at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:160)
              at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:155)
              at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
              at java.awt.EventDispatchThread.run(EventDispatchThread.java:136)

      import java.awt.Font;
      import java.awt.image.BufferedImage;
      import javax.swing.JLabel;
      import javax.swing.SwingUtilities;

      public class Bug {

              public static void main(String a[]) {
                 SwingUtilities.invokeLater(new Runnable() {

                  public void run() {
                      final BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
                      final JLabel jLabel = new JLabel() {
                              @Override
                              public void setText(final String text) {
                                      super.setText(text);
                                      paintComponent(image.getGraphics());
                              }
                      };
                      jLabel.setFont(Font.decode("Dialog"));
                      final char[] chars = Character.toChars(2375);
                      jLabel.setText(String.valueOf(chars));
                  }
              });
              }

      }


      It turns out that ExtendedTextLabel may return -1 for line break position:

      ====
        /**
         * Return the logical index of the character, starting with the character at
         * logicalStart, whose accumulated advance exceeds width. If the advances of
         * all characters do not exceed width, return getNumCharacters. If width is
         * less than zero, return logicalStart - 1.
         */
        public abstract int getLineBreakIndex(int logicalStart, float width);
      ====

      That cause TextMeasurer.getLineBreakIndex() to return -1 too and this causes out of bounds exception.

      Even if T2K code will be fixed to return non null objects it is still legitimate case that overall width is negative.
      TextMeasurer logic needs to be improved to handle it.

      Perhaps the fix could be to check return value of tlc.getLineBreakIndex in the TextMeasurer.calcLineBreak() and
      interpret is as "full string can be drawn before line break"?

      ---------------------------

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                prr Philip Race
                Reporter:
                prr Philip Race
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: