--- old/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java 2016-01-25 00:12:38.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java 2016-01-25 00:12:38.000000000 +0400 @@ -415,7 +415,9 @@ /*** paint the text disabled ***/ g.setColor(defaultDisabledTextColor); } - SwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemonicIndex, localTextRect.x, localTextRect.y + fm.getAscent()); + getTextUIDrawing().drawStringUnderlineCharAt(c, g, text, mnemonicIndex, + localTextRect.x, + localTextRect.y + fm.getAscent()); } protected void paintText(final Graphics g, final AbstractButton b, final Rectangle localTextRect, final String text) { --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRendererInternal.java 2016-01-25 00:12:40.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRendererInternal.java 2016-01-25 00:12:40.000000000 +0400 @@ -153,7 +153,8 @@ if (fChecked && !fEditable && fDrawCheckedItem) { final int y = getHeight() - 4; g.setColor(getForeground()); - SwingUtilities2.drawString(fComboBox, g, "\u2713", 6, y); + SwingUtilities2.getTextUIDrawing(fComboBox) + .drawString(fComboBox, g, "\u2713", 6, y); } } super.paintComponent(g); --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java 2016-01-25 00:12:41.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java 2016-01-25 00:12:41.000000000 +0400 @@ -1076,16 +1076,16 @@ g.fillRect(textX - 1, paintTextR.y, paintTextR.width + 2, fm.getAscent() + 2); g.setColor(getForeground()); - SwingUtilities2.drawString(filechooser, g, clippedText, textX, textY); + getTextUIDrawing().drawString(filechooser, g, clippedText, textX, textY); } else { final Color background = getBackground(); g.setColor(background); g.fillRect(textX - 1, paintTextR.y, paintTextR.width + 2, fm.getAscent() + 2); g.setColor(background.brighter()); - SwingUtilities2.drawString(filechooser, g, clippedText, textX, textY); + getTextUIDrawing().drawString(filechooser, g, clippedText, textX, textY); g.setColor(background.darker()); - SwingUtilities2.drawString(filechooser, g, clippedText, textX + 1, textY + 1); + getTextUIDrawing().drawString(filechooser, g, clippedText, textX + 1, textY + 1); } } } --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java 2016-01-25 00:12:43.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java 2016-01-25 00:12:43.000000000 +0400 @@ -209,7 +209,10 @@ } else { g.setColor(Color.white); } - SwingUtilities2.drawString(frame, g, text, x + startXPosition + iconWidth, y + baseline + 1); + SwingUtilities2.getTextUIDrawing(frame) + .drawString(frame, g, text, + x + startXPosition + iconWidth, + y + baseline + 1); if (isSelected || fIsUtility) { g.setColor(selectedTextColor); @@ -217,7 +220,10 @@ g.setColor(notSelectedTextColor); } - SwingUtilities2.drawString(frame, g, text, x + startXPosition + iconWidth, y + baseline); + SwingUtilities2.getTextUIDrawing(frame) + .drawString(frame, g, text, + x + startXPosition + iconWidth, + y + baseline); g.setFont(f); } --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java 2016-01-25 00:12:44.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java 2016-01-25 00:12:44.000000000 +0400 @@ -276,9 +276,9 @@ } g.setColor(Color.black); - SwingUtilities2.drawString(this, g, text, x, 2 + ascent); + getTextUIDrawing().drawString(this, g, text, x, 2 + ascent); g.setColor(Color.white); - SwingUtilities2.drawString(this, g, text, x, 1 + ascent); + getTextUIDrawing().drawString(this, g, text, x, 1 + ascent); } public void show(final Component invoker) { --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaLabelUI.java 2016-01-25 00:12:46.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaLabelUI.java 2016-01-25 00:12:46.000000000 +0400 @@ -60,7 +60,7 @@ } g.setColor(l.getForeground()); - SwingUtilities2.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); + getTextUIDrawing().drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); } /** @@ -81,7 +81,7 @@ // if our background is still something we set then we can use our happy background color. if (background instanceof UIResource) { g.setColor(getDisabledLabelColor(l)); - SwingUtilities2.drawStringUnderlineCharAt(l, g, s, accChar, textX, textY); + getTextUIDrawing().drawStringUnderlineCharAt(l, g, s, accChar, textX, textY); } else { super.paintDisabledText(l, g, s, textX, textY); } --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuPainter.java 2016-01-25 00:12:48.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuPainter.java 2016-01-25 00:12:47.000000000 +0400 @@ -253,7 +253,7 @@ final int yAccel = acceleratorRect.y + fm.getAscent(); if (modifiersString.equals("")) { // just draw the keyString - SwingUtilities2.drawString(c, g, keyString, acceleratorRect.x, yAccel); + SwingUtilities2.getTextUIDrawing(c).drawString(c, g, keyString, acceleratorRect.x, yAccel); } else { final int modifiers = accelerator.getModifiers(); int underlinedChar = 0; @@ -266,13 +266,19 @@ g.setFont(acceleratorFont); drawString(g, c, modifiersString, underlinedChar, acceleratorRect.x, yAccel, isEnabled, isSelected); g.setFont(f); - SwingUtilities2.drawString(c, g, keyString, acceleratorRect.x + acceleratorRect.width - emWidth, yAccel); + SwingUtilities2.getTextUIDrawing(c) + .drawString(c, g, keyString, + acceleratorRect.x + acceleratorRect.width - emWidth, + yAccel); } else { final int xAccel = acceleratorRect.x + emWidth; g.setFont(acceleratorFont); drawString(g, c, modifiersString, underlinedChar, xAccel, yAccel, isEnabled, isSelected); g.setFont(f); - SwingUtilities2.drawString(c, g, keyString, xAccel - fm.stringWidth(keyString), yAccel); + SwingUtilities2.getTextUIDrawing(c) + .drawString(c, g, keyString, + xAccel - fm.stringWidth(keyString), + yAccel); } } } @@ -425,7 +431,8 @@ else index = (lci < uci) ? lci : uci; } - SwingUtilities2.drawStringUnderlineCharAt(c, g, text, index, x, y); + SwingUtilities2.getTextUIDrawing(c) + .drawStringUnderlineCharAt(c, g, text, index, x, y); } /* --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java 2016-01-25 00:12:49.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java 2016-01-25 00:12:49.000000000 +0400 @@ -204,7 +204,7 @@ if (isHorizontal()) { g2.setColor(selectionForeground); - SwingUtilities2.drawString(progressBar, g2, progressString, renderLocation.x, renderLocation.y); + getTextUIDrawing().drawString(progressBar, g2, progressString, renderLocation.x, renderLocation.y); } else { // VERTICAL // We rotate it -90 degrees, then translate it down since we are going to be bottom up. final AffineTransform savedAT = g2.getTransform(); @@ -214,7 +214,7 @@ // 0,0 is now the bottom left of the viewable area, so we just draw our image at // the render location since that calculation knows about rotation. g2.setColor(selectionForeground); - SwingUtilities2.drawString(progressBar, g2, progressString, renderLocation.x, renderLocation.y); + getTextUIDrawing().drawString(progressBar, g2, progressString, renderLocation.x, renderLocation.y); g2.setTransform(savedAT); } --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneContrastUI.java 2016-01-25 00:12:51.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneContrastUI.java 2016-01-25 00:12:50.000000000 +0400 @@ -71,7 +71,7 @@ g2d.setColor(color); } g2d.setFont(font); - SwingUtilities2.drawString(tabPane, g2d, title, textRect.x, textRect.y + metrics.getAscent()); + getTextUIDrawing().drawString(tabPane, g2d, title, textRect.x, textRect.y + metrics.getAscent()); } protected static Color getSelectedTabTitleColor(boolean enabled, boolean pressed) { --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java 2016-01-25 00:12:52.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java 2016-01-25 00:12:52.000000000 +0400 @@ -212,6 +212,7 @@ // UI Installation/De-installation public void installUI(final JComponent c) { + super.installUI(c); this.tabPane = (JTabbedPane)c; calculatedBaseline = false; @@ -827,7 +828,7 @@ if (scrollableTabLayoutEnabled() && tabScroller.croppedEdge.isParamsSet() && tabScroller.croppedEdge.getTabIndex() == tabIndex && isHorizontalTabPlacement()) { final int availTextWidth = tabScroller.croppedEdge.getCropline() - (textRect.x - tabRect.x) - tabScroller.croppedEdge.getCroppedSideWidth(); - clippedTitle = SwingUtilities2.clipStringIfNecessary(null, metrics, title, availTextWidth); + clippedTitle = getTextUIDrawing().getClippedString(null, metrics, title, availTextWidth); } paintText(g, tabPlacement, font, metrics, tabIndex, clippedTitle, textRect, isSelected); @@ -1006,13 +1007,13 @@ } } g.setColor(fg); - SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); + getTextUIDrawing().drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); } else { // tab disabled g.setColor(tabPane.getBackgroundAt(tabIndex).brighter()); - SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); + getTextUIDrawing().drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); g.setColor(tabPane.getBackgroundAt(tabIndex).darker()); - SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1); + getTextUIDrawing().drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1); } } @@ -1639,7 +1640,7 @@ } else { // plain text final String title = tabPane.getTitleAt(tabIndex); - width += SwingUtilities2.stringWidth(tabPane, metrics, title); + width += getTextUIDrawing().getStringWidth(tabPane, metrics, title); } } return width; --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java 2016-01-25 00:12:54.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java 2016-01-25 00:12:53.000000000 +0400 @@ -366,7 +366,7 @@ } g2d.setFont(font); - SwingUtilities2.drawString(tabPane, g2d, title, textRect.x, textRect.y + metrics.getAscent()); + getTextUIDrawing().drawString(tabPane, g2d, title, textRect.x, textRect.y + metrics.getAscent()); } protected void rotateGraphics(final Graphics2D g2d, final Rectangle tabRect, final Rectangle textRect, final Rectangle iconRect, final int tabPlacement) { --- old/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java 2016-01-25 00:12:55.000000000 +0400 +++ new/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java 2016-01-25 00:12:55.000000000 +0400 @@ -261,9 +261,12 @@ static void paintDropShadowText(final Graphics g, final JComponent c, final Font font, final FontMetrics metrics, final int x, final int y, final int offsetX, final int offsetY, final Color textColor, final Color shadowColor, final String text) { g.setFont(font); g.setColor(shadowColor); - SwingUtilities2.drawString(c, g, text, x + offsetX, y + offsetY + metrics.getAscent()); + SwingUtilities2.getTextUIDrawing(c) + .drawString(c, g, text, + x + offsetX, y + offsetY + metrics.getAscent()); g.setColor(textColor); - SwingUtilities2.drawString(c, g, text, x, y + metrics.getAscent()); + SwingUtilities2.getTextUIDrawing(c) + .drawString(c, g, text, x, y + metrics.getAscent()); } static class ShadowBorder implements Border { --- old/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java 2016-01-25 00:12:57.000000000 +0400 +++ new/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java 2016-01-25 00:12:57.000000000 +0400 @@ -726,13 +726,15 @@ } FontMetrics fm = frame.getFontMetrics(titlePane.getFont()); String frameTitle = frame.getTitle(); - int title_w = frameTitle != null ? SwingUtilities2.stringWidth( + int title_w = frameTitle != null ? SwingUtilities2 + .getTextUIDrawing(frame).getStringWidth( frame, fm, frameTitle) : 0; int title_length = frameTitle != null ? frameTitle.length() : 0; // Leave room for three characters in the title. if (title_length > 3) { - int subtitle_w = SwingUtilities2.stringWidth( + int subtitle_w = SwingUtilities2 + .getTextUIDrawing(frame).getStringWidth( frame, fm, frameTitle.substring(0, 3) + "..."); width += (title_w < subtitle_w) ? title_w : subtitle_w; } else { @@ -1000,10 +1002,12 @@ String title = jif.getTitle(); if (title != null) { FontMetrics fm = SwingUtilities2.getFontMetrics(jif, g); - title = SwingUtilities2.clipStringIfNecessary(jif, fm, title, + title = SwingUtilities2.getTextUIDrawing(jif) + .getClippedString(jif, fm, title, calculateTitleArea(jif).width); g.setColor(color); - SwingUtilities2.drawString(jif, g, title, x, y + fm.getAscent()); + SwingUtilities2.getTextUIDrawing(jif) + .drawString(jif, g, title, x, y + fm.getAscent()); } } @@ -1089,7 +1093,7 @@ String title = jif.getTitle(); if (title != null) { Rectangle r = calculateTitleArea(jif); - return Math.min(SwingUtilities2.stringWidth(jif, + return Math.min(SwingUtilities2.getTextUIDrawing(jif).getStringWidth(jif, SwingUtilities2.getFontMetrics(jif, g), title), r.width); } return 0; --- old/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifBorders.java 2016-01-25 00:12:59.000000000 +0400 +++ new/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifBorders.java 2016-01-25 00:12:58.000000000 +0400 @@ -687,8 +687,8 @@ int descent = fm.getDescent(); int ascent = fm.getAscent(); Point textLoc = new Point(); - int stringWidth = SwingUtilities2.stringWidth(popup, fm, - title); + int stringWidth = SwingUtilities2.getTextUIDrawing(popup) + .getStringWidth(popup, fm, title); textLoc.y = y + ascent + TEXT_SPACING; textLoc.x = x + ((width - stringWidth) / 2); @@ -697,7 +697,8 @@ g.fillRect(textLoc.x - TEXT_SPACING, textLoc.y - (fontHeight-descent), stringWidth + (2 * TEXT_SPACING), fontHeight - descent); g.setColor(foreground); - SwingUtilities2.drawString(popup, g, title, textLoc.x, textLoc.y); + SwingUtilities2.getTextUIDrawing(popup) + .drawString(popup, g, title, textLoc.x, textLoc.y); MotifGraphicsUtils.drawGroove(g, x, textLoc.y + TEXT_SPACING, width, GROOVE_HEIGHT, --- old/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java 2016-01-25 00:13:00.000000000 +0400 +++ new/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java 2016-01-25 00:13:00.000000000 +0400 @@ -260,7 +260,7 @@ FontMetrics fm = frame.getFontMetrics(defaultTitleFont); int w = 4; if (title != null) { - w += SwingUtilities2.stringWidth(frame, fm, title); + w += getTextUIDrawing().getStringWidth(frame, fm, title); } return new Dimension(w, LABEL_HEIGHT + LABEL_DIVIDER); } @@ -288,7 +288,7 @@ g.setColor(UIManager.getColor("inactiveCaptionText")); String title = frame.getTitle(); if (title != null) { - SwingUtilities2.drawString(frame, g, title, 4, y); + getTextUIDrawing().drawString(frame, g, title, 4, y); } } } --- old/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifGraphicsUtils.java 2016-01-25 00:13:02.000000000 +0400 +++ new/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifGraphicsUtils.java 2016-01-25 00:13:01.000000000 +0400 @@ -113,13 +113,15 @@ } if (justification == CENTER) { - drawWidth = SwingUtilities2.stringWidth(c, fontMetrics, aString); + drawWidth = SwingUtilities2.getTextUIDrawing(c) + .getStringWidth(c, fontMetrics, aString); if (drawWidth > width) { drawWidth = width; } startX = x + (width - drawWidth) / 2; } else if (justification == RIGHT) { - drawWidth = SwingUtilities2.stringWidth(c, fontMetrics, aString); + drawWidth = SwingUtilities2.getTextUIDrawing(c) + .getStringWidth(c, fontMetrics, aString); if (drawWidth > width) { drawWidth = width; } @@ -135,7 +137,8 @@ startY = y + height - delta - fontMetrics.getDescent(); - SwingUtilities2.drawString(c, g, aString, startX, startY); + SwingUtilities2.getTextUIDrawing(c) + .drawString(c, g, aString, startX, startY); } /** @@ -254,11 +257,12 @@ if(!model.isEnabled()) { // *** paint the text disabled g.setColor(b.getBackground().brighter()); - SwingUtilities2.drawStringUnderlineCharAt(b, g,text, + SwingUtilities2.getTextUIDrawing(c).drawStringUnderlineCharAt(b, g,text, mnemIndex, textRect.x, textRect.y + fmAccel.getAscent()); g.setColor(b.getBackground().darker()); - SwingUtilities2.drawStringUnderlineCharAt(b, g,text, + SwingUtilities2.getTextUIDrawing(c). + drawStringUnderlineCharAt(b, g,text, mnemIndex, textRect.x - 1, textRect.y + fmAccel.getAscent() - 1); @@ -269,7 +273,8 @@ } else { g.setColor(b.getForeground()); } - SwingUtilities2.drawStringUnderlineCharAt(b, g,text, + SwingUtilities2.getTextUIDrawing(c) + .drawStringUnderlineCharAt(b, g,text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); @@ -297,10 +302,10 @@ if(!model.isEnabled()) { // *** paint the acceleratorText disabled g.setColor(b.getBackground().brighter()); - SwingUtilities2.drawString(c, g,acceleratorText, + SwingUtilities2.getTextUIDrawing(c).drawString(c, g,acceleratorText, acceleratorRect.x - accOffset, acceleratorRect.y + fm.getAscent()); g.setColor(b.getBackground().darker()); - SwingUtilities2.drawString(c, g,acceleratorText, + SwingUtilities2.getTextUIDrawing(c).drawString(c, g,acceleratorText, acceleratorRect.x - accOffset - 1, acceleratorRect.y + fm.getAscent() - 1); } else { // *** paint the acceleratorText normally @@ -310,7 +315,7 @@ } else { g.setColor(b.getForeground()); } - SwingUtilities2.drawString(c, g,acceleratorText, + SwingUtilities2.getTextUIDrawing(c).drawString(c, g,acceleratorText, acceleratorRect.x - accOffset, acceleratorRect.y + fmAccel.getAscent()); } @@ -383,7 +388,8 @@ } else { acceleratorR.width - = SwingUtilities2.stringWidth(c, fmAccel, acceleratorText); + = SwingUtilities2.getTextUIDrawing(c) + .getStringWidth(c, fmAccel, acceleratorText); acceleratorR.height = fmAccel.getHeight(); } --- old/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuUI.java 2016-01-25 00:13:03.000000000 +0400 +++ new/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuUI.java 2016-01-25 00:13:03.000000000 +0400 @@ -82,7 +82,7 @@ int stringWidth = 0; if (title!=null) { - stringWidth += SwingUtilities2.stringWidth(c, fm, title); + stringWidth += getTextUIDrawing().getStringWidth(c, fm, title); } if (d.width < stringWidth) { --- old/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java 2016-01-25 00:13:05.000000000 +0400 +++ new/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java 2016-01-25 00:13:04.000000000 +0400 @@ -93,7 +93,8 @@ * reach them from this class */ g.setColor(b.getForeground()); } - SwingUtilities2.drawStringUnderlineCharAt(b, g,text, mnemIndex, x, y); + SwingUtilities2.getTextUIDrawing(b) + .drawStringUnderlineCharAt(b, g,text, mnemIndex, x, y); } else { /*** paint the text disabled ***/ color = getDisabledTextColor(b); if (color == null) { @@ -107,14 +108,14 @@ shadow = b.getBackground().darker(); } g.setColor(shadow); - SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, + SwingUtilities2.getTextUIDrawing(b).drawStringUnderlineCharAt(b, g, text, mnemIndex, x + 1, y + 1); } if (color == null) { color = b.getBackground().brighter(); } g.setColor(color); - SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); + SwingUtilities2.getTextUIDrawing(b).drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); } } @@ -176,7 +177,7 @@ Point offset = xp.getPoint(b, part, state, Prop.TEXTSHADOWOFFSET); if (offset != null) { g.setColor(shadowColor); - SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, + SwingUtilities2.getTextUIDrawing(b).drawStringUnderlineCharAt(b, g, text, mnemIndex, x + offset.x, y + offset.y); } @@ -184,7 +185,7 @@ } g.setColor(textColor); - SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); + SwingUtilities2.getTextUIDrawing(b).drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); } static boolean isLeftToRight(Component c) { --- old/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java 2016-01-25 00:13:06.000000000 +0400 +++ new/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java 2016-01-25 00:13:06.000000000 +0400 @@ -164,7 +164,8 @@ if (lastIconBounds.x == 0) { // There are no icons lastIconBounds.x = frame.getInsets().left; } - titleW = SwingUtilities2.stringWidth(frame, fm, title); + titleW = SwingUtilities2.getTextUIDrawing(frame) + .getStringWidth(frame, fm, title); int minTitleX = lastIconBounds.x + lastIconBounds.width + gap; if (xp != null) { minTitleX += 2; @@ -192,14 +193,16 @@ Prop.TEXTSHADOWCOLOR, null); if (shadowOffset != null && shadowColor != null) { g.setColor(shadowColor); - SwingUtilities2.drawString(frame, g, title, - titleX + shadowOffset.x, - baseline + shadowOffset.y); + SwingUtilities2.getTextUIDrawing(frame) + .drawString(frame, g, title, + titleX + shadowOffset.x, + baseline + shadowOffset.y); } } } g.setColor(isSelected ? selectedTextColor : notSelectedTextColor); - SwingUtilities2.drawString(frame, g, title, titleX, baseline); + SwingUtilities2.getTextUIDrawing(frame) + .drawString(frame, g, title, titleX, baseline); g.setFont(oldFont); } } --- old/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java 2016-01-25 00:13:07.000000000 +0400 +++ new/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java 2016-01-25 00:13:07.000000000 +0400 @@ -78,7 +78,7 @@ } g.setColor(l.getForeground()); - SwingUtilities2.drawStringUnderlineCharAt(l, g, s, mnemonicIndex, + getTextUIDrawing().drawStringUnderlineCharAt(l, g, s, mnemonicIndex, textX, textY); } @@ -92,20 +92,20 @@ if ( UIManager.getColor("Label.disabledForeground") instanceof Color && UIManager.getColor("Label.disabledShadow") instanceof Color) { g.setColor( UIManager.getColor("Label.disabledShadow") ); - SwingUtilities2.drawStringUnderlineCharAt(l, g, s, + getTextUIDrawing().drawStringUnderlineCharAt(l, g, s, mnemonicIndex, textX + 1, textY + 1); g.setColor( UIManager.getColor("Label.disabledForeground") ); - SwingUtilities2.drawStringUnderlineCharAt(l, g, s, + getTextUIDrawing().drawStringUnderlineCharAt(l, g, s, mnemonicIndex, textX, textY); } else { Color background = l.getBackground(); g.setColor(background.brighter()); - SwingUtilities2.drawStringUnderlineCharAt(l,g, s, mnemonicIndex, + getTextUIDrawing().drawStringUnderlineCharAt(l,g, s, mnemonicIndex, textX + 1, textY + 1); g.setColor(background.darker()); - SwingUtilities2.drawStringUnderlineCharAt(l,g, s, mnemonicIndex, + getTextUIDrawing().drawStringUnderlineCharAt(l,g, s, mnemonicIndex, textX, textY); } } --- old/src/java.desktop/share/classes/javax/swing/SwingUtilities.java 2016-01-25 00:13:09.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/SwingUtilities.java 2016-01-25 00:13:08.000000000 +0400 @@ -1090,7 +1090,8 @@ (int) v.getPreferredSpan(View.X_AXIS)); textR.height = (int) v.getPreferredSpan(View.Y_AXIS); } else { - textR.width = SwingUtilities2.stringWidth(c, fm, text); + textR.width = SwingUtilities2.getTextUIDrawing(c) + .getStringWidth(c, fm, text); lsb = SwingUtilities2.getLeftSideBearing(c, fm, text); if (lsb < 0) { // If lsb is negative, add it to the width and later @@ -1108,7 +1109,8 @@ if (textR.width > availTextWidth) { text = SwingUtilities2.clipString(c, fm, text, availTextWidth); - textR.width = SwingUtilities2.stringWidth(c, fm, text); + textR.width = SwingUtilities2.getTextUIDrawing(c) + .getStringWidth(c, fm, text); } textR.height = fm.getHeight(); } --- old/src/java.desktop/share/classes/javax/swing/colorchooser/DefaultPreviewPanel.java 2016-01-25 00:13:10.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/colorchooser/DefaultPreviewPanel.java 2016-01-25 00:13:10.000000000 +0400 @@ -81,9 +81,9 @@ } FontMetrics fm = host.getFontMetrics(getFont()); - int ascent = fm.getAscent(); int height = fm.getHeight(); - int width = SwingUtilities2.stringWidth(host, fm, getSampleText()); + int width = SwingUtilities2.getTextUIDrawing(host) + .getStringWidth(host, fm, getSampleText()); int y = height*3 + textGap*3; int x = squareSize * 3 + squareGap*2 + swatchWidth + width + textGap*3; @@ -128,7 +128,8 @@ int ascent = fm.getAscent(); int height = fm.getHeight(); - int width = SwingUtilities2.stringWidth(host, fm, getSampleText()); + int width = SwingUtilities2.getTextUIDrawing(host) + .getStringWidth(host, fm, getSampleText()); int textXOffset = offsetX + textGap; @@ -136,8 +137,9 @@ g.setColor(color); - SwingUtilities2.drawString(host, g, getSampleText(),textXOffset+(textGap/2), - ascent+2); + SwingUtilities2.getTextUIDrawing(host) + .drawString(host, g, getSampleText(),textXOffset+(textGap/2), + ascent+2); g.fillRect(textXOffset, ( height) + textGap, @@ -145,9 +147,10 @@ height +2); g.setColor(Color.black); - SwingUtilities2.drawString(host, g, getSampleText(), - textXOffset+(textGap/2), - height+ascent+textGap+2); + SwingUtilities2.getTextUIDrawing(host) + .drawString(host, g, getSampleText(), + textXOffset+(textGap/2), + height+ascent+textGap+2); g.setColor(Color.white); @@ -158,9 +161,10 @@ height +2); g.setColor(color); - SwingUtilities2.drawString(host, g, getSampleText(), - textXOffset+(textGap/2), - ((height+textGap) * 2)+ascent+2); + SwingUtilities2.getTextUIDrawing(host) + .drawString(host, g, getSampleText(), + textXOffset+(textGap/2), + ((height+textGap) * 2)+ascent+2); return width + textGap*3; --- old/src/java.desktop/share/classes/javax/swing/plaf/ComponentUI.java 2016-01-25 00:13:12.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/ComponentUI.java 2016-01-25 00:13:11.000000000 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,10 @@ import javax.accessibility.Accessible; import java.awt.Component; -import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; -import java.awt.Insets; +import javax.swing.UIManager; +import sun.swing.SwingUtilities2; /** @@ -52,6 +52,9 @@ * */ public abstract class ComponentUI { + + private TextUIDrawing textUIDrawing; + /** * Sole constructor. (For invocation by subclass constructors, * typically implicit.) @@ -85,6 +88,14 @@ * @see javax.swing.JComponent#updateUI */ public void installUI(JComponent c) { + + if (textUIDrawing == null || textUIDrawing instanceof UIResource) { + textUIDrawing = (TextUIDrawing) UIManager.get("uiDrawing.text"); + } + + if (textUIDrawing == null) { + textUIDrawing = SwingUtilities2.DEFAULT_UI_TEXT_DRAWING; + } } /** @@ -113,6 +124,9 @@ * @see javax.swing.JComponent#updateUI */ public void uninstallUI(JComponent c) { + if (textUIDrawing instanceof UIResource) { + textUIDrawing = null; + } } /** @@ -365,4 +379,16 @@ public Accessible getAccessibleChild(JComponent c, int i) { return SwingUtilities.getAccessibleChild(c, i); } + + /** + * Returns the {@code TextUIDrawing} instance responsible for text drawing + * and measuring. + * + * @return {@code TextUIDrawing} instance + * + * @since 9 + */ + public TextUIDrawing getTextUIDrawing() { + return textUIDrawing; + } } --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonUI.java 2016-01-25 00:13:13.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonUI.java 2016-01-25 00:13:13.000000000 +0400 @@ -102,6 +102,7 @@ // Install PLAF // ******************************** public void installUI(JComponent c) { + super.installUI(c); installDefaults((AbstractButton) c); installListeners((AbstractButton) c); installKeyboardActions((AbstractButton) c); @@ -381,17 +382,17 @@ if(model.isEnabled()) { /*** paint the text normally */ g.setColor(b.getForeground()); - SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex, + getTextUIDrawing().drawStringUnderlineCharAt(c, g,text, mnemonicIndex, textRect.x + getTextShiftOffset(), textRect.y + fm.getAscent() + getTextShiftOffset()); } else { /*** paint the text disabled ***/ g.setColor(b.getBackground().brighter()); - SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex, + getTextUIDrawing().drawStringUnderlineCharAt(c, g,text, mnemonicIndex, textRect.x, textRect.y + fm.getAscent()); g.setColor(b.getBackground().darker()); - SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex, + getTextUIDrawing().drawStringUnderlineCharAt(c, g,text, mnemonicIndex, textRect.x - 1, textRect.y + fm.getAscent() - 1); } } --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java 2016-01-25 00:13:14.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java 2016-01-25 00:13:14.000000000 +0400 @@ -480,11 +480,12 @@ titleW = r.x - titleX - 3; title = getTitle(frame.getTitle(), fm, titleW); } else { - titleX = menuBar.getX() - 2 - - SwingUtilities2.stringWidth(frame,fm,title); + titleX = menuBar.getX() - 2 - SwingUtilities2 + .getTextUIDrawing(frame).getStringWidth(frame, fm, title); } - SwingUtilities2.drawString(frame, g, title, titleX, baseline); + SwingUtilities2.getTextUIDrawing(frame) + .drawString(frame, g, title, titleX, baseline); g.setFont(f); } } @@ -515,7 +516,7 @@ * @return the title. */ protected String getTitle(String text, FontMetrics fm, int availTextWidth) { - return SwingUtilities2.clipStringIfNecessary( + return SwingUtilities2.getTextUIDrawing(frame).getClippedString( frame, fm, text, availTextWidth); } @@ -646,14 +647,16 @@ FontMetrics fm = frame.getFontMetrics(getFont()); String frameTitle = frame.getTitle(); - int title_w = frameTitle != null ? SwingUtilities2.stringWidth( + int title_w = frameTitle != null ? SwingUtilities2 + .getTextUIDrawing(frame).getStringWidth( frame, fm, frameTitle) : 0; int title_length = frameTitle != null ? frameTitle.length() : 0; // Leave room for three characters in the title. if (title_length > 3) { - int subtitle_w = SwingUtilities2.stringWidth( - frame, fm, frameTitle.substring(0, 3) + "..."); + int subtitle_w = SwingUtilities2.getTextUIDrawing(frame) + .getStringWidth(frame, fm, + frameTitle.substring(0, 3) + "..."); width += (title_w < subtitle_w) ? title_w : subtitle_w; } else { width += title_w; --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java 2016-01-25 00:13:15.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java 2016-01-25 00:13:15.000000000 +0400 @@ -119,6 +119,7 @@ * @param c the component */ public void installUI(JComponent c) { + super.installUI(c); frame = (JInternalFrame)c; --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java 2016-01-25 00:13:17.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java 2016-01-25 00:13:17.000000000 +0400 @@ -129,7 +129,7 @@ { int mnemIndex = l.getDisplayedMnemonicIndex(); g.setColor(l.getForeground()); - SwingUtilities2.drawStringUnderlineCharAt(l, g, s, mnemIndex, + getTextUIDrawing().drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); } @@ -151,10 +151,10 @@ int accChar = l.getDisplayedMnemonicIndex(); Color background = l.getBackground(); g.setColor(background.brighter()); - SwingUtilities2.drawStringUnderlineCharAt(l, g, s, accChar, + getTextUIDrawing().drawStringUnderlineCharAt(l, g, s, accChar, textX + 1, textY + 1); g.setColor(background.darker()); - SwingUtilities2.drawStringUnderlineCharAt(l, g, s, accChar, + getTextUIDrawing().drawStringUnderlineCharAt(l, g, s, accChar, textX, textY); } @@ -339,6 +339,7 @@ public void installUI(JComponent c) { + super.installUI(c); installDefaults((JLabel)c); installComponents((JLabel)c); installListeners((JLabel)c); --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java 2016-01-25 00:13:18.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java 2016-01-25 00:13:18.000000000 +0400 @@ -29,21 +29,17 @@ import java.awt.Color; import java.awt.SystemColor; import java.awt.event.*; -import java.awt.Insets; import java.awt.Component; -import java.awt.Container; -import java.awt.FocusTraversalPolicy; import java.awt.AWTEvent; import java.awt.Toolkit; import java.awt.Point; -import java.net.URL; import java.io.*; import java.awt.Dimension; -import java.awt.KeyboardFocusManager; +import java.awt.FontMetrics; +import java.awt.Graphics; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; -import java.lang.reflect.*; import javax.sound.sampled.*; import sun.awt.AppContext; @@ -75,6 +71,7 @@ import javax.swing.text.DefaultEditorKit; import javax.swing.JInternalFrame; import static javax.swing.UIDefaults.LazyValue; +//import javax.swing.plaf. import java.beans.PropertyVetoException; import java.awt.Window; import java.beans.PropertyChangeListener; @@ -1841,6 +1838,7 @@ "ctrl ENTER", "press", "ctrl released ENTER", "release" }, + "uiDrawing.text", SwingUtilities2.DEFAULT_UI_TEXT_DRAWING, }; table.putDefaults(defaults); --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java 2016-01-25 00:13:19.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java 2016-01-25 00:13:19.000000000 +0400 @@ -25,6 +25,7 @@ package javax.swing.plaf.basic; +import javax.swing.plaf.TextUIDrawing; import java.awt.*; import java.awt.event.*; import java.beans.PropertyChangeEvent; @@ -148,6 +149,7 @@ } public void installUI(JComponent c) { + super.installUI(c); menuItem = (JMenuItem) c; installDefaults(); @@ -674,16 +676,16 @@ // *** paint the accText disabled if (disabledForeground != null) { g.setColor(disabledForeground); - SwingUtilities2.drawString(lh.getMenuItem(), g, + getTextUIDrawing().drawString(lh.getMenuItem(), g, lh.getAccText(), lr.getAccRect().x, lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); } else { g.setColor(lh.getMenuItem().getBackground().brighter()); - SwingUtilities2.drawString(lh.getMenuItem(), g, + getTextUIDrawing().drawString(lh.getMenuItem(), g, lh.getAccText(), lr.getAccRect().x, lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); g.setColor(lh.getMenuItem().getBackground().darker()); - SwingUtilities2.drawString(lh.getMenuItem(), g, + getTextUIDrawing().drawString(lh.getMenuItem(), g, lh.getAccText(), lr.getAccRect().x - 1, lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1); } @@ -696,7 +698,7 @@ } else { g.setColor(acceleratorForeground); } - SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(), + getTextUIDrawing().drawString(lh.getMenuItem(), g, lh.getAccText(), lr.getAccRect().x, lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); } @@ -791,14 +793,14 @@ // *** paint the text disabled if ( UIManager.get("MenuItem.disabledForeground") instanceof Color ) { g.setColor( UIManager.getColor("MenuItem.disabledForeground") ); - SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text, + getTextUIDrawing().drawStringUnderlineCharAt(menuItem, g,text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); } else { g.setColor(menuItem.getBackground().brighter()); - SwingUtilities2.drawStringUnderlineCharAt(menuItem, g, text, + getTextUIDrawing().drawStringUnderlineCharAt(menuItem, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); g.setColor(menuItem.getBackground().darker()); - SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text, + getTextUIDrawing().drawStringUnderlineCharAt(menuItem, g,text, mnemIndex, textRect.x - 1, textRect.y + fm.getAscent() - 1); } @@ -807,7 +809,7 @@ if (model.isArmed()|| (menuItem instanceof JMenu && model.isSelected())) { g.setColor(selectionForeground); // Uses protected field. } - SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text, + getTextUIDrawing().drawStringUnderlineCharAt(menuItem, g,text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); } } --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicProgressBarUI.java 2016-01-25 00:13:21.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicProgressBarUI.java 2016-01-25 00:13:20.000000000 +0400 @@ -827,11 +827,11 @@ if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { g2.setColor(getSelectionBackground()); - SwingUtilities2.drawString(progressBar, g2, progressString, + getTextUIDrawing().drawString(progressBar, g2, progressString, renderLocation.x, renderLocation.y); g2.setColor(getSelectionForeground()); g2.clipRect(fillStart, y, amountFull, height); - SwingUtilities2.drawString(progressBar, g2, progressString, + getTextUIDrawing().drawString(progressBar, g2, progressString, renderLocation.x, renderLocation.y); } else { // VERTICAL g2.setColor(getSelectionBackground()); @@ -840,11 +840,11 @@ g2.setFont(progressBar.getFont().deriveFont(rotate)); renderLocation = getStringPlacement(g2, progressString, x, y, width, height); - SwingUtilities2.drawString(progressBar, g2, progressString, + getTextUIDrawing().drawString(progressBar, g2, progressString, renderLocation.x, renderLocation.y); g2.setColor(getSelectionForeground()); g2.clipRect(x, fillStart, width, amountFull); - SwingUtilities2.drawString(progressBar, g2, progressString, + getTextUIDrawing().drawString(progressBar, g2, progressString, renderLocation.x, renderLocation.y); } g2.setClip(oldClip); @@ -870,7 +870,7 @@ int x,int y,int width,int height) { FontMetrics fontSizer = SwingUtilities2.getFontMetrics(progressBar, g, progressBar.getFont()); - int stringWidth = SwingUtilities2.stringWidth(progressBar, fontSizer, + int stringWidth = getTextUIDrawing().getStringWidth(progressBar, fontSizer, progressString); if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { @@ -899,7 +899,7 @@ if (progressBar.isStringPainted()) { // I'm doing this for completeness. String progString = progressBar.getString(); - int stringWidth = SwingUtilities2.stringWidth( + int stringWidth = getTextUIDrawing().getStringWidth( progressBar, fontSizer, progString); if (stringWidth > size.width) { size.width = stringWidth; @@ -926,7 +926,7 @@ size.width = stringHeight; } // This is also for completeness. - int stringWidth = SwingUtilities2.stringWidth( + int stringWidth = getTextUIDrawing().getStringWidth( progressBar, fontSizer, progString); if (stringWidth > size.height) { size.height = stringWidth; --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java 2016-01-25 00:13:22.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java 2016-01-25 00:13:22.000000000 +0400 @@ -239,6 +239,7 @@ // UI Installation/De-installation public void installUI(JComponent c) { + super.installUI(c); this.tabPane = (JTabbedPane)c; calculatedBaseline = false; @@ -942,9 +943,9 @@ tabScroller.croppedEdge.getTabIndex() == tabIndex && isHorizontalTabPlacement()) { int availTextWidth = tabScroller.croppedEdge.getCropline() - (textRect.x - tabRect.x) - tabScroller.croppedEdge.getCroppedSideWidth(); - clippedTitle = SwingUtilities2.clipStringIfNecessary(null, metrics, title, availTextWidth); + clippedTitle = getTextUIDrawing().getClippedString(null, metrics, title, availTextWidth); } else if (!scrollableTabLayoutEnabled() && isHorizontalTabPlacement()) { - clippedTitle = SwingUtilities2.clipStringIfNecessary(null, metrics, title, textRect.width); + clippedTitle = getTextUIDrawing().getClippedString(null, metrics, title, textRect.width); } paintText(g, tabPlacement, font, metrics, @@ -1178,17 +1179,17 @@ } } g.setColor(fg); - SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, + getTextUIDrawing().drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); } else { // tab disabled g.setColor(tabPane.getBackgroundAt(tabIndex).brighter()); - SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, + getTextUIDrawing().drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); g.setColor(tabPane.getBackgroundAt(tabIndex).darker()); - SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, + getTextUIDrawing().drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1); @@ -2026,7 +2027,7 @@ } else { // plain text String title = tabPane.getTitleAt(tabIndex); - width += SwingUtilities2.stringWidth(tabPane, metrics, title); + width += getTextUIDrawing().getStringWidth(tabPane, metrics, title); } } return width; --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java 2016-01-25 00:13:24.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java 2016-01-25 00:13:23.000000000 +0400 @@ -1411,6 +1411,8 @@ // Installation public void installUI(JComponent c) { + super.installUI(c); + table = (JTable)c; rendererPane = new CellRendererPane(); --- old/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolTipUI.java 2016-01-25 00:13:25.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolTipUI.java 2016-01-25 00:13:25.000000000 +0400 @@ -73,6 +73,7 @@ } public void installUI(JComponent c) { + super.installUI(c); installDefaults(c); installComponents(c); installListeners(c); @@ -173,7 +174,7 @@ v.paint(g, paintTextR); } else { g.setFont(font); - SwingUtilities2.drawString(c, g, tipText, paintTextR.x, + getTextUIDrawing().drawString(c, g, tipText, paintTextR.x, paintTextR.y + metrics.getAscent()); } } @@ -196,7 +197,7 @@ prefSize.width += (int) v.getPreferredSpan(View.X_AXIS) + 6; prefSize.height += (int) v.getPreferredSpan(View.Y_AXIS); } else { - prefSize.width += SwingUtilities2.stringWidth(c,fm,text) + 6; + prefSize.width += getTextUIDrawing().getStringWidth(c,fm,text) + 6; prefSize.height += fm.getHeight(); } } --- old/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalButtonUI.java 2016-01-25 00:13:26.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalButtonUI.java 2016-01-25 00:13:26.000000000 +0400 @@ -237,7 +237,7 @@ /*** paint the text disabled ***/ g.setColor(getDisabledTextColor()); } - SwingUtilities2.drawStringUnderlineCharAt(c, g,text,mnemIndex, + getTextUIDrawing().drawStringUnderlineCharAt(c, g,text,mnemIndex, textRect.x, textRect.y + fm.getAscent()); } } --- old/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java 2016-01-25 00:13:27.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java 2016-01-25 00:13:27.000000000 +0400 @@ -244,12 +244,14 @@ } FontMetrics fm = frame.getFontMetrics(getFont()); String frameTitle = frame.getTitle(); - int title_w = frameTitle != null ? SwingUtilities2.stringWidth( + int title_w = frameTitle != null ? SwingUtilities2. + getTextUIDrawing(frame).getStringWidth( frame, fm, frameTitle) : 0; int title_length = frameTitle != null ? frameTitle.length() : 0; if (title_length > 2) { - int subtitle_w = SwingUtilities2.stringWidth(frame, fm, + int subtitle_w = SwingUtilities2.getTextUIDrawing(frame) + .getStringWidth(frame, fm, frame.getTitle().substring(0, 2) + "..."); width += (title_w < subtitle_w) ? title_w : subtitle_w; } @@ -469,12 +471,15 @@ } else { titleW = xOffset - rect.x - rect.width - 4; frameTitle = getTitle(frameTitle, fm, titleW); - xOffset -= SwingUtilities2.stringWidth(frame, fm, frameTitle); + xOffset -= SwingUtilities2.getTextUIDrawing(frame) + .getStringWidth(frame, fm, frameTitle); } - titleLength = SwingUtilities2.stringWidth(frame, fm, frameTitle); - SwingUtilities2.drawString(frame, g, frameTitle, xOffset, yOffset); - xOffset += leftToRight ? titleLength + 5 : -5; + titleLength = SwingUtilities2.getTextUIDrawing(frame) + .getStringWidth(frame, fm, frameTitle); + SwingUtilities2.getTextUIDrawing(frame) + .drawString(frame, g, frameTitle, xOffset, yOffset); + xOffset += leftToRight ? titleLength + 5 : -5; } int bumpXOffset; --- old/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLabelUI.java 2016-01-25 00:13:29.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLabelUI.java 2016-01-25 00:13:28.000000000 +0400 @@ -87,7 +87,7 @@ { int mnemIndex = l.getDisplayedMnemonicIndex(); g.setColor(UIManager.getColor("Label.disabledForeground")); - SwingUtilities2.drawStringUnderlineCharAt(l, g, s, mnemIndex, + getTextUIDrawing().drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); } } --- old/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java 2016-01-25 00:13:30.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java 2016-01-25 00:13:30.000000000 +0400 @@ -244,7 +244,7 @@ // *** paint the text disabled g.setColor(getDisabledTextColor()); } - SwingUtilities2.drawStringUnderlineCharAt(c,g,text, + getTextUIDrawing().drawStringUnderlineCharAt(c,g,text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); } if(b.hasFocus() && b.isFocusPainted() && --- old/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTitlePane.java 2016-01-25 00:13:31.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTitlePane.java 2016-01-25 00:13:31.000000000 +0400 @@ -748,19 +748,19 @@ rect.x = window.getWidth() - window.getInsets().right-2; } titleW = rect.x - xOffset - 4; - theTitle = SwingUtilities2.clipStringIfNecessary( - rootPane, fm, theTitle, titleW); + theTitle = SwingUtilities2.getTextUIDrawing(rootPane) + .getClippedString(rootPane, fm, theTitle, titleW); } else { titleW = xOffset - rect.x - rect.width - 4; - theTitle = SwingUtilities2.clipStringIfNecessary( - rootPane, fm, theTitle, titleW); - xOffset -= SwingUtilities2.stringWidth(rootPane, fm, - theTitle); - } - int titleLength = SwingUtilities2.stringWidth(rootPane, fm, - theTitle); - SwingUtilities2.drawString(rootPane, g, theTitle, xOffset, - yOffset ); + theTitle = SwingUtilities2.getTextUIDrawing(rootPane) + .getClippedString(rootPane, fm, theTitle, titleW); + xOffset -= SwingUtilities2.getTextUIDrawing(rootPane) + .getStringWidth(rootPane, fm, theTitle); + } + int titleLength = SwingUtilities2.getTextUIDrawing(rootPane) + .getStringWidth(rootPane, fm, theTitle); + SwingUtilities2.getTextUIDrawing(rootPane) + .drawString(rootPane, g, theTitle, xOffset, yOffset); xOffset += leftToRight ? titleLength + 5 : -5; } --- old/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java 2016-01-25 00:13:32.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java 2016-01-25 00:13:32.000000000 +0400 @@ -212,7 +212,7 @@ g.setColor(getDisabledTextColor()); } } - SwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemIndex, + getTextUIDrawing().drawStringUnderlineCharAt(c, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); } --- old/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToolTipUI.java 2016-01-25 00:13:34.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToolTipUI.java 2016-01-25 00:13:33.000000000 +0400 @@ -127,7 +127,7 @@ paintTextR.height); } else { g.setFont(font); - SwingUtilities2.drawString(tip, g, tipText, paintTextR.x, + getTextUIDrawing().drawString(tip, g, tipText, paintTextR.x, paintTextR.y + metrics.getAscent()); accelBL = metrics.getAscent(); } @@ -135,7 +135,7 @@ if (!accelString.equals("")) { g.setFont(smallFont); g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() ); - SwingUtilities2.drawString(tip, g, accelString, + getTextUIDrawing().drawString(tip, g, accelString, tip.getWidth() - 1 - insets.right - accelSpacing + padSpaceBetweenStrings @@ -148,7 +148,7 @@ return accel.equals("") ? 0 : padSpaceBetweenStrings + - SwingUtilities2.stringWidth(c, fm, accel); + getTextUIDrawing().getStringWidth(c, fm, accel); } public Dimension getPreferredSize(JComponent c) { --- old/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java 2016-01-25 00:13:35.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java 2016-01-25 00:13:35.000000000 +0400 @@ -173,8 +173,9 @@ */ public int computeStringWidth(SynthContext ss, Font font, FontMetrics metrics, String text) { - return SwingUtilities2.stringWidth(ss.getComponent(), metrics, - text); + JComponent comp = ss.getComponent(); + return SwingUtilities2.getTextUIDrawing(comp) + .getStringWidth(comp, metrics, text); } /** @@ -347,8 +348,8 @@ JComponent c = ss.getComponent(); FontMetrics fm = SwingUtilities2.getFontMetrics(c, g); y += fm.getAscent(); - SwingUtilities2.drawStringUnderlineCharAt(c, g, text, - mnemonicIndex, x, y); + SwingUtilities2.getTextUIDrawing(c) + .drawStringUnderlineCharAt(c, g, text, mnemonicIndex, x, y); } } --- old/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java 2016-01-25 00:13:36.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java 2016-01-25 00:13:36.000000000 +0400 @@ -690,6 +690,8 @@ "KP_RIGHT", "selectParent", }); + table.put("uiDrawing.text", SwingUtilities2.DEFAULT_UI_TEXT_DRAWING); + // enabled antialiasing depending on desktop settings flushUnreferenced(); SwingUtilities2.putAATextInfo(useLAFConditions(), table); --- old/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java 2016-01-25 00:13:37.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java 2016-01-25 00:13:37.000000000 +0400 @@ -432,7 +432,7 @@ } // adjust the width if necessary to make room for the string - int stringWidth = SwingUtilities2.stringWidth( + int stringWidth = getTextUIDrawing().getStringWidth( progressBar, fontSizer, progString); if (stringWidth > size.width) { size.width = stringWidth; @@ -447,7 +447,7 @@ } // make sure the height is big enough for the string - int stringWidth = SwingUtilities2.stringWidth( + int stringWidth = getTextUIDrawing().getStringWidth( progressBar, fontSizer, progString); if (stringWidth > size.height) { size.height = stringWidth; --- old/src/java.desktop/share/classes/javax/swing/text/Utilities.java 2016-01-25 00:13:39.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/text/Utilities.java 2016-01-25 00:13:38.000000000 +0400 @@ -1092,4 +1092,5 @@ } return retValue; } + } --- old/src/java.desktop/share/classes/sun/swing/MenuItemLayoutHelper.java 2016-01-25 00:13:40.000000000 +0400 +++ new/src/java.desktop/share/classes/sun/swing/MenuItemLayoutHelper.java 2016-01-25 00:13:40.000000000 +0400 @@ -256,7 +256,8 @@ // accRect if (!accText.equals("")) { - accSize.width = SwingUtilities2.stringWidth(mi, accFm, accText); + accSize.width = SwingUtilities2.getTextUIDrawing(mi) + .getStringWidth(mi, accFm, accText); accSize.height = accFm.getHeight(); } @@ -272,7 +273,8 @@ (int) htmlView.getPreferredSpan(View.Y_AXIS); } else { // Text isn't HTML - textSize.width = SwingUtilities2.stringWidth(mi, fm, text); + textSize.width = SwingUtilities2.getTextUIDrawing(mi) + .getStringWidth(mi, fm, text); textSize.height = fm.getHeight(); } } --- old/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java 2016-01-25 00:13:42.000000000 +0400 +++ new/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java 2016-01-25 00:13:41.000000000 +0400 @@ -60,6 +60,9 @@ import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TextUIDrawing; +import javax.swing.plaf.UIResource; /** * A collection of utility methods for Swing. @@ -183,9 +186,9 @@ // Many of the following methods are invoked from older API. // As this older API was not passed a Component, a null Component may // now be passsed in. For example, SwingUtilities.computeStringWidth - // is implemented to call SwingUtilities2.stringWidth, the + // is implemented to call getTextUIDrawing().getStringWidth, the // SwingUtilities variant does not take a JComponent, as such - // SwingUtilities2.stringWidth can be passed a null Component. + // getTextUIDrawing().getStringWidth can be passed a null Component. // In other words, if you add new functionality to these methods you // need to gracefully handle null. // @@ -2005,4 +2008,135 @@ public interface RepaintListener { void repaintPerformed(JComponent c, int x, int y, int w, int h); } + + + public static final TextUIDrawing DEFAULT_UI_TEXT_DRAWING + = new DefaultUITextDrawing(); + + + public static TextUIDrawing getTextUIDrawing(JComponent comp) { + + if (comp != null) { + ComponentUI compUI = comp.getUI(); + if (compUI != null) { + TextUIDrawing uiTextDrawing = compUI.getTextUIDrawing(); + if (uiTextDrawing != null) { + return uiTextDrawing; + } + } + } + + return DEFAULT_UI_TEXT_DRAWING; + } + + public static class DefaultUITextDrawing implements TextUIDrawing, UIResource { + + /** + * Draws the passed in string at the specified location using the given + * graphics context. Anti-aliasing hints and a numeric shaper from + * the provided component are used to draw the string for the non-print + * graphics context. + * Nothing is drawn for the null string. + * + * @param c the component that will display the string, may be null + * @param g the graphics context, must not be null + * @param string the string to display, may be null + * @param x the x coordinate to draw the text at + * @param y the y coordinate to draw the text at + * @throws NullPointerException if the specified {@code g} is {@code null} + * + * @since 9 + */ + @Override + public void drawString(JComponent c, Graphics g, String string, + int x, int y) { + SwingUtilities2.drawString(c, g, string, x, y); + } + + /** + * Draws the passed in string at the specified location underlining + * the specified character using the given graphics context. + * The provided component is used to query a numeric shaper and anti-aliasing + * hints for the non-print graphics context. + *

+ * The {@code underlinedIndex} parameter points to a char value + * (Unicode code unit) in the given string. + * If the char value specified at the underlined index is in + * the high-surrogate range and the char value at the following index is in + * the low-surrogate range then the supplementary character corresponding + * to this surrogate pair is underlined. + *

+ * No character is underlined if the index is negative or greater + * than the string length {@code (index < 0 || index >= string.length())} + * or if the char value specified at the given index + * is in the low-surrogate range. + * + * @param c the component that will display the string, may be null + * @param g the graphics context, must not be null + * @param string the string to display, may be null + * @param underlinedIndex index of a a char value (Unicode code unit) + * in the string to underline + * @param x the x coordinate to draw the text at + * @param y the y coordinate to draw the text at + * @throws NullPointerException if the specified {@code g} is {@code null} + * + * @see #getStringWidth + * + * @since 9 + */ + @Override + public void drawStringUnderlineCharAt(JComponent c, Graphics g, + String string, int underlinedIndex, int x, int y) { + SwingUtilities2.drawStringUnderlineCharAt(c, g, string, underlinedIndex, x, y); + } + + /** + * Replaces last characters of the passed in string with ellipsis that it + * width fits to the space provided. A numeric shaper from the given + * component is used for the string width calculation. + * The unchanged string is returned if the space provided is greater than + * the string width. Ellipsis is returned if the string width is not greater + * than ellipsis width. + * + * @param c the component + * @param fm the FontMetrics used to measure the string width, must not be null + * @param string the string to clip, may be null + * @param availTextWidth the amount of space that the string can be drawn in + * @return the clipped string that fits in the provided space, an empty + * string if the given string argument is {@code null} or empty, + * ellipses if the string width is not greater than ellipsis width. + * @throws NullPointerException if the specified {@code fm} is {@code null} + * + * @see #getStringWidth + * + * @since 9 + */ + @Override + public String getClippedString(JComponent c, FontMetrics fm, + String string, int availTextWidth) { + return SwingUtilities2.clipStringIfNecessary(c, fm, string, availTextWidth); + } + + /** + * Returns the total advance width of the passed in string using the given + * font metrics and numeric shaper from the given component. + * The advance is the distance from the leftmost point to the rightmost point + * on the string's baseline. + * If the passed string is {@code null}, returns zero. + * + * @param c the component, may be null + * @param fm the FontMetrics used to measure the advance string width, + * must not be null + * @param string the string to get the advance width of, may be null + * @return the advance width of the specified string, zero is returned for + * {@code null} string + * @throws NullPointerException if the specified {@code fm} is {@code null} + * + * @since 9 + */ + @Override + public int getStringWidth(JComponent c, FontMetrics fm, String string) { + return SwingUtilities2.stringWidth(c, fm, string); + } + } } --- /dev/null 2016-01-25 00:13:43.000000000 +0400 +++ new/src/java.desktop/share/classes/javax/swing/plaf/TextUIDrawing.java 2016-01-25 00:13:43.000000000 +0400 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.swing.plaf; + +import java.awt.FontMetrics; +import java.awt.Graphics; +import javax.swing.JComponent; + +/** + * This interface is designed to be used by various component ui classes + * for drawing and measuring text. + * {@literal L&F} sets the instance of the {@code TextUIDrawing} to the + * look and feel defaults using {@literal "uiDrawing.text"} property. + * To get an instance of {@code TextUIDrawing} for the current {@literal L&F} + * use {@code UIManager.get("uiDrawing.text")}. + * To set a custom {@code TextUIDrawing} use + * {@code UIManager.put("uiDrawing.text", new CustomTextUIDrawing())}. + * + * @see javax.swing.plaf.ComponentUI#getTextUIDrawing + * + * @since 9 + */ +public interface TextUIDrawing { + /** + * Draws the given string at the specified location using text properties + * and anti-aliasing hints from the provided component. + * Nothing is drawn for the null string. + * + * @param c the component that will display the string, may be null + * @param g the graphics context, must not be null + * @param string the string to display, may be null + * @param x the x coordinate to draw the text at + * @param y the y coordinate to draw the text at + * @throws NullPointerException if the specified {@code g} is {@code null} + * + * @since 9 + */ + void drawString(JComponent c, Graphics g, String string, + int x, int y); + + /** + * Draws the given string at the specified location underlining + * the specified character. The provided component is used to query text + * properties and anti-aliasing hints. + *

+ * The {@code underlinedIndex} parameter points to a char value + * (Unicode code unit) in the given string. + * If the char value specified at the underlined index is in + * the high-surrogate range and the char value at the following index is in + * the low-surrogate range then the supplementary character corresponding + * to this surrogate pair is underlined. + *

+ * No character is underlined if the index is negative or greater + * than the string length {@code (index < 0 || index >= string.length())} + * or if the char value specified at the given index + * is in the low-surrogate range. + * + * @param c the component that will display the string, may be null + * @param g the graphics context, must not be null + * @param string the string to display, may be null + * @param underlinedIndex index of a a char value (Unicode code unit) + * in the string to underline + * @param x the x coordinate to draw the text at + * @param y the y coordinate to draw the text at + * @throws NullPointerException if the specified {@code g} is {@code null} + * + * @see #getStringWidth + * + * @since 9 + */ + void drawStringUnderlineCharAt(JComponent c, Graphics g, + String string, int underlinedIndex, int x, int y); + + /** + * Clips the passed in string to the space provided. + * The provided component is used to query text properties. + * The unchanged string is returned if the space provided is greater than + * the string width. + * + * @param c the component + * @param fm the FontMetrics used to measure the string width, must not be null + * @param string the string to clip, may be null + * @param availTextWidth the amount of space that the string can be drawn in + * @return the clipped string that fits in the provided space, an empty + * string if the given string argument is {@code null} or empty + * @throws NullPointerException if the specified {@code fm} is {@code null} + * + * @see #getStringWidth + * + * @since 9 + */ + String getClippedString(JComponent c, FontMetrics fm, + String string, int availTextWidth); + + /** + * Returns the total advance width of the passed in string using the given + * font metrics, and text properties from the given component. + * The advance is the distance from the leftmost point to the rightmost point + * on the string's baseline. + * If the passed string is {@code null}, returns zero. + * + * @param c the component, may be null + * @param fm the FontMetrics used to measure the advance string width, + * must not be null + * @param string the string to get the advance width of, may be null + * @return the advance width of the specified string, zero is returned for + * {@code null} string + * @throws NullPointerException if the specified {@code fm} is {@code null} + * + * @since 9 + */ + int getStringWidth(JComponent c, FontMetrics fm, String string); + +} --- /dev/null 2016-01-25 00:13:44.000000000 +0400 +++ new/test/javax/swing/UIDefaults/8132119/bug8132119.java 2016-01-25 00:13:44.000000000 +0400 @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.font.FontRenderContext; +import java.awt.font.NumericShaper; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.plaf.basic.BasicLookAndFeel; +import javax.swing.plaf.TextUIDrawing; +import javax.swing.plaf.metal.MetalLookAndFeel; + +/** + * @test + * @bug 8132119 + * @author Alexandr Scherbatiy + * @summary Provide public API for text related methods in SwingUtilities2 + */ +public class bug8132119 { + + private static final int WIDTH = 150; + private static final int HEIGHT = 50; + private static final Color DEFAULT_DRAW_COLOR = Color.RED; + private static final Color TEST_DRAW_COLOR = Color.PINK; + private static final Color BACKGROUND_COLOR = Color.GREEN; + private static final NumericShaper NUMERIC_SHAPER = NumericShaper.getShaper( + NumericShaper.ARABIC); + private static final String TEXT_UI_DRAWING_PROPERTY = "uiDrawing.text"; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(bug8132119::testDrawStringMethods); + } + + private static void testDrawStringMethods() { + testTextDrawingProperty(); + testDefaultTextDrawing(); + testCustomTextDrawing(); + } + + private static void testDefaultTextDrawing() { + setMetalLAF(); + testStringWidth(); + testStringClip(); + testDrawEmptyString(); + testDrawString(false, DEFAULT_DRAW_COLOR); + testDrawString(true, DEFAULT_DRAW_COLOR); + checkNullArguments(); + } + + private static void testCustomTextDrawing() { + setMetalLAF(); + setCustomTextDrawing(); + testDrawString(false, TEST_DRAW_COLOR); + testDrawString(true, TEST_DRAW_COLOR); + } + + private static void testTextDrawingProperty() { + try { + LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels(); + + for (LookAndFeelInfo info : infos) { + UIManager.setLookAndFeel(info.getClassName()); + Class cls = UIManager.getLookAndFeel().getClass(); + if (!BasicLookAndFeel.class.isAssignableFrom(cls)) { + continue; + } + + Object textDrawing = UIManager.get(TEXT_UI_DRAWING_PROPERTY); + if (!(textDrawing instanceof TextUIDrawing)) { + throw new RuntimeException( + String.format("%s property is not set for %s!", + TEXT_UI_DRAWING_PROPERTY, info.getClassName())); + } + + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void testStringWidth() { + + String str = "12345678910\u036F"; + JComponent comp = createComponent(str); + Font font = comp.getFont(); + FontMetrics fontMetrics = comp.getFontMetrics(font); + int stringWidth = getTextDrawing().getStringWidth(comp, fontMetrics, str); + + if (stringWidth == fontMetrics.stringWidth(str)) { + throw new RuntimeException("Numeric shaper is not used!"); + } + + if (stringWidth != getLayoutWidth(str, font, NUMERIC_SHAPER)) { + throw new RuntimeException("Wrong text width!"); + } + } + + private static void testStringClip() { + + String str = "1234567890"; + JComponent comp = createComponent(str); + FontMetrics fontMetrics = comp.getFontMetrics(comp.getFont()); + + TextUIDrawing textDrawing = getTextDrawing(); + + int width = textDrawing.getStringWidth(comp, fontMetrics, str); + + String clip = textDrawing.getClippedString(comp, fontMetrics, str, width); + checkClippedString(str, clip, str); + + clip = textDrawing.getClippedString(comp, fontMetrics, str, width + 1); + checkClippedString(str, clip, str); + + clip = textDrawing.getClippedString(comp, fontMetrics, str, -1); + checkClippedString(str, clip, "..."); + + clip = textDrawing.getClippedString(comp, fontMetrics, str, 0); + checkClippedString(str, clip, "..."); + + clip = textDrawing.getClippedString(comp, fontMetrics, + str, width - width / str.length()); + int endIndex = str.length() - 3; + checkClippedString(str, clip, str.substring(0, endIndex) + "..."); + } + + private static void checkClippedString(String str, String res, String golden) { + if (!golden.equals(res)) { + throw new RuntimeException(String.format("The string '%s' is not " + + "properly clipped. The result is '%s' instead of '%s'", + str, res, golden)); + } + } + + private static void testDrawEmptyString() { + JLabel label = new JLabel(); + BufferedImage buffImage = createBufferedImage(50, 50); + Graphics2D g2 = buffImage.createGraphics(); + g2.setColor(DEFAULT_DRAW_COLOR); + TextUIDrawing textDrawing = getTextDrawing(); + textDrawing.drawString(null, g2, null, 0, 0); + textDrawing.drawString(label, g2, null, 0, 0); + textDrawing.drawString(null, g2, "", 0, 0); + textDrawing.drawString(label, g2, "", 0, 0); + textDrawing.drawStringUnderlineCharAt(null, g2, null, 3, 0, 0); + textDrawing.drawStringUnderlineCharAt(label, g2, null, 3, 0, 0); + textDrawing.drawStringUnderlineCharAt(null, g2, "", 3, 0, 0); + textDrawing.drawStringUnderlineCharAt(label, g2, "", 3, 0, 0); + g2.dispose(); + checkImageIsEmpty(buffImage); + } + + private static void testDrawString(boolean underlined, Color drawColor) { + String str = "AOB"; + JComponent comp = createComponent(str, underlined); + + BufferedImage buffImage = createBufferedImage(WIDTH, HEIGHT); + Graphics2D g2 = buffImage.createGraphics(); + + comp.paint(g2); + g2.dispose(); + + FontMetrics fontMetrices = comp.getFontMetrics(comp.getFont()); + TextUIDrawing textDrawing = getTextDrawing(); + int width = textDrawing.getStringWidth(comp, fontMetrices, str); + int xx = width / 2 + 6; + + checkImageContainsSymbol(buffImage, xx, underlined ? 3 : 2, drawColor); + } + + private static void checkNullArguments() { + + Graphics g = null; + try { + String text = "Test"; + JComponent component = new JLabel(text); + BufferedImage img = createBufferedImage(100, 100); + g = img.createGraphics(); + checkNullArguments(component, g, text); + } finally { + g.dispose(); + } + } + + private static void checkNullArguments(JComponent comp, Graphics g, + String text) { + + checkNullArgumentsDrawString(comp, g, text); + checkNullArgumentsDrawStringUnderlineCharAt(comp, g, text); + checkNullArgumentsGetClippedString(comp, text); + checkNullArgumentsGetStringWidth(comp, text); + } + + private static void checkNullArgumentsDrawString(JComponent comp, Graphics g, + String text) { + + int x = 50; + int y = 50; + TextUIDrawing textDrawing = getTextDrawing(); + textDrawing.drawString(null, g, text, x, y); + textDrawing.drawString(comp, g, null, x, y); + + try { + textDrawing.drawString(comp, null, text, x, y); + } catch (NullPointerException e) { + return; + } + + throw new RuntimeException("NPE is not thrown"); + } + + private static void checkNullArgumentsDrawStringUnderlineCharAt( + JComponent comp, Graphics g, String text) { + + int x = 50; + int y = 50; + TextUIDrawing textDrawing = getTextDrawing(); + textDrawing.drawStringUnderlineCharAt(null, g, text, 1, x, y); + textDrawing.drawStringUnderlineCharAt(comp, g, null, 1, x, y); + + try { + textDrawing.drawStringUnderlineCharAt(comp, null, text, 1, x, y); + } catch (NullPointerException e) { + return; + } + + throw new RuntimeException("NPE is not thrown"); + } + + private static void checkNullArgumentsGetClippedString( + JComponent comp, String text) { + + FontMetrics fontMetrics = comp.getFontMetrics(comp.getFont()); + TextUIDrawing textDrawing = getTextDrawing(); + textDrawing.getClippedString(null, fontMetrics, text, 1); + String result = textDrawing.getClippedString(comp, fontMetrics, null, 1); + if (!"".equals(result)) { + throw new RuntimeException("Empty string is not returned!"); + } + + try { + textDrawing.getClippedString(comp, null, text, 1); + } catch (NullPointerException e) { + return; + } + + throw new RuntimeException("NPE is not thrown"); + } + + private static void checkNullArgumentsGetStringWidth(JComponent comp, + String text) { + + FontMetrics fontMetrics = comp.getFontMetrics(comp.getFont()); + TextUIDrawing textDrawing = getTextDrawing(); + textDrawing.getStringWidth(null, fontMetrics, text); + int result = textDrawing.getStringWidth(comp, fontMetrics, null); + + if (result != 0) { + throw new RuntimeException("The string length is not 0"); + } + + try { + textDrawing.getStringWidth(comp, null, text); + } catch (NullPointerException e) { + return; + } + + throw new RuntimeException("NPE is not thrown"); + } + + private static void setMetalLAF() { + try { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static JComponent createComponent(String str) { + return createComponent(str, false); + } + + private static JComponent createComponent(String str, boolean underline) { + JLabel comp = new JLabel(str); + + if (underline) { + comp.setDisplayedMnemonicIndex(1); + UIManager.put("Button.showMnemonics", true); + } + comp.setSize(WIDTH, HEIGHT); + comp.putClientProperty(TextAttribute.NUMERIC_SHAPING, NUMERIC_SHAPER); + comp.setFont(getFont()); + comp.setForeground(DEFAULT_DRAW_COLOR); + return comp; + } + + private static Font getFont() { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + String[] fontNames = ge.getAvailableFontFamilyNames(); + String fontName = fontNames[0]; + for (String name : fontNames) { + if ("Dialog".equals(name)) { + fontName = name; + break; + } + } + return new Font(fontName, Font.PLAIN, 28); + } + + private static int getLayoutWidth(String text, Font font, NumericShaper shaper) { + HashMap map = new HashMap(); + map.put(TextAttribute.FONT, font); + map.put(TextAttribute.NUMERIC_SHAPING, shaper); + FontRenderContext frc = new FontRenderContext(null, false, false); + TextLayout layout = new TextLayout(text, map, frc); + return (int) layout.getAdvance(); + } + + private static TextUIDrawing getTextDrawing() { + return (TextUIDrawing) UIManager.get(TEXT_UI_DRAWING_PROPERTY); + } + + private static void setCustomTextDrawing() { + UIManager.put(TEXT_UI_DRAWING_PROPERTY, new TestLAFTextDrawing()); + } + + private static void checkImageIsEmpty(BufferedImage buffImage) { + int background = BACKGROUND_COLOR.getRGB(); + + for (int i = 0; i < buffImage.getWidth(); i++) { + for (int j = 0; j < buffImage.getHeight(); j++) { + if (background != buffImage.getRGB(i, j)) { + throw new RuntimeException("Image is not empty!"); + } + } + } + } + + private static void checkImageContainsSymbol(BufferedImage buffImage, + int x, int intersections, Color drawColor) { + boolean hasDrawColor = false; + int background = BACKGROUND_COLOR.getRGB(); + boolean isBackground = true; + int backgroundChangesCount = 0; + + for (int y = 0; y < buffImage.getHeight(); y++) { + int imgRGB = buffImage.getRGB(x, y); + if (!(isBackground ^ (background != imgRGB))) { + isBackground = !isBackground; + backgroundChangesCount++; + } + + if (!hasDrawColor && imgRGB == drawColor.getRGB()) { + hasDrawColor = true; + } + } + if (backgroundChangesCount != intersections * 2) { + throw new RuntimeException("String is not properly drawn!"); + } + if (!hasDrawColor) { + throw new RuntimeException("Wrong draw color!"); + } + } + + private static BufferedImage createBufferedImage(int width, int height) { + BufferedImage bufffImage = new BufferedImage(width, height, + BufferedImage.TYPE_INT_RGB); + + Graphics2D g = bufffImage.createGraphics(); + g.setColor(BACKGROUND_COLOR); + g.fillRect(0, 0, width, height); + g.dispose(); + return bufffImage; + } + + private static class TestLAFTextDrawing implements TextUIDrawing { + + @Override + public void drawString(JComponent c, Graphics g, String string, int x, int y) { + drawStringUnderlineCharAt(c, g, string, -1, x, y); + } + + @Override + public void drawStringUnderlineCharAt(JComponent c, Graphics g, + String string, int underlinedIndex, int x, int y) { + g.setColor(BACKGROUND_COLOR); + g.fillRect(0, 0, c.getWidth(), c.getHeight()); + g.setColor(TEST_DRAW_COLOR); + g.drawString(string, x, y); + if (underlinedIndex > -1) { + int w = WIDTH; + int h = 8; + g.drawLine(x, y + h, x + w, y + h); + } + } + + @Override + public String getClippedString(JComponent c, FontMetrics fm, + String string, int availTextWidth) { + return string.substring(0, string.length() - 3) + "***"; + } + + @Override + public int getStringWidth(JComponent c, FontMetrics fm, String string) { + return fm.stringWidth(string); + } + } +}