Example usage for java.awt Graphics drawString

List of usage examples for java.awt Graphics drawString

Introduction

In this page you can find the example usage for java.awt Graphics drawString.

Prototype

public abstract void drawString(AttributedCharacterIterator iterator, int x, int y);

Source Link

Document

Renders the text of the specified iterator applying its attributes in accordance with the specification of the java.awt.font.TextAttribute TextAttribute class.

Usage

From source file:net.sourceforge.msscodefactory.cflib.v1_11.CFLib.Swing.CFReferenceColumnCellRenderer.java

public void paint(Graphics g) {
    if (g == null) {
        return;//from   ww  w  .ja  va 2s  . co  m
    }
    Rectangle bounds = getBounds();
    g.setColor(getBackground());
    g.fill3DRect(0, 0, bounds.width, bounds.height, true);
    g.setColor(getForeground());
    String str;
    if (value instanceof ICFLibAnyObj2) {
        ICFLibAnyObj2 anyObj = (ICFLibAnyObj2) value;
        str = anyObj.getObjQualifiedName();
    } else if (value instanceof String) {
        str = (String) value;
    } else {
        str = null;
    }
    if (str != null) {
        int firstNewline = str.indexOf('\n');
        if (firstNewline < 0) {
            firstNewline = str.indexOf('\r');
            if (firstNewline < 0) {
                firstNewline = str.indexOf('\f');
                if (firstNewline < 0) {
                    firstNewline = str.length();
                }
            }
        }
        String firstLine = str.substring(0, firstNewline);
        FontMetrics fm = g.getFontMetrics();
        int ascent = fm.getAscent();
        int leading = fm.getLeading();
        g.drawString(firstLine, 4, leading + ascent + 4);
    }
}

From source file:org.fcrepo.localservices.imagemanip.ImageManipulation.java

/**
 * Method automatically called by browser to handle image manipulations.
 * // w  ww.  j  a va2 s  . c o  m
 * @param req
 *        Browser request to servlet res Response sent back to browser after
 *        image manipulation
 * @throws IOException
 *         If an input or output exception occurred ServletException If a
 *         servlet exception occurred
 */
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    System.setProperty("java.awt.headless", "true");
    // collect all possible parameters for servlet
    String url = req.getParameter("url");
    String op = req.getParameter("op");
    String newWidth = req.getParameter("newWidth");
    String brightAmt = req.getParameter("brightAmt");
    String zoomAmt = req.getParameter("zoomAmt");
    String wmText = req.getParameter("wmText");
    String cropX = req.getParameter("cropX");
    String cropY = req.getParameter("cropY");
    String cropWidth = req.getParameter("cropWidth");
    String cropHeight = req.getParameter("cropHeight");
    String convertTo = req.getParameter("convertTo");
    if (convertTo != null) {
        convertTo = convertTo.toLowerCase();
    }
    try {
        if (op == null) {
            throw new ServletException("op parameter not specified.");
        }
        String outputMimeType;
        // get the image via url and put it into the ImagePlus processor.
        BufferedImage img = getImage(url);
        // do watermarking stuff
        if (op.equals("watermark")) {
            if (wmText == null) {
                throw new ServletException("Must specify wmText.");
            }
            Graphics g = img.getGraphics();
            int fontSize = img.getWidth() * 3 / 100;
            if (fontSize < 10) {
                fontSize = 10;
            }
            g.setFont(new Font("Lucida Sans", Font.BOLD, fontSize));
            FontMetrics fm = g.getFontMetrics();
            int stringWidth = (int) fm.getStringBounds(wmText, g).getWidth();
            int x = img.getWidth() / 2 - stringWidth / 2;
            int y = img.getHeight() - fm.getHeight();
            g.setColor(new Color(180, 180, 180));
            g.fill3DRect(x - 10, y - fm.getHeight() - 4, stringWidth + 20, fm.getHeight() + 12, true);
            g.setColor(new Color(100, 100, 100));
            g.drawString(wmText, x + 2, y + 2);
            g.setColor(new Color(240, 240, 240));
            g.drawString(wmText, x, y);
        }
        ImageProcessor ip = new ImagePlus("temp", img).getProcessor();
        // if the inputMimeType is image/gif, need to convert to RGB in any case
        if (inputMimeType.equals("image/gif")) {
            ip = ip.convertToRGB();
            alreadyConvertedToRGB = true;
        }
        // causes scale() and resize() to do bilinear interpolation
        ip.setInterpolate(true);
        if (!op.equals("convert")) {
            if (op.equals("resize")) {
                ip = resize(ip, newWidth);
            } else if (op.equals("zoom")) {
                ip = zoom(ip, zoomAmt);
            } else if (op.equals("brightness")) {
                ip = brightness(ip, brightAmt);
            } else if (op.equals("watermark")) {
                // this is now taken care of beforehand (see above)
            } else if (op.equals("grayscale")) {
                ip = grayscale(ip);
            } else if (op.equals("crop")) {
                ip = crop(ip, cropX, cropY, cropWidth, cropHeight);
            } else {
                throw new ServletException("Invalid operation: " + op);
            }
            outputMimeType = inputMimeType;
        } else {
            if (convertTo == null) {
                throw new ServletException("Neither op nor convertTo was specified.");
            }
            if (convertTo.equals("jpg") || convertTo.equals("jpeg")) {
                outputMimeType = "image/jpeg";
            } else if (convertTo.equals("gif")) {
                outputMimeType = "image/gif";
            } else if (convertTo.equals("tiff")) {
                outputMimeType = "image/tiff";
            } else if (convertTo.equals("bmp")) {
                outputMimeType = "image/bmp";
            } else if (convertTo.equals("png")) {
                outputMimeType = "image/png";
            } else {
                throw new ServletException("Invalid format: " + convertTo);
            }
        }
        res.setContentType(outputMimeType);
        BufferedOutputStream out = new BufferedOutputStream(res.getOutputStream());
        outputImage(ip, out, outputMimeType);
        out.flush();
        out.close();
    } catch (Exception e) {
        e.printStackTrace();
        res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                e.getClass().getName() + ": " + e.getMessage());
    }
}

From source file:ImageLabel.java

public void paint(Graphics g) {

    /*/*from   w w w.ja  va  2 s  .  c om*/
     * Draw the image stretched to exactly cover the size of the drawing area.
     */
    Dimension size = getSize();
    g.drawImage(img, 0, 0, size.width, size.height, 0, 0, img.getWidth(null), img.getHeight(null), null);

    /*
     * Fill a rounded rectangle centered in the drawing area. Calculate the size
     * of the rectangle from the size of the text
     */
    g.setFont(font);
    FontRenderContext frc = ((Graphics2D) g).getFontRenderContext();
    Rectangle2D bounds = font.getStringBounds(text, frc);

    int wText = (int) bounds.getWidth();
    int hText = (int) bounds.getHeight();

    int rX = (size.width - wText) / 2;
    int rY = (size.height - hText) / 2;
    g.setColor(Color.yellow);
    g.fillRoundRect(rX, rY, wText, hText, hText / 2, hText / 2);

    /*
     * Draw text positioned in the rectangle. Since the rectangle is sized based
     * on the bounds of the String we can position it using those bounds.
     */
    int xText = rX - (int) bounds.getX();
    int yText = rY - (int) bounds.getY();
    g.setColor(Color.black);
    g.setFont(font);
    g.drawString(text, xText, yText);
}

From source file:edu.ku.brc.specify.ui.containers.ContainerTreeRenderer.java

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Dimension d = getSize();//from www  .  j  a v a2 s.  c  o m
    //System.out.println("d: "+d+"     "+g.getClipBounds());

    Graphics2D g2d = (Graphics2D) g.create();
    g2d.setRenderingHints(renderingHints);

    FontMetrics fm = g2d.getFontMetrics();
    int imgY = img1 != null ? (d.height - 24) / 2 : 0;
    int imgY2 = img1 != null ? (d.height - 16) / 2 : 0;
    int txtY = ((d.height - fm.getHeight()) / 2) + fm.getAscent();
    int x = 0;

    Color color = g2d.getColor();

    if (img1 != null) {
        g2d.drawImage(img1.getImage(), x, imgY, null);
        x += img1.getIconWidth();
    }

    int iconInx = 0;

    if (txt1 != null) {
        x += getIconTextGap();
        g2d.setColor(getForeground());
        g.drawString(txt1, x, txtY);
        x += fm.stringWidth(txt1);
        g2d.setColor(color);
    }

    if (isContainer) {
        //if (isSelected  && isEditable)
        //{
        //    x += drawIcon(g2d, x, imgY2, delImgIcon, iconInx++); // Delete the container
        //}

        if (hasColObj) {
            if (img2 != null) {
                x += 1;
                x += iconSep;
                g2d.drawImage(img2.getImage(), x, imgY2, null);
                x += img2.getIconWidth();
            }

            if (txt2 != null) {
                x += getIconTextGap();
                g2d.setColor(getForeground());
                g.drawString(txt2, x, txtY);
                x += fm.stringWidth(txt2);
                g2d.setColor(color);
            }

            if (isSelected) {
                x += iconSep;
                x += drawIcon(g2d, x, imgY2, viewImgIcon, iconInx++);

                if (isEditable) {
                    x += drawIcon(g2d, x, imgY2, delImgIcon, iconInx++);
                }
            }
        } else if (isSelected) // No Col Obj
        {
            x += iconSep;
            x += drawIcon(g2d, x, imgY2, schImgIcon, iconInx++);
            x += drawIcon(g2d, x, imgY2, addImgIcon, iconInx++);
        }

    } else if (isSelected) {
        x += iconSep;
        x += drawIcon(g2d, x, imgY2, viewImgIcon, iconInx++); // View for Collection Object

        //if (!isViewMode)
        //{
        //    x += iconSep;
        //    x += drawIcon(g2d, x, imgY2, delImgIcon, iconInx++); // Delete for Collection Object
        //}
    }

    g2d.dispose();
}

From source file:net.sourceforge.msscodefactory.cflib.v1_11.CFLib.Swing.CFDateColumnCellRenderer.java

public void paint(Graphics g) {
    if (g == null) {
        return;/*from  www.j av  a 2 s  .  co m*/
    }
    Rectangle bounds = getBounds();
    g.setColor(getBackground());
    g.fill3DRect(0, 0, bounds.width, bounds.height, true);
    g.setColor(getForeground());
    String str;
    if (value instanceof Calendar) {
        Calendar cal = (Calendar) value;
        Format fmt = getDefaultFormat();
        str = fmt.format(cal.getTime());
    } else if (value instanceof String) {
        str = (String) value;
    } else {
        str = null;
    }
    if (str != null) {
        int firstNewline = str.indexOf('\n');
        if (firstNewline < 0) {
            firstNewline = str.indexOf('\r');
            if (firstNewline < 0) {
                firstNewline = str.indexOf('\f');
                if (firstNewline < 0) {
                    firstNewline = str.length();
                }
            }
        }
        String firstLine = str.substring(0, firstNewline);
        FontMetrics fm = g.getFontMetrics();
        int ascent = fm.getAscent();
        int leading = fm.getLeading();
        g.drawString(firstLine, 4, leading + ascent + 4);
    }
}

From source file:edu.uci.ics.jung.samples.PerspectiveVertexImageShaperDemo.java

/**
 * create an instance of a simple graph with controls to
 * demo the zoom features./*from ww  w  .  j  av a2  s  .  c om*/
 * 
 */
@SuppressWarnings("serial")
public PerspectiveVertexImageShaperDemo() {

    // create a simple graph for the demo
    graph = new DirectedSparseMultigraph<Number, Number>();
    Number[] vertices = createVertices(11);

    // a Map for the labels
    Map<Number, String> map = new HashMap<Number, String>();
    for (int i = 0; i < vertices.length; i++) {
        map.put(vertices[i], iconNames[i % iconNames.length]);
    }

    // a Map for the Icons
    Map<Number, Icon> iconMap = new HashMap<Number, Icon>();
    for (int i = 0; i < vertices.length; i++) {
        String name = "/images/topic" + iconNames[i] + ".gif";
        try {
            Icon icon = new LayeredIcon(
                    new ImageIcon(PerspectiveVertexImageShaperDemo.class.getResource(name)).getImage());
            iconMap.put(vertices[i], icon);
        } catch (Exception ex) {
            System.err.println("You need slashdoticons.jar in your classpath to see the image " + name);
        }
    }

    createEdges(vertices);

    final VertexStringerImpl<Number> vertexStringerImpl = new VertexStringerImpl<Number>(map);

    final VertexIconShapeTransformer<Number> vertexImageShapeFunction = new VertexIconShapeTransformer<Number>(
            new EllipseVertexShapeTransformer<Number>());

    FRLayout<Number, Number> layout = new FRLayout<Number, Number>(graph);
    layout.setMaxIterations(100);
    vv = new VisualizationViewer<Number, Number>(layout, new Dimension(400, 400));

    vv.setBackground(Color.decode("0xffffdd"));
    final DefaultVertexIconTransformer<Number> vertexIconFunction = new DefaultVertexIconTransformer<Number>();
    vertexImageShapeFunction.setIconMap(iconMap);
    vertexIconFunction.setIconMap(iconMap);
    vv.getRenderContext().setVertexShapeTransformer(vertexImageShapeFunction);
    vv.getRenderContext().setVertexIconTransformer(vertexIconFunction);
    vv.getRenderContext().setVertexLabelTransformer(vertexStringerImpl);
    PickedState<Number> ps = vv.getPickedVertexState();
    ps.addItemListener(new PickWithIconListener(vertexIconFunction));

    vv.addPostRenderPaintable(new VisualizationServer.Paintable() {
        int x;
        int y;
        Font font;
        FontMetrics metrics;
        int swidth;
        int sheight;
        String str = "Thank You, slashdot.org, for the images!";

        public void paint(Graphics g) {
            Dimension d = vv.getSize();
            if (font == null) {
                font = new Font(g.getFont().getName(), Font.BOLD, 20);
                metrics = g.getFontMetrics(font);
                swidth = metrics.stringWidth(str);
                sheight = metrics.getMaxAscent() + metrics.getMaxDescent();
                x = (d.width - swidth) / 2;
                y = (int) (d.height - sheight * 1.5);
            }
            g.setFont(font);
            Color oldColor = g.getColor();
            g.setColor(Color.lightGray);
            g.drawString(str, x, y);
            g.setColor(oldColor);
        }

        public boolean useTransform() {
            return false;
        }
    });

    // add a listener for ToolTips
    vv.setVertexToolTipTransformer(new ToStringLabeller<Number>());

    Container content = getContentPane();
    final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
    content.add(panel);

    final DefaultModalGraphMouse<Number, Number> graphMouse = new DefaultModalGraphMouse<Number, Number>();

    vv.setGraphMouse(graphMouse);

    this.viewSupport = new PerspectiveImageLensSupport<Number, Number>(vv);
    this.layoutSupport = new PerspectiveLayoutTransformSupport<Number, Number>(vv);

    final ScalingControl scaler = new CrossoverScalingControl();

    JButton plus = new JButton("+");
    plus.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            scaler.scale(vv, 1.1f, vv.getCenter());
        }
    });
    JButton minus = new JButton("-");
    minus.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            scaler.scale(vv, 0.9f, vv.getCenter());
        }
    });
    final JSlider horizontalSlider = new JSlider(-120, 120, 0) {

        /* (non-Javadoc)
         * @see javax.swing.JComponent#getPreferredSize()
         */
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(80, super.getPreferredSize().height);
        }
    };

    final JSlider verticalSlider = new JSlider(-120, 120, 0) {

        /* (non-Javadoc)
         * @see javax.swing.JComponent#getPreferredSize()
         */
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(super.getPreferredSize().width, 80);
        }
    };
    verticalSlider.setOrientation(JSlider.VERTICAL);
    final ChangeListener changeListener = new ChangeListener() {

        public void stateChanged(ChangeEvent e) {
            int vval = -verticalSlider.getValue();
            int hval = horizontalSlider.getValue();

            Dimension d = vv.getSize();
            PerspectiveTransform pt = null;
            pt = PerspectiveTransform.getQuadToQuad(vval, hval, d.width - vval, -hval, d.width + vval,
                    d.height + hval, -vval, d.height - hval,

                    0, 0, d.width, 0, d.width, d.height, 0, d.height);

            viewSupport.getPerspectiveTransformer().setPerspectiveTransform(pt);
            layoutSupport.getPerspectiveTransformer().setPerspectiveTransform(pt);
            vv.repaint();
        }
    };
    horizontalSlider.addChangeListener(changeListener);
    verticalSlider.addChangeListener(changeListener);

    JPanel perspectivePanel = new JPanel(new BorderLayout());
    JPanel perspectiveCenterPanel = new JPanel(new BorderLayout());
    perspectivePanel.setBorder(BorderFactory.createTitledBorder("Perspective Controls"));
    final JButton center = new JButton("Center");
    center.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent e) {
            horizontalSlider.setValue(0);
            verticalSlider.setValue(0);
        }
    });

    final JCheckBox noText = new JCheckBox("No Text");
    noText.addItemListener(new ItemListener() {

        public void itemStateChanged(ItemEvent e) {
            JCheckBox cb = (JCheckBox) e.getSource();
            vertexStringerImpl.setEnabled(!cb.isSelected());
            vv.repaint();
        }
    });
    JPanel centerPanel = new JPanel();
    centerPanel.add(noText);

    ButtonGroup radio = new ButtonGroup();
    JRadioButton none = new JRadioButton("None");
    none.addItemListener(new ItemListener() {
        public void itemStateChanged(ItemEvent e) {
            boolean selected = e.getStateChange() == ItemEvent.SELECTED;
            if (selected) {
                if (viewSupport != null) {
                    viewSupport.deactivate();
                }
                if (layoutSupport != null) {
                    layoutSupport.deactivate();
                }
            }
            center.setEnabled(!selected);
            horizontalSlider.setEnabled(!selected);
            verticalSlider.setEnabled(!selected);
        }
    });
    none.setSelected(true);

    JRadioButton hyperView = new JRadioButton("View");
    hyperView.addItemListener(new ItemListener() {
        public void itemStateChanged(ItemEvent e) {
            viewSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
        }
    });

    JRadioButton hyperModel = new JRadioButton("Layout");
    hyperModel.addItemListener(new ItemListener() {
        public void itemStateChanged(ItemEvent e) {
            layoutSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
        }
    });
    radio.add(none);
    radio.add(hyperView);
    radio.add(hyperModel);

    JMenuBar menubar = new JMenuBar();
    JMenu modeMenu = graphMouse.getModeMenu();
    menubar.add(modeMenu);

    panel.setCorner(menubar);

    JPanel scaleGrid = new JPanel(new GridLayout(2, 0));
    scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom"));
    JPanel controls = new JPanel(new BorderLayout());
    scaleGrid.add(plus);
    scaleGrid.add(minus);
    controls.add(scaleGrid, BorderLayout.WEST);

    JPanel lensPanel = new JPanel(new GridLayout(2, 0));
    lensPanel.add(none);
    lensPanel.add(hyperView);
    lensPanel.add(hyperModel);

    perspectivePanel.add(lensPanel, BorderLayout.WEST);
    perspectiveCenterPanel.add(horizontalSlider, BorderLayout.SOUTH);
    perspectivePanel.add(verticalSlider, BorderLayout.EAST);
    perspectiveCenterPanel.add(center);
    perspectivePanel.add(perspectiveCenterPanel);
    controls.add(perspectivePanel, BorderLayout.EAST);

    controls.add(centerPanel);
    content.add(controls, BorderLayout.SOUTH);
}

From source file:tilt.image.page.Line.java

/**
 * Print the shapes onto the original image
 * @param g the graphics environment//from   ww w  . j av a  2s. c  o m
 * @param wr the raster to write on
 * @param n the number of the line
 */
public void print(Graphics g, WritableRaster wr, int n) {
    Color tColour;
    if (n % 3 == 0)
        tColour = new Color(255, 0, 0, 128);
    else if (n % 3 == 1)
        tColour = new Color(0, 255, 0, 128);
    else
        tColour = new Color(0, 0, 255, 128);
    Color old = g.getColor();
    if (shapes.size() > 0) {
        Rectangle bounds = shapes.get(0).getBounds();
        g.setColor(Color.black);
        g.drawString(Integer.toString(n), bounds.x - 20, (bounds.y * 2 + bounds.height) / 2);
    }
    for (int i = 0; i < shapes.size(); i++) {
        Shape s = shapes.get(i);
        g.setColor(tColour);
        if (s instanceof Polygon)
            g.fillPolygon((Polygon) s);
        else if (s instanceof Rectangle) {
            Rectangle r = (Rectangle) s;
            g.fillRect(r.x, r.y, r.width, r.height);
        }
    }
    g.setColor(old);
}

From source file:edu.ku.brc.af.core.NavBox.java

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);

    Dimension dim = getSize();/*from   w ww. j  av  a2s. c  o  m*/

    FontMetrics fm = g.getFontMetrics();
    int strW = fm.stringWidth(name);

    int x = (dim.width - strW) / 2;
    Insets ins = getBorder().getBorderInsets(this);
    int y = 2 + fm.getAscent();

    int lineW = dim.width - ins.left - ins.right;
    x = ins.left;
    int txtY = y;
    y += 3;

    g.setColor(Color.LIGHT_GRAY);
    g.drawLine(x, y, x + lineW, y);
    y++;
    minHeight = y;

    x++;
    g.setColor(Color.LIGHT_GRAY.darker());
    g.drawLine(x, y, x + lineW, y);

    ((Graphics2D) g).setRenderingHints(UIHelper.createTextRenderingHints());
    g.setColor(Color.BLUE.darker());
    g.drawString(name, x, txtY);

    if (collapsableIconOpen != null) {
        if (iconRect == null) {
            iconRect = getBounds();
            iconRect.x = iconRect.width - collapsableIconOpen.getIconWidth();
            iconRect.y = 0;
        }
        g.drawImage(icon.getImage(), iconRect.x, iconRect.y, null);
    }
}

From source file:net.sourceforge.msscodefactory.cflib.v1_11.CFLib.Swing.CFInt64ColumnCellRenderer.java

public void paint(Graphics g) {
    if (g == null) {
        return;/*from  w  ww.ja v a2s . co m*/
    }
    Rectangle bounds = getBounds();
    g.setColor(getBackground());
    g.fill3DRect(0, 0, bounds.width, bounds.height, true);
    g.setColor(getForeground());
    String str;
    if (value instanceof Long) {
        Long val = (Long) value;
        Format fmt = getDefaultFormat();
        str = fmt.format(val);
    } else if (value instanceof String) {
        str = (String) value;
    } else {
        str = null;
    }
    if (str != null) {
        int firstNewline = str.indexOf('\n');
        if (firstNewline < 0) {
            firstNewline = str.indexOf('\r');
            if (firstNewline < 0) {
                firstNewline = str.indexOf('\f');
                if (firstNewline < 0) {
                    firstNewline = str.length();
                }
            }
        }
        String firstLine = str.substring(0, firstNewline);
        FontMetrics fm = g.getFontMetrics();
        int ascent = fm.getAscent();
        int leading = fm.getLeading();
        int width = fm.stringWidth(firstLine);
        int x = (bounds.width - 8) - width;
        g.drawString(firstLine, x, leading + ascent + 4);
    }
}

From source file:net.sourceforge.msscodefactory.cflib.v1_11.CFLib.Swing.CFInt16ColumnCellRenderer.java

public void paint(Graphics g) {
    if (g == null) {
        return;//from w w w.ja va2 s.  co m
    }
    Rectangle bounds = getBounds();
    g.setColor(getBackground());
    g.fill3DRect(0, 0, bounds.width, bounds.height, true);
    g.setColor(getForeground());
    String str;
    if (value instanceof Short) {
        Short val = (Short) value;
        Format fmt = getDefaultFormat();
        str = fmt.format(val);
    } else if (value instanceof String) {
        str = (String) value;
    } else {
        str = null;
    }
    if (str != null) {
        int firstNewline = str.indexOf('\n');
        if (firstNewline < 0) {
            firstNewline = str.indexOf('\r');
            if (firstNewline < 0) {
                firstNewline = str.indexOf('\f');
                if (firstNewline < 0) {
                    firstNewline = str.length();
                }
            }
        }
        String firstLine = str.substring(0, firstNewline);
        FontMetrics fm = g.getFontMetrics();
        int ascent = fm.getAscent();
        int leading = fm.getLeading();
        int width = fm.stringWidth(firstLine);
        int x = (bounds.width - 8) - width;
        g.drawString(firstLine, x, leading + ascent + 4);
    }
}