Question

I have the below program to print a sentence string by string in java awt :

package awt;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.swing.JFrame;
import javax.swing.JPanel;

import com.lowagie.text.pdf.DefaultFontMapper;

public class ItalicTest extends JPanel{
    private static final int FONT_SIZE = 9;
    protected static Graphics2D bgWorkGraphics = null;
    protected static Graphics2D fgWorkGraphics = null;
    private static DefaultFontMapper fontMapper = new DefaultFontMapper();


    static float width = 0;
    static int height = 0;
    static String arial_family = "Arial";
    static String arial_italic_filePath = "C:\\WINDOWS\\Fonts\\Ariali.ttf";

    static String familyToUse = arial_family;
    static String filepathToUse = arial_italic_filePath;

    public static final double AT_SCALE_X = 1.34;
    public static final double AT_SCALE_Y = 1.34;

    public static List<Image> outputList;

    public static Graphics2D currentGraphics = null;

    static List<String> myContentWords = new ArrayList<String>();
    static {
        myContentWords.add("and");
        myContentWords.add(" ");
        myContentWords.add("additional");
        myContentWords.add(" ");
        myContentWords.add("description");
        myContentWords.add(" ");
        myContentWords.add("text");
        myContentWords.add(" ");
        myContentWords.add("#");
        myContentWords.add(" ");
        myContentWords.add("4");
    }
   public void paint(Graphics g) {

      Graphics2D g2 = (Graphics2D)g;

      fontMapper.insertDirectory("C:\\Windows\\Fonts");

      Font font = new Font(familyToUse, java.awt.Font.ITALIC, FONT_SIZE);

      FontRenderContext frc = g2.getFontRenderContext();

      g2.setFont(font);

      TextLayout textLayout = null;
      float width1 = 0.0f;
      float x = 0.0f;
        float y = 8.2946780f;
        float previousWidth = 0.0f;
        for(int i=0; i<myContentWords.size(); i++) {
             textLayout = new TextLayout(myContentWords.get(i), font, frc);

             previousWidth = width1;

             x=x+previousWidth;
             width1 = textLayout.getAdvance();
            if(myContentWords.get(i).equals(" ")) {
                System.out.println("Width of space calculated is "+width1);
            }
            g2.drawString(myContentWords.get(i), x, y);
        }
   }

   public static void main(String[] args) {
      JFrame f = new JFrame();
      f.getContentPane().add(new ItalicTest());
      f.setSize(300, 200);
      f.setVisible(true);
   }

}

This gives me wrong width for the space between words. So, the spacing appears too wide. This happens only for italic fonts.

I need to know if there is any other way to retrieve correct width of space?

I do not want to use drawString("and additional description text to # 4", x, y) as the complete thing. I need to draw it word by word.

The Solution to get string width by using font metrics gives correct results, however, I need to get the correct value from TextLayout, since the algorithm written in the bigger application uses TextLayout to calculate height, width etc. This algorithm works perfectly, when we use any fonts other than oblique fonts. For Oblique fonts, it gives additional width for any input string. I need to know, if there is anything special in oblique fonts, if yes, whats the correct way to retrieve width in case of oblique fonts?

No correct solution

OTHER TIPS

Try and use FontMetrics. You can learn more here

private final Font font = new Font("impact", Font.ITALIC, 20);
....
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setFont(font);
    FontMetrics fm = g.getFontMetrics();
    int height = fm.getAscent();
    int y = getHeight()/2 + height/2;
    int x = 0;
    for (String s : list) {
        g.drawString(s, x, y);
        x += fm.stringWidth(s);
    }
}

enter image description here

import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Italic extends JPanel{
    private final List<String> list;
    private final Font font = new Font("impact", Font.ITALIC, 20);

    public Italic() {
       list = createList();
    }

    private List<String> createList() {
        List<String> myContentWords = new ArrayList<>();
        myContentWords.add("and");
        myContentWords.add(" ");
        myContentWords.add("additional");
        myContentWords.add(" ");
        myContentWords.add("description");
        myContentWords.add(" ");
        myContentWords.add("text");
        myContentWords.add(" ");
        myContentWords.add("#");
        myContentWords.add(" ");
        myContentWords.add("4");
        return myContentWords;
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setFont(font);
        FontMetrics fm = g.getFontMetrics();
        int height = fm.getAscent();
        int y = getHeight()/2 + height/2;
        int x = 0;
        for (String s : list) {
            g.drawString(s, x, y);
            x += fm.stringWidth(s);
        }
    }

    @Override 
    public Dimension getPreferredSize() {
        return new Dimension(300, 100);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                JOptionPane.showMessageDialog(null, new Italic());
            }
        });
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top