0

I am making a 2d engine using Java based on entities. The physics and sprites are done, but I still need to be able to draw text with the BaseText class. For experimental purposes I am using the following code in the Renderer class (that handles drawing all the sprites and such):

BufferGraphics.drawString(((BaseText) Entity).getText(), (int) -(Origin.getX() * PositionTransform), (int) -Origin.getY());

I would like to, however, be able to either move this code into the setText(final String Text) method of the BaseText entity, i.e. when it is called a new image is created containing the text specified (possibly in different fonts and sizes and such, I haven't decided).

My problem is this: I would like to be able to resize (scale) the text to my liking. It would also be nice to have the text converted to an image as I can get the dimensions of it and set the size of the text entity itself.

Basically, what I need follows something along these lines:

  1. Take desired string and feed it into the setText method.
  2. Take the string and draw it onto an image, sized so that the text will fit into it exactly.
  3. Set this new image to the Image field in the entity so that the engine can draw it.

Is this even possible? There may be a way to do this with the FontMetrics class or whatever it may be called, but I'm not so sure as I have not used it before.

Edit : Let me clarify: I want to create a BufferedImage based on the size of some text set to a specific font and size, not size the text to fit an image.

Edit 2: Thanks to this fellow Andrew, whom so graciously provided code, I was able to add some code to the engine that, by all means, just plain should work. Again, however, not even with that drawRect in there, the image either remains either transparent or somehow is not getting drawn. Let me supply some breadcrumbs: -snip-

The stupid thing is that all the other sprites and images and such draw fine, so I am not sure how it could be the Renderer. By the way, that was the paint() method.

Edit 3:
...
Uh...
...
Oh my.
I am...
...
Text can not explain how hard I belted myself in the face with my left palm.

BaseText.java

@Override
public BufferedImage getImage() {return null;}

Renderer.java

BufferedImage Image = Entity.getImage();

I am
a huge idiot.
Thank you, Andrew, for that code. It worked fine.

Edit 4: By the way, here's the final code that I used:

public void setText(final String Text)
{
    Graphics2D Draw = (Graphics2D) Game.View.getBuffer().getDrawGraphics();
    FontMetrics Metrics = Draw.getFontMetrics();
    Rectangle2D Bounds = Metrics.getStringBounds(Text, Draw);
    BufferedImage NewImage = new BufferedImage((int) Bounds.getWidth(), (int) (Bounds.getHeight() + Metrics.getDescent()), BufferedImage.TYPE_INT_RGB);
    Draw = (Graphics2D) NewImage.getGraphics();
    Draw.setColor(new Color(0xAAFF0000));
    Draw.drawRect(0, 0, NewImage.getWidth(), NewImage.getHeight());
    Draw.drawString(Text, 0, (int) Bounds.getHeight());
    this.Image = NewImage;
    this.Text = Text;
    this.setSize(new Vector(NewImage.getWidth(), NewImage.getHeight()));
}
  • *"The text does not display."* It is probably being written to a point ***above*** the visible area of the image. See my answer for an example. – Andrew Thompson Feb 03 '12 at 03:19

1 Answers1

2
  1. Use FontMetrics, GlyphView or the preferred size a JLabel (handy for getting the size needed to display formatted text.
  2. Adjust the sizes of the font in step 1 until it fits. Call BufferedImage.createGraphics() to get a Graphics2D object. Paint the String to that.
  3. I do not understand point 3, so won't comment.

Here is how it would work with either FontMetrics or a JLabel.

import java.awt.*;
import java.awt.image.*;
import java.awt.geom.Rectangle2D;
import javax.swing.*;

class TextSize {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                // Technique 1 - FontMetrics
                String s = "The quick brown fox jumps over the lazy dog!";
                BufferedImage bi = new BufferedImage(
                    1,
                    1,
                    BufferedImage.TYPE_INT_RGB);
                Graphics g = bi.getGraphics();
                FontMetrics fm = g.getFontMetrics();
                Rectangle2D b = fm.getStringBounds(s,g);
                System.out.println(b);
                bi = new BufferedImage(
                    (int)b.getWidth(),
                    (int)(b.getHeight() + fm.getDescent()),
                    BufferedImage.TYPE_INT_RGB);
                g = bi.getGraphics();
                g.drawString(s,0,(int)b.getHeight());

                JOptionPane.showMessageDialog(
                    null,
                    new JLabel(new ImageIcon(bi)));

                // Technique 3 - JLabel
                JLabel l = new JLabel(s);
                l.setSize(l.getPreferredSize());
                bi = new BufferedImage(
                    l.getWidth(),
                    l.getHeight(),
                    BufferedImage.TYPE_INT_RGB);
                g = bi.getGraphics();
                g.setColor(Color.WHITE);
                g.fillRect(0,0,400,100);
                l.paint(g);

                JOptionPane.showMessageDialog(
                    null,
                    new JLabel(new ImageIcon(bi)));
            }
        });
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • I think what I mean is that: oh dear I hit enter y u so not multiline. Anyway what I mean is that I would like to have the font, size and such beforehand and then create the BufferedImage itself that will fit the text. I guess you could compare the BufferedImage to an ArrayList, in that the image is sized to explicitly hold the text, that is already set to a size... Am I making sense? –  Feb 03 '12 at 01:34
  • Whatever sense you are making seems to have been covered by my answer. – Andrew Thompson Feb 03 '12 at 01:56
  • Edited OP for a possible solution. (I hate being sleep deprived) –  Feb 03 '12 at 02:58
  • Edited OP again because of MORE problems. –  Feb 04 '12 at 01:54
  • Life is too short for trying to decipher code snippets. For better help sooner, post an [SSCCE](http://sscce.org/). And please learn Java nomenclature and use it consistently. – Andrew Thompson Feb 04 '12 at 02:14
  • No idea what nomenclature means. What an odd word. Oh well, I'll check out that SSCCE thing. I've been mucking around with this all day to no avail. –  Feb 04 '12 at 03:59
  • *"No idea what nomenclature means."* Do you have any idea what 'Google is your friend' means? – Andrew Thompson Feb 04 '12 at 04:01
  • Oh, I see what you mean. Yes, that would be a lot simpler than snippets. But still, I basically just directly used your code. If your code works then mine should (I just realised I never even ran your example, I just used the code directly). But it won't be easy to reformat all of my code into one of these SSCCEs, for, as I have said before, it is an entire engine. I'll see what I can do but I probably won't be able to create one. Pretty much every class requires another class which requires another class and so on and so forth. And I already Googled it, thank you. I'm not an idiot. –  Feb 04 '12 at 04:02
  • You probably don't like me naming the local variables class names. It bugs me unless I give something a meaningful name, however. I have some very persistent OCD and things make more sense to me if they are organized, capitalized and spelled correctly, et cetera. –  Feb 04 '12 at 04:05
  • Explicitly I mean that class names should be `EachWordUpperCase`, methods and attributes should be `camelCase`, and constants should be `ALL_UPPER_CASE`. *"I have some very persistent OCD"* I have a pervasive dislike of reading code that does not stick to the conventions. Make a choice. Fix the names or find help from other people. But be warned that most other people expect you to stick to the common Java nomenclature, and also don't accept excuses. Same deal with the SSCCE. – Andrew Thompson Feb 04 '12 at 04:28
  • I am an idiot. Thank you. Not all was for ill gain, however. Your code is much better than mine was. –  Feb 05 '12 at 00:18