Clip an image to be rendered with a text in Swing



Main.java:

import java.awt.image.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.font.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private BufferedImage image; 
   private boolean clip = false;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      image = toBufferedImage(new javax.swing.ImageIcon("djkrush.jpg").getImage());
      JButton button = new JButton("Clip to Text");
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            clip = true;
            repaint();
         }
      });
 
      getContentPane().setLayout(new BorderLayout());
      getContentPane().add(BorderLayout.SOUTH, button);
   }
 
   public void paint(Graphics g) {
      super.paint(g);
 
      Graphics2D g2d = (Graphics2D) g;
 
      if (clip) {
         int w = getSize().width;
         int h = getSize().height;
 
         FontRenderContext frc = g2d.getFontRenderContext();
         Font font = new Font("Helvetica", Font.PLAIN, 12);
         TextLayout tl = new TextLayout("ALICIA", font, frc);
 
         double stringWidth = tl.getBounds().getWidth();
         double stringHeight = tl.getBounds().getHeight();
 
         // determine to what extend the string should be 
         // scaled in order to fill the window
         double scalex = (w - 50) / stringWidth;
         double scaley = (h - 50) / stringHeight;
         AffineTransform ta = AffineTransform.getScaleInstance(scalex, scaley);
 
         // transform the string in a shape
         Shape shape = tl.getOutline(ta);
 
         // position the shape
         double shapeWidth  = shape.getBounds().getWidth();
         double shapeHeight = shape.getBounds().getHeight();
         AffineTransform at = AffineTransform.getTranslateInstance(
                                                w / 2 - shapeWidth / 2, 
                                                h / 2 + shapeHeight / 2);
         shape = at.createTransformedShape(shape);
 
         g2d.clip(shape);
      }
 
      g2d.setColor(Color.red);
      g2d.fillRect(20, 50, 100, 140);
 
      Rectangle2D tr = new Rectangle2D.Double(0, 0, image.getWidth(), image.getHeight());
      TexturePaint tp = new TexturePaint(image, tr);
      g2d.setPaint(tp);
      g2d.fillRect(120, 50, 100, 140);
       
      g2d.setColor(Color.blue);
      g2d.fillRect(220, 50, 100, 140);
 
      g2d.setColor(Color.yellow);
      g2d.fillOval(320, 50, 100, 140);
   }
 
   public BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(440, 240);
      main.setVisible(true);
   }
}

Image used: