* Calculate the width on screen, obtain a TextLayout with * advances for the printer graphics FRC, and then justify * it to fit in the screen width. This distributes the spacing * more evenly than directly laying out to the screen advances. */ float screenWidth = (float) g2d.getFont().getStringBounds(text, DEFAULT_FRC).getWidth(); TextLayout layout = createTextLayout(c, text, g2d.getFont(), g2d.getFontRenderContext()); layout = layout.getJustifiedLayout(screenWidth); /* Use alternate print color if specified */ Color col = g2d.getColor(); if (col instanceof PrintColorUIResource) { g2d.setColor(((PrintColorUIResource)col).getPrintColor()); } layout.draw(g2d, x, y); g2d.setColor(col); return; } } // If we get here we're not printing AATextInfo info = drawTextAntialiased(c); if (info != null && (g instanceof Graphics2D)) { Graphics2D g2 = (Graphics2D)g; Object oldContrast = null; Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING); if (info.aaHint != oldAAValue) { g2.setRenderingHint(KEY_TEXT_ANTIALIASING, info.aaHint); } else { oldAAValue = null; } if (info.lcdContrastHint != null) { oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST); if (info.lcdContrastHint.equals(oldContrast)) { oldContrast = null; } else { g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, info.lcdContrastHint); } } boolean needsTextLayout = ((c != null) && (c.getClientProperty(TextAttribute.NUMERIC_SHAPING) != null)); if (needsTextLayout) { synchronized(charsBufferLock) { int length = syncCharsBuffer(text); needsTextLayout = isComplexLayout(charsBuffer, 0, length); } } if (needsTextLayout) { TextLayout layout = createTextLayout(c, text, g2.getFont(), g2.getFontRenderContext()); layout.draw(g2, x, y); } else { g.drawString(text, x, y); } if (oldAAValue != null) { g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue); } if (oldContrast != null) { g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast); } } else { g.drawString(text, x, y); } } /** * Draws the string at the specified location underlining the specified * character. * * @param c JComponent that will display the string, may be null * @param g Graphics to draw the text to * @param text String to display * @param underlinedIndex Index of a character in the string to underline * @param x X coordinate to draw the text at * @param y Y coordinate to draw the text at */ public static void drawStringUnderlineCharAt(JComponent c,Graphics g, String text, int underlinedIndex, int x,int y) { if (text == null || text.length() <= 0) { return; } SwingUtilities2.drawString(c, g, text, x, y); int textLength = text.length(); if (underlinedIndex >= 0 && underlinedIndex < textLength ) { int underlineRectY = y; int underlineRectHeight = 1; int underlineRectX = 0; int underlineRectWidth = 0; boolean isPrinting = isPrinting(g); boolean needsTextLayout = isPrinting; if (!needsTextLayout) { synchronized (charsBufferLock) { syncCharsBuffer(text); needsTextLayout = isComplexLayout(charsBuffer, 0, textLength); } } if (!needsTextLayout) { FontMetrics fm = g.getFontMetrics(); underlineRectX = x + SwingUtilities2.stringWidth(c,fm, text.substring(0,underlinedIndex)); underlineRectWidth = fm.charWidth(text. charAt(underlinedIndex)); } else { Graphics2D g2d = getGraphics2D(g); if (g2d != null) { TextLayout layout = createTextLayout(c, text, g2d.getFont(), g2d.getFontRenderContext()); if (isPrinting) { float screenWidth = (float)g2d.getFont(). getStringBounds(text, DEFAULT_FRC).getWidth(); layout = layout.getJustifiedLayout(screenWidth); } TextHitInfo leading = TextHitInfo.leading(underlinedIndex); TextHitInfo trailing = TextHitInfo.trailing(underlinedIndex); Shape shape = layout.getVisualHighlightShape(leading, trailing); Rectangle rect = shape.getBounds(); underlineRectX = x + rect.x; underlineRectWidth = rect.width; } } g.fillRect(underlineRectX, underlineRectY + 1, underlineRectWidth, underlineRectHeight); } } /** * A variation of locationToIndex() which only returns an index if the * Point is within the actual bounds of a list item (not just in the cell) * and if the JList has the "List.isFileList" client property set. * Otherwise, this method returns -1. * This is used to make WindowsL&F JFileChooser act like native dialogs. */ public static int loc2IndexFileList(JList list, Point point) { int index = list.locationToIndex(point); if (index != -1) { Object bySize = list.getClientProperty("List.isFileList"); if (bySize instanceof Boolean && ((Boolean)bySize).booleanValue() && !pointIsInActualBounds(list, index, point)) { index = -1; } } return index; } /** * Returns true if the given point is within the actual bounds of the * JList item at index (not just inside the cell). */ private static boolean pointIsInActualBounds(JList list, int index, Point point) { ListCellRenderer renderer = list.getCellRenderer(); ListModel dataModel = list.getModel(); Object value = dataModel.getElementAt(index); Component item = renderer.getListCellRendererComponent(list, value, index, false, false); Dimension itemSize = item.getPreferredSize(); Rectangle cellBounds = list.getCellBounds(index, index); if (!item.getComponentOrientation().isLeftToRight()) { cellBounds.x += (cellBounds.width - itemSize.width); } cellBounds.width = itemSize.width; return cellBounds.contains(point); } /** * Returns true if the given point is outside the preferredSize of the * item at the given row of the table. (Column must be 0). * Does not check the "Table.isFileList" property. That should be checked * before calling this method. * This is used to make WindowsL&F JFileChooser act like native dialogs. */ public static boolean pointOutsidePrefSize(JTable table, int row, int column, Point p) { if (table.convertColumnIndexToModel(column) != 0 || row == -1) { return true; } TableCellRenderer tcr = table.getCellRenderer(row, column); Object value = table.getValueAt(row, column); Component cell = tcr.getTableCellRendererComponent(table, value, false, false, row, column); Dimension itemSize = cell.getPreferredSize(); Rectangle cellBounds = table.getCellRect(row, column, false); cellBounds.width = itemSize.width; cellBounds.height = itemSize.height; // See if coords are inside // ASSUME: mouse x,y will never be < cell's x,y assert (p.x >= cellBounds.x && p.y >= cellBounds.y); return p.x > cellBounds.x + cellBounds.width || p.y > cellBounds.y + cellBounds.height; } /** * Set the lead and anchor without affecting selection. */ public static void setLeadAnchorWithoutSelection(ListSelectionModel model, int lead, int anchor) { if (anchor == -1) { anchor = lead; } if (lead == -1) { model.setAnchorSelectionIndex(-1); model.setLeadSelectionIndex(-1); } else { if (model.isSelectedIndex(lead)) { model.addSelectionInterval(lead, lead); } else { model.removeSelectionInterval(lead, lead); } model.setAnchorSelectionIndex(anchor); } } /** * Ignore mouse events if the component is null, not enabled, the event * is not associated with the left mouse button, or the event has been * consumed. */ public static boolean shouldIgnore(MouseEvent me, JComponent c) { return c == null || !c.isEnabled() || !SwingUtilities.isLeftMouseButton(me) || me.isConsumed(); } /** * Request focus on the given component if it doesn't already have it * and <code>isRequestFocusEnabled()</code> returns true. */ public static void adjustFocus(JComponent c) { if (!c.hasFocus() && c.isRequestFocusEnabled()) { c.requestFocus(); } } /** * The following draw functions have the same semantic as the * Graphics methods with the same names. * * this is used for printing */ public static int drawChars(JComponent c, Graphics g, char[] data, int offset, int length, int x, int y) { if ( length <= 0 ) { //no need to paint empty strings return x; } int nextX = x + getFontMetrics(c, g).charsWidth(data, offset, length); if (isPrinting(g)) { Graphics2D g2d = getGraphics2D(g); if (g2d != null) { FontRenderContext deviceFontRenderContext = g2d. getFontRenderContext(); FontRenderContext frc = getFontRenderContext(c); if (frc != null && !isFontRenderContextPrintCompatible (deviceFontRenderContext, frc)) { TextLayout layout = createTextLayout(c, new String(data, offset, length), g2d.getFont(), deviceFontRenderContext); float screenWidth = (float)g2d.getFont(). getStringBounds(data, offset, offset + length, frc). getWidth(); layout = layout.getJustifiedLayout(screenWidth); /* Use alternate print color if specified */ Color col = g2d.getColor(); if (col instanceof PrintColorUIResource) { g2d.setColor(((PrintColorUIResource)col).getPrintColor()); } layout.draw(g2d,x,y); g2d.setColor(col); return nextX; } } } // Assume we're not printing if we get here, or that we are invoked // via Swing text printing which is laid out for the printer. AATextInfo info = drawTextAntialiased(c); if (info != null && (g instanceof Graphics2D)) { Graphics2D g2 = (Graphics2D)g; Object oldContrast = null; Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING); if (info.aaHint != null && info.aaHint != oldAAValue) { g2.setRenderingHint(KEY_TEXT_ANTIALIASING, info.aaHint); } else { oldAAValue = null; } if (info.lcdContrastHint != null) { oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST); if (info.lcdContrastHint.equals(oldContrast)) { oldContrast = null; } else { g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, info.lcdContrastHint); } } g.drawChars(data, offset, length, x, y); if (oldAAValue != null) { g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue); } if (oldContrast != null) { g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast); } } else { g.drawChars(data, offset, length, x, y); } return nextX; } /* * see documentation for drawChars * returns the advance */ public static float drawString(JComponent c, Graphics g, AttributedCharacterIterator iterator, int x, int y) { float retVal; boolean isPrinting = isPrinting(g); Color col = g.getColor(); if (isPrinting) { /* Use alternate print color if specified */ if (col instanceof PrintColorUIResource) { g.setColor(((PrintColorUIResource)col).getPrintColor()); } } Graphics2D g2d = getGraphics2D(g); if (g2d == null) { g.drawString(iterator,x,y); //for the cases where advance //matters it should not happen retVal = x; } else { FontRenderContext frc; if (isPrinting) { frc = getFontRenderContext(c); if (frc.isAntiAliased() || frc.usesFractionalMetrics()) { frc = new FontRenderContext(frc.getTransform(), false, false); } } else if ((frc = getFRCProperty(c)) != null) { /* frc = frc; ! */ } else { frc = g2d.getFontRenderContext(); } TextLayout layout = new TextLayout(iterator, frc); if (isPrinting) { FontRenderContext deviceFRC = g2d.getFontRenderContext(); if (!isFontRenderContextPrintCompatible(frc, deviceFRC)) { float screenWidth = layout.getAdvance(); layout = new TextLayout(iterator, deviceFRC); layout = layout.getJustifiedLayout(screenWidth); } } layout.draw(g2d, x, y); retVal = layout.getAdvance(); } if (isPrinting) { g.setColor(col); } return retVal; } private static TextLayout createTextLayout(JComponent c, String s, Font f, FontRenderContext frc) { Object shaper = (c == null ? null : c.getClientProperty(TextAttribute.NUMERIC_SHAPING)); if (shaper == null) { return new TextLayout(s, f, frc); } else { Map<TextAttribute, Object> a = new HashMap<TextAttribute, Object>(); a.put(TextAttribute.FONT, f); a.put(TextAttribute.NUMERIC_SHAPING, shaper); return new TextLayout(s, a, frc); } } /* * Checks if two given FontRenderContexts are compatible for printing. * We can't just use equals as we want to exclude from the comparison : * + whether AA is set as irrelevant for printing and shouldn't affect * printed metrics anyway * + any translation component in the transform of either FRC, as it * does not affect metrics. * Compatible means no special handling needed for text painting */ private static boolean isFontRenderContextPrintCompatible(FontRenderContext frc1, FontRenderContext frc2) { if (frc1 == frc2) { return true; } if (frc1 == null || frc2 == null) { // not supposed to happen return false; } if (frc1.getFractionalMetricsHint() != frc2.getFractionalMetricsHint()) { return false; } /* If both are identity, return true */ if (!frc1.isTransformed() && !frc2.isTransformed()) { return true; } /* That's the end of the cheap tests, need to get and compare * the transform matrices. We don't care about the translation * components, so return true if they are otherwise identical. */ double[] mat1 = new double[4]; double[] mat2 = new double[4]; frc1.getTransform().getMatrix(mat1); frc2.getTransform().getMatrix(mat2); return mat1[0] == mat2[0] && mat1[1] == mat2[1] && mat1[2] == mat2[2] && mat1[3] == mat2[3]; } /* * Tries it best to get Graphics2D out of the given Graphics * returns null if can not derive it. */ public static Graphics2D getGraphics2D(Graphics g) { if (g instanceof Graphics2D) { return (Graphics2D) g; } else if (g instanceof ProxyPrintGraphics) { return (Graphics2D)(((ProxyPrintGraphics)g).getGraphics()); } else { return null; } } /* * Returns FontRenderContext associated with Component. * FontRenderContext from Component.getFontMetrics is associated * with the component. * * Uses Component.getFontMetrics to get the FontRenderContext from. * see JComponent.getFontMetrics and TextLayoutStrategy.java */ public static FontRenderContext getFontRenderContext(Component c) { assert c != null; if (c == null) { return DEFAULT_FRC; } else { return c.getFontMetrics(c.getFont()).getFontRenderContext(); } } /** * A convenience method to get FontRenderContext. * Returns the FontRenderContext for the passed in FontMetrics or * for the passed in Component if FontMetrics is null */ private static FontRenderContext getFontRenderContext(Component c, FontMetrics fm) { assert fm != null || c!= null; return (fm != null) ? fm.getFontRenderContext() : getFontRenderContext(c); } Lines 501–1000 of 1871. Previous lines Load more
* Calculate the width on screen, obtain a TextLayout with * advances for the printer graphics FRC, and then justify * it to fit in the screen width. This distributes the spacing * more evenly than directly laying out to the screen advances. */ float screenWidth = (float) g2d.getFont().getStringBounds(text, DEFAULT_FRC).getWidth(); TextLayout layout = createTextLayout(c, text, g2d.getFont(), g2d.getFontRenderContext()); layout = layout.getJustifiedLayout(screenWidth); /* Use alternate print color if specified */ Color col = g2d.getColor(); if (col instanceof PrintColorUIResource) { g2d.setColor(((PrintColorUIResource)col).getPrintColor()); } layout.draw(g2d, x, y); g2d.setColor(col); return; } } // If we get here we're not printing AATextInfo info = drawTextAntialiased(c); if (info != null && (g instanceof Graphics2D)) { Graphics2D g2 = (Graphics2D)g; Object oldContrast = null; Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING); if (info.aaHint != oldAAValue) { g2.setRenderingHint(KEY_TEXT_ANTIALIASING, info.aaHint); } else { oldAAValue = null; } if (info.lcdContrastHint != null) { oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST); if (info.lcdContrastHint.equals(oldContrast)) { oldContrast = null; } else { g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, info.lcdContrastHint); } } boolean needsTextLayout = ((c != null) && (c.getClientProperty(TextAttribute.NUMERIC_SHAPING) != null)); if (needsTextLayout) { synchronized(charsBufferLock) { int length = syncCharsBuffer(text); needsTextLayout = isComplexLayout(charsBuffer, 0, length); } } if (needsTextLayout) { TextLayout layout = createTextLayout(c, text, g2.getFont(), g2.getFontRenderContext()); layout.draw(g2, x, y); } else { g.drawString(text, x, y); } if (oldAAValue != null) { g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue); } if (oldContrast != null) { g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast); } } else { g.drawString(text, x, y); } } /** * Draws the string at the specified location underlining the specified * character. * * @param c JComponent that will display the string, may be null * @param g Graphics to draw the text to * @param text String to display * @param underlinedIndex Index of a character in the string to underline * @param x X coordinate to draw the text at * @param y Y coordinate to draw the text at */ public static void drawStringUnderlineCharAt(JComponent c,Graphics g, String text, int underlinedIndex, int x,int y) { if (text == null || text.length() <= 0) { return; } SwingUtilities2.drawString(c, g, text, x, y); int textLength = text.length(); if (underlinedIndex >= 0 && underlinedIndex < textLength ) { int underlineRectY = y; int underlineRectHeight = 1; int underlineRectX = 0; int underlineRectWidth = 0; boolean isPrinting = isPrinting(g); boolean needsTextLayout = isPrinting; if (!needsTextLayout) { synchronized (charsBufferLock) { syncCharsBuffer(text); needsTextLayout = isComplexLayout(charsBuffer, 0, textLength); } } if (!needsTextLayout) { FontMetrics fm = g.getFontMetrics(); underlineRectX = x + SwingUtilities2.stringWidth(c,fm, text.substring(0,underlinedIndex)); underlineRectWidth = fm.charWidth(text. charAt(underlinedIndex)); } else { Graphics2D g2d = getGraphics2D(g); if (g2d != null) { TextLayout layout = createTextLayout(c, text, g2d.getFont(), g2d.getFontRenderContext()); if (isPrinting) { float screenWidth = (float)g2d.getFont(). getStringBounds(text, DEFAULT_FRC).getWidth(); layout = layout.getJustifiedLayout(screenWidth); } TextHitInfo leading = TextHitInfo.leading(underlinedIndex); TextHitInfo trailing = TextHitInfo.trailing(underlinedIndex); Shape shape = layout.getVisualHighlightShape(leading, trailing); Rectangle rect = shape.getBounds(); underlineRectX = x + rect.x; underlineRectWidth = rect.width; } } g.fillRect(underlineRectX, underlineRectY + 1, underlineRectWidth, underlineRectHeight); } } /** * A variation of locationToIndex() which only returns an index if the * Point is within the actual bounds of a list item (not just in the cell) * and if the JList has the "List.isFileList" client property set. * Otherwise, this method returns -1. * This is used to make WindowsL&F JFileChooser act like native dialogs. */ public static int loc2IndexFileList(JList list, Point point) { int index = list.locationToIndex(point); if (index != -1) { Object bySize = list.getClientProperty("List.isFileList"); if (bySize instanceof Boolean && ((Boolean)bySize).booleanValue() && !pointIsInActualBounds(list, index, point)) { index = -1; } } return index; } /** * Returns true if the given point is within the actual bounds of the * JList item at index (not just inside the cell). */ private static boolean pointIsInActualBounds(JList list, int index, Point point) { ListCellRenderer renderer = list.getCellRenderer(); ListModel dataModel = list.getModel(); Object value = dataModel.getElementAt(index); Component item = renderer.getListCellRendererComponent(list, value, index, false, false); Dimension itemSize = item.getPreferredSize(); Rectangle cellBounds = list.getCellBounds(index, index); if (!item.getComponentOrientation().isLeftToRight()) { cellBounds.x += (cellBounds.width - itemSize.width); } cellBounds.width = itemSize.width; return cellBounds.contains(point); } /** * Returns true if the given point is outside the preferredSize of the * item at the given row of the table. (Column must be 0). * Does not check the "Table.isFileList" property. That should be checked * before calling this method. * This is used to make WindowsL&F JFileChooser act like native dialogs. */ public static boolean pointOutsidePrefSize(JTable table, int row, int column, Point p) { if (table.convertColumnIndexToModel(column) != 0 || row == -1) { return true; } TableCellRenderer tcr = table.getCellRenderer(row, column); Object value = table.getValueAt(row, column); Component cell = tcr.getTableCellRendererComponent(table, value, false, false, row, column); Dimension itemSize = cell.getPreferredSize(); Rectangle cellBounds = table.getCellRect(row, column, false); cellBounds.width = itemSize.width; cellBounds.height = itemSize.height; // See if coords are inside // ASSUME: mouse x,y will never be < cell's x,y assert (p.x >= cellBounds.x && p.y >= cellBounds.y); return p.x > cellBounds.x + cellBounds.width || p.y > cellBounds.y + cellBounds.height; } /** * Set the lead and anchor without affecting selection. */ public static void setLeadAnchorWithoutSelection(ListSelectionModel model, int lead, int anchor) { if (anchor == -1) { anchor = lead; } if (lead == -1) { model.setAnchorSelectionIndex(-1); model.setLeadSelectionIndex(-1); } else { if (model.isSelectedIndex(lead)) { model.addSelectionInterval(lead, lead); } else { model.removeSelectionInterval(lead, lead); } model.setAnchorSelectionIndex(anchor); } } /** * Ignore mouse events if the component is null, not enabled, the event * is not associated with the left mouse button, or the event has been * consumed. */ public static boolean shouldIgnore(MouseEvent me, JComponent c) { return c == null || !c.isEnabled() || !SwingUtilities.isLeftMouseButton(me) || me.isConsumed(); } /** * Request focus on the given component if it doesn't already have it * and <code>isRequestFocusEnabled()</code> returns true. */ public static void adjustFocus(JComponent c) { if (!c.hasFocus() && c.isRequestFocusEnabled()) { c.requestFocus(); } } /** * The following draw functions have the same semantic as the * Graphics methods with the same names. * * this is used for printing */ public static int drawChars(JComponent c, Graphics g, char[] data, int offset, int length, int x, int y) { if ( length <= 0 ) { //no need to paint empty strings return x; } int nextX = x + getFontMetrics(c, g).charsWidth(data, offset, length); if (isPrinting(g)) { Graphics2D g2d = getGraphics2D(g); if (g2d != null) { FontRenderContext deviceFontRenderContext = g2d. getFontRenderContext(); FontRenderContext frc = getFontRenderContext(c); if (frc != null && !isFontRenderContextPrintCompatible (deviceFontRenderContext, frc)) { TextLayout layout = createTextLayout(c, new String(data, offset, length), g2d.getFont(), deviceFontRenderContext); float screenWidth = (float)g2d.getFont(). getStringBounds(data, offset, offset + length, frc). getWidth(); layout = layout.getJustifiedLayout(screenWidth); /* Use alternate print color if specified */ Color col = g2d.getColor(); if (col instanceof PrintColorUIResource) { g2d.setColor(((PrintColorUIResource)col).getPrintColor()); } layout.draw(g2d,x,y); g2d.setColor(col); return nextX; } } } // Assume we're not printing if we get here, or that we are invoked // via Swing text printing which is laid out for the printer. AATextInfo info = drawTextAntialiased(c); if (info != null && (g instanceof Graphics2D)) { Graphics2D g2 = (Graphics2D)g; Object oldContrast = null; Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING); if (info.aaHint != null && info.aaHint != oldAAValue) { g2.setRenderingHint(KEY_TEXT_ANTIALIASING, info.aaHint); } else { oldAAValue = null; } if (info.lcdContrastHint != null) { oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST); if (info.lcdContrastHint.equals(oldContrast)) { oldContrast = null; } else { g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, info.lcdContrastHint); } } g.drawChars(data, offset, length, x, y); if (oldAAValue != null) { g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue); } if (oldContrast != null) { g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast); } } else { g.drawChars(data, offset, length, x, y); } return nextX; } /* * see documentation for drawChars * returns the advance */ public static float drawString(JComponent c, Graphics g, AttributedCharacterIterator iterator, int x, int y) { float retVal; boolean isPrinting = isPrinting(g); Color col = g.getColor(); if (isPrinting) { /* Use alternate print color if specified */ if (col instanceof PrintColorUIResource) { g.setColor(((PrintColorUIResource)col).getPrintColor()); } } Graphics2D g2d = getGraphics2D(g); if (g2d == null) { g.drawString(iterator,x,y); //for the cases where advance //matters it should not happen retVal = x; } else { FontRenderContext frc; if (isPrinting) { frc = getFontRenderContext(c); if (frc.isAntiAliased() || frc.usesFractionalMetrics()) { frc = new FontRenderContext(frc.getTransform(), false, false); } } else if ((frc = getFRCProperty(c)) != null) { /* frc = frc; ! */ } else { frc = g2d.getFontRenderContext(); } TextLayout layout = new TextLayout(iterator, frc); if (isPrinting) { FontRenderContext deviceFRC = g2d.getFontRenderContext(); if (!isFontRenderContextPrintCompatible(frc, deviceFRC)) { float screenWidth = layout.getAdvance(); layout = new TextLayout(iterator, deviceFRC); layout = layout.getJustifiedLayout(screenWidth); } } layout.draw(g2d, x, y); retVal = layout.getAdvance(); } if (isPrinting) { g.setColor(col); } return retVal; } private static TextLayout createTextLayout(JComponent c, String s, Font f, FontRenderContext frc) { Object shaper = (c == null ? null : c.getClientProperty(TextAttribute.NUMERIC_SHAPING)); if (shaper == null) { return new TextLayout(s, f, frc); } else { Map<TextAttribute, Object> a = new HashMap<TextAttribute, Object>(); a.put(TextAttribute.FONT, f); a.put(TextAttribute.NUMERIC_SHAPING, shaper); return new TextLayout(s, a, frc); } } /* * Checks if two given FontRenderContexts are compatible for printing. * We can't just use equals as we want to exclude from the comparison : * + whether AA is set as irrelevant for printing and shouldn't affect * printed metrics anyway * + any translation component in the transform of either FRC, as it * does not affect metrics. * Compatible means no special handling needed for text painting */ private static boolean isFontRenderContextPrintCompatible(FontRenderContext frc1, FontRenderContext frc2) { if (frc1 == frc2) { return true; } if (frc1 == null || frc2 == null) { // not supposed to happen return false; } if (frc1.getFractionalMetricsHint() != frc2.getFractionalMetricsHint()) { return false; } /* If both are identity, return true */ if (!frc1.isTransformed() && !frc2.isTransformed()) { return true; } /* That's the end of the cheap tests, need to get and compare * the transform matrices. We don't care about the translation * components, so return true if they are otherwise identical. */ double[] mat1 = new double[4]; double[] mat2 = new double[4]; frc1.getTransform().getMatrix(mat1); frc2.getTransform().getMatrix(mat2); return mat1[0] == mat2[0] && mat1[1] == mat2[1] && mat1[2] == mat2[2] && mat1[3] == mat2[3]; } /* * Tries it best to get Graphics2D out of the given Graphics * returns null if can not derive it. */ public static Graphics2D getGraphics2D(Graphics g) { if (g instanceof Graphics2D) { return (Graphics2D) g; } else if (g instanceof ProxyPrintGraphics) { return (Graphics2D)(((ProxyPrintGraphics)g).getGraphics()); } else { return null; } } /* * Returns FontRenderContext associated with Component. * FontRenderContext from Component.getFontMetrics is associated * with the component. * * Uses Component.getFontMetrics to get the FontRenderContext from. * see JComponent.getFontMetrics and TextLayoutStrategy.java */ public static FontRenderContext getFontRenderContext(Component c) { assert c != null; if (c == null) { return DEFAULT_FRC; } else { return c.getFontMetrics(c.getFont()).getFontRenderContext(); } } /** * A convenience method to get FontRenderContext. * Returns the FontRenderContext for the passed in FontMetrics or * for the passed in Component if FontMetrics is null */ private static FontRenderContext getFontRenderContext(Component c, FontMetrics fm) { assert fm != null || c!= null; return (fm != null) ? fm.getFontRenderContext() : getFontRenderContext(c); }