Java - Convert several strings to image format - java

I was looking for a way to rearrange several arguments recived as strings and one byte[] image and put them all togther as one image (jpg for example) ready to be printed (immidiatly).
example:
public static void printCard(String name, String LName, Image MainImage)
Basicly this function will be a simple card printer.
I was looking for an idea or some one who can guide me, this could be very easy if some one will guide me a bit.

This is a simple method that I use to add text onto a pre-existing image.
I'm sure you can work out how to pass a blank image in and add the other lines as you see fit.
private BufferedImage drawText2(BufferedImage bi, String outputText) {
Graphics2D g2d = bi.createGraphics();
g2d.setFont(new Font("Helvetica", Font.BOLD, 36));
FontMetrics fm = g2d.getFontMetrics();
int textWidth = fm.stringWidth(outputText);
int imageWidth = bi.getWidth();
int leftAlignment;
int topAlignment;
// Align the text to the middle
leftAlignment = (imageWidth / 2) - (textWidth / 2);
// Align the text to the top
topAlignment = fm.getHeight() - 10;
// Create the drop shadow
g2d.setColor(Color.DARK_GRAY);
g2d.drawString(outputText, leftAlignment + 2, topAlignment + 2);
// Create the text itself
g2d.setColor(Color.LIGHT_GRAY);
g2d.drawString(outputText, leftAlignment, topAlignment);
g2d.dispose();
return bi;
}

If you want to print directly from your application you can use
java.awt.print package.
Try this method
public static void printCard(final String name, final String lName, final Image mainImage){
Printable contentToPrint = new Printable(){
#Override
public int print(Graphics graphics, PageFormat pageFormat, int page) throws PrinterException {
if (page > 0) {
return NO_SUCH_PAGE;
}
pageFormat.setOrientation(PageFormat.PORTRAIT);
graphics.drawImage(mainImage, 0, 0, null);
graphics.drawString(lName, 100, 300);
graphics.drawString(name, 100, 100);
return PAGE_EXISTS;
}
};
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(contentToPrint);
//You can show a print dialog before printing by job by wrapping the following blocks with a conditional statement if(job.printDialog()){...}
try {
job.print();
} catch (PrinterException e) {
System.err.println(e.getMessage());
}
}
You need to import the print related classes from java.awt.print.

i used graphics2d to impliment my function . this method recive 2 images and 6 strings :
Bufferdimage bi is my blank image, on this image i add objects (ex: image, string) :
private static BufferedImage drawText2(BufferedImage logo,BufferedImage small,BufferedImage bi, String Headline,String outputText2,String outputText3,String outputText4,String outputText5,String outputText6) {
Graphics2D g2d = bi.createGraphics();
RenderingHints rh = new RenderingHints(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
g2d.setRenderingHints(rh);
g2d.setFont(new Font("Arial", Font.BOLD, 50));
FontMetrics fm = g2d.getFontMetrics();
int textWidth = fm.stringWidth(Headline);
int imageWidth = bi.getWidth();
int leftAlignment;
int topAlignment;
// Align the text to the top
topAlignment = fm.getHeight() - 10;
// Create the text itself
//headline
leftAlignment = (imageWidth / 2) - (textWidth);
g2d.setColor(Color.blue);
g2d.drawString(Headline, leftAlignment+290, topAlignment+60);
//property changed
g2d.setFont(new Font("Arial", Font.BOLD, 30));
fm = g2d.getFontMetrics();
textWidth = fm.stringWidth(Headline);
//second line
textWidth = fm.stringWidth(outputText2);
leftAlignment = (imageWidth / 2) - (textWidth);
g2d.setColor(Color.black);
g2d.drawString(outputText2, leftAlignment+290, topAlignment+120);
//third line
textWidth = fm.stringWidth(outputText3);
leftAlignment = (imageWidth / 2) - (textWidth);
g2d.setColor(Color.black);
g2d.drawString(outputText3, leftAlignment+290, topAlignment+160);
//4 line
textWidth = fm.stringWidth(outputText4);
leftAlignment = (imageWidth / 2) - (textWidth);
g2d.setColor(Color.black);
g2d.drawString(outputText4, leftAlignment+290, topAlignment+200);
//5 line
textWidth = fm.stringWidth(outputText5);
leftAlignment = (imageWidth / 2) - (textWidth);
g2d.setColor(Color.black);
g2d.drawString(outputText5, leftAlignment+290, topAlignment+240);
//property changed
g2d.setFont(new Font("Arial", Font.getFont("Arial").HANGING_BASELINE, 20));
fm = g2d.getFontMetrics();
//security line
textWidth = fm.stringWidth(outputText6);
leftAlignment = (textWidth);
g2d.setColor(Color.red);
g2d.drawString(outputText6, 10, topAlignment+300);
//logo
g2d.drawImage (logo, 44, 44,180,70, null);
//profile
g2d.drawImage (small, 60, 120,160,190, null);
g2d.dispose();
return bi;
}
bi is the card with all other objects
btw i added smothing to the font, without this the text is very unpleasent.

Related

Making text width flexible with ttf font

I am inquiring about two things. First I am having an ttf file and it is located in my macair drive. I do not want to add that file into my project structure. How can i import the True_type font from it. I have tried various ways to import it my Java program. e.g. public class TextFixer {
private static String[] names = { "iksswgrg.ttf" }; //this exists on my macair drive and i want to create font from it.
private static Map<String, Font> cache = new ConcurrentHashMap<String, Font>(names.length);
static {
for (String name : names) {
cache.put(name, getFont(name));
}
}
public static Font getFont(String name) {
Font font = null;
if (cache != null) {
if ((font = cache.get(name)) != null) {
return font;
}
}
String fName = "/fonts/" + name;
try {
InputStream is = TextFixer.class.getResourceAsStream(fName);
font = new Font("ttf", 0, 16);
//font = Font.createFont(Font.TRUETYPE_FONT, is);
} catch (Exception ex) {
ex.printStackTrace();
System.err.println(fName + " not loaded. Using serif font.");
font = new Font("serif", Font.PLAIN, 24);
}
return font;
}
2nd part is I want to create a String by using Graphics. First I need to have width that is of 130mm. The height of the displayed box will be the tallest character in the provided string. The font size is between 8 and 16. I have an enterprise project which take care of the height and size of the ttf. The problem i face is: I do not want to use swing/javafx libraries. I want to use Graphics library of Java, use Graphics2D to have a rectangle. How can i set its width to be precisely 130mm? Then I want to make that width flexible with according to the Font. I want to draw a string and the string should get adjusted/being flexible in the provided width. I am able to draw a string through g.drawString() but I am unable to see it on console. As I do not want to use Jframe or any Swing/javaFX libraries.
I know this seems a bit long but I hope I have explained it well enough. I desperately need help. Please let me know if you guys can help me out here.
Thanks in advance
First I am having an ttf file and it is located in my macair drive. I do not want to add that file into my project structure. How can i import the True_type font from it
This is more of a problem to do with "How do you reference a file on the file system" then "How do I load a font", because if you can solve the first, you can solve the second.
File fontFile = new File("some/relative/path/to/your/Font.tff");
or
File fontFile = new File("/some/absolute/path/to/your/Font.tff");
Personally, I like neither, as it it causes too much trouble (working directories, other systems, etc), I prefer to use embedded resources where possible or put the files in a common location.
For example {user.home}/AppData/Local/{application name} on Windows or on Mac you could use {user.home}/Library/Application Support/{application name}, then it doesn't matter where the program is executed from
Loading the font is relatively simple. For my example, I placed the font file in the working directory of the program
System.out.println(new File("Pacifico.ttf").exists());
Font font = Font.createFont(Font.TRUETYPE_FONT, new File("Pacifico.ttf"));
2nd part is I want to create a String by using Graphics. First I need to have width that is of 130mm. The height of the displayed box will be the tallest character in the provided string
This is much more complicated, as images are measured in pixels. In order to know how many pixels make up a given distance, we need to know the DPI of the image.
its 72DPI
Okay then, from that, we can calculate the number of pixels we need
public static double cmToPixel(double cm, double dpi) {
return (dpi / 2.54) * cm;
}
130mm (13 cm) comes out to be 368.503937007874 # 72dpi.
From this, we need to find the font point size for a given piece of text to fit within this range.
Now, there are a number of was you can do this, you could simply start at point 1 and perform a linear progression till you pass the range you're after. It's not exactly fast and, as you increase the size, it can become a little error prone.
I've opted for more of a divide and conquer approach
protected static int widthOfText(String text, Font font, float fontSize, Graphics2D g2d) {
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int textWidth = fm.stringWidth(text);
return textWidth;
}
public static Float pointToFit(double width, String text, Font font, Graphics2D g2d, float min, float max) {
float fontSize = min + ((max - min) / 2f);
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int textWidth = fm.stringWidth(text);
if (fontSize == min || fontSize == max) {
return fontSize;
}
if (textWidth < width) {
return pointToFit(width, text, font, g2d, fontSize, max);
} else if (textWidth > width) {
return pointToFit(width, text, font, g2d, min, fontSize);
}
return fontSize;
}
Important to note, it's not perfect, but it betters a linear progression :P
With this in hand, we can start calculating the required properties we need...
String text = "Happy, Happy, Joy, Joy";
double width = cmToPixel(13.0, 72.0);
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
float fontSize = pointToFit(width, text, font, g2d, 0, (float)width);
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int height = fm.getHeight();
g2d.dispose();
Okay, so this creates a small (1x1) temporary image. We need Graphics context in order to calculate all the other properties. It then calculates the font point size, from it can then calculate the text height
With all that information in hand, we can get around to actually rendering the text...
img = new BufferedImage((int) Math.round(width), height, BufferedImage.TYPE_INT_ARGB);
g2d = img.createGraphics();
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
Which will eventually output something like this...
I added the red border before I rendered the text so I could see how well it fitted.
Now, this is a really basic example, what this doesn't do is tell you when the text won't fit (ie, the point size is 1 or 0), you'll have to put traps in to catch that yourself
And, because I know you'll probably have lots of fun putting it together, my test code...
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
public class Test {
public static void main(String[] args) {
try {
System.out.println(new File("Pacifico.ttf").exists());
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Font font = Font.createFont(Font.TRUETYPE_FONT, new File("Pacifico.ttf"));
String text = "Happy, Happy, Joy, Joy";
double width = cmToPixel(13.0, 72.0);
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
float fontSize = pointToFit(width, text, font, g2d, 0, (float) width);
System.out.println(width);
System.out.println(fontSize);
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int height = fm.getHeight();
g2d.dispose();
img = new BufferedImage((int) Math.round(width), height, BufferedImage.TYPE_INT_ARGB);
g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, img.getWidth() - 1, img.getHeight() - 1);
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
JOptionPane.showConfirmDialog(null, new ImageIcon(img));
} catch (IOException | FontFormatException e) {
//Handle exception
}
}
public static Float pointToFit(double width, String text, Font font, Graphics2D g2d) {
return pointToFit(width, text, font, g2d, 0f, Float.MAX_VALUE);
}
protected static int widthOfText(String text, Font font, float fontSize, Graphics2D g2d) {
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int textWidth = fm.stringWidth(text);
return textWidth;
}
public static Float pointToFit(double width, String text, Font font, Graphics2D g2d, float min, float max) {
float fontSize = min + ((max - min) / 2f);
NumberFormat nf = NumberFormat.getInstance();
font = font.deriveFont(fontSize);
FontMetrics fm = g2d.getFontMetrics(font);
int textWidth = fm.stringWidth(text);
if (fontSize == min || fontSize == max) {
return fontSize;
}
if (textWidth < width) {
return pointToFit(width, text, font, g2d, fontSize, max);
} else if (textWidth > width) {
return pointToFit(width, text, font, g2d, min, fontSize);
}
return fontSize;
}
public static double cmToPixel(double cm, double dpi) {
return (dpi / 2.54) * cm;
}
}

Java Image over image has white b/g even though it's a png

As seen below, I have a BufferedImage over another BufferedImage. They are both pngs and I would like there to be no background on the overlayed image. I'm sure there's so way to do this, but am unsure of where in the api.
Here's the method in question:
private static BufferedImage finalizeImage(BufferedImage originalImage, String tokenImage, Integer occurrences, int height, int width, int type){
//Font font = new Font("Courier New", Font.PLAIN, 12);
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g = resizedImage.createGraphics();
FontMetrics fm = g.getFontMetrics();
int strWidth = (fm.stringWidth(tokenImage));
int imageWidth = resizedImage.getWidth();
int textBegin = (imageWidth - strWidth) / 2;
//g.setFont(font);
g.drawImage(originalImage, 0, 0, width, height, null);
g.setColor(Color.black);
int textHeight = (fm.getAscent() + (TOKEN_HEIGHT - (fm.getAscent() + fm.getDescent())) / 2);
g.drawString(tokenImage, textBegin, textHeight);
//for multiple occurrences
try {
BufferedImage numOnSubscript = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/subscript.fw.png"));
g.drawImage(numOnSubscript, width - 20, height-20, 20, 20, null);
g.setColor(Color.white);
g.drawString(occurrences.toString(), width - 16, (height-20)*2 - 1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
g.dispose();
return resizedImage;
}
Here is what is happening.
I found my problem. Of course, it's the silliest thing. I had a white background on as default in fireworks :-/

printing bufferedimage to a printer

i have an application from which i want to print an image. The image is loaded as a BufferedImage object. The problem is, when i print the image (to the postscript or to the pdf file), the quality is really poor.
When i'm using some other tools (basically any picture viewer application which can print the image) the result is significantly better.
I know there can be some problems with the DPI vs resolution but i'm not exactly sure how to compute the correct values for printing.
I tried to google and tried some methods, but nothing seems to work as i expected.
Basicaly i just want to print an image (in resolution let's say 3000x2000) to a printer (with DPI for example 600x600).
This is how i create the print job:
PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
printAttributes.add(PrintQuality.HIGH);
printAttributes.add(new PrinterResolution(600, 600 PrinterResolution.DPI));
printAttributes.add(new Destination(URI.create("file:/tmp/test.ps")));
PageFormat pf = printerJob.defaultPage();
Paper paper = pf.getPaper();
double xMargin = 0.0;
double yMargin = 0.0;
paper.setImageableArea(xMargin, yMargin, paper.getWidth() - 2 * xMargin, paper.getHeight() - 2 * yMargin);
pf.setPaper(paper);
// create new Printable for the specified image
printerJob.setPrintable(PrintableImage.get(image), pf)
if (printerJob.printDialog(printAttributes)) {
printerJob.print(printAttributes);
}
Where image is BufferedImage and PrintableImage.get returns new instance which implements Printable
Then the actual print is doing this way (i let the commented code which i tried but didn't work for me)
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (image == null)
throw new PrinterException("no image specified to be printed");
// We have only one page, and 'page' is zero-based
if (pageIndex > 0) {
return NO_SUCH_PAGE;
}
// tranlate the coordinates (according to the orientations, margins, etc)
Graphics2D printerGraphics = (Graphics2D) graphics;
//g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
//g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
printerGraphics.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
// THIS IS A TEST - javax.printing api uses 72 DPI, but we have 600DPI set for the printer
//AffineTransform at = printerGraphics.getTransform();
//printerGraphics.scale((double)72 / (double)600, (double)72 / (double)600);
//printerGraphics.drawRenderedImage(image, null);
//printerGraphics.setTransform(at);
//if(printerGraphics != null)
//return PAGE_EXISTS;
double scale = 72.0 / 600.0;
Dimension pictureSize = new Dimension((int)Math.round(image.getWidth() / scale), (int) Math.round(image.getHeight() / scale));
// center the image horizontaly and verticaly on the page
int xMargin = (int) ((pageFormat.getImageableWidth() - image.getWidth()) / 2);
int yMargin = (int) ((pageFormat.getImageableHeight() - image.getHeight()) / 2);
xMargin = yMargin = 0;
System.out.println(String.format("page size [%.2f x %.2f], picture size [%.2f x %.2f], margins [%d x %d]", pageFormat.getImageableWidth(), pageFormat.getImageableHeight(), pictureSize.getWidth(), pictureSize.getHeight(), xMargin, yMargin));
printerGraphics.drawImage(image, xMargin, yMargin, (int)pageFormat.getWidth(), (int)pageFormat.getHeight(), null);
//printerGraphics.drawImage(image, 0, 0, null);
//printerGraphics.drawImage(image, xMargin, yMargin, pictureSize.width, pictureSize.height, null);
//printerGraphics.drawImage(image, xMargin, yMargin, (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableHeight(), 0, 0, pictureSize.width, pictureSize.height, null);
//printerGraphics.drawImage(image, 0, 0, (int) pageFormat.getWidth() - xMargin, (int) pageFormat.getHeight() - yMargin, 0, 0, pictureSize.width, pictureSize.height, null);
return PAGE_EXISTS;
}
Does anybody solves the same problem?
Any help would be appreciated.
Thanks
Matej
This is how I did it. It works smoothly. Note that this code snippet doesn't center the image.
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex > 0) {
return (NO_SUCH_PAGE);
} else {
double pageHeight = pageFormat.getImageableHeight(), pageWidth = pageFormat.getImageableWidth();
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
if (pageHeight < image.getHeight() || pageWidth < image.getWidth()) {
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(image, 0, 0, (int) pageWidth, (int) pageHeight - textSize, null);
} else {
g2d.drawImage(image, 0, 0, null);
}
g2d.dispose();
return (PAGE_EXISTS);
}
}
#Viktor Fonic
Thank you for this, I was searching a lot to do this!
You're solution works perfectly, but has a small error,
textSize was not declared, so:
int textSize = (int) (pageHeight - image.getHeight()*pageWidth/image.getWidth());

Java Write Text Image with Specific Fonts

I'm writing some text on top of an existing image and the font isn't very sharp. Is there some settings either with the Graphics2D or Font classes that help make fonts look nicer when writing text on top of images? The Dante font doesn't come out as Dante when I write it. I've tried to use antialiasing but it had no effect (see setRenderingHint). The images came out the same with or without the RenderingHint set. Any suggestions?
public class ImageCreator{
public void createImage(String text){
Graphics2D g = img.createGraphics(); //img is a BufferedImage read in from file system
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Font fnt=new Font("Dante",1,20);
Color fntC = new Color(4, 4, 109);
g.setColor(fntC);
g.setFont(fnt);
Dimension d = new Dimension(200, 113);
drawCenteredString(text, d.width, d.height, g);
}
public static void drawCenteredString(String s, int w, int h, Graphics g) {
FontMetrics fm = g.getFontMetrics();
int x = (w - fm.stringWidth(s)) / 2;
int y = (fm.getAscent() + (h - (fm.getAscent() + fm.getDescent())) / 2);
g.drawString(s, x, y);
}
}
Use TextLayout, as shown here.
Addendum: The advantage of TextLayout is that RenderingHints may be applied to the FontRenderContext.

Java (AWT): fitting text in a box

I have an application that extends a Frame. Then, it'll display a few lines of text using:
Font f = new Font("Arial", Font.PLAIN, 10);
g.setFont(f);
g.drawString("Test|great Yes ^.", x, y + 10);
Now what happens is that the text doesn't fit in the box around. E.g. I'm expecting the text to fit in [x,y]-[x+width, y+10] (don't care about the width) but it falls somewhat below the y+10 line. Now for most characters ('T', 'e', etc.) this fits but '|' and 'g' don't! They go below the y+10-line. It seems you can't use: draw at y + characterHeight. But what does work?
To see what I mean, here's some sample code:
import java.awt.*;
public class test extends Frame
{
public test()
{
/* retrieve max window size */
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
GraphicsConfiguration [] gc = gs[0].getConfigurations();
Rectangle r = gc[0].getBounds();
setSize(r.width, r.height);
setVisible(true);
}
public void paint(Graphics g)
{
final int windowWidth = getSize().width;
final int windowHeight = getSize().height;
g.setColor(Color.BLUE);
g.fillRect(0, 0, windowWidth, windowHeight);
g.setColor(Color.WHITE);
g.fillRect(0, 100, windowWidth, 110);
int textHeight = 100;
Font f = new Font("Arial", Font.PLAIN, textHeight);
g.setFont(f);
g.setColor(Color.BLACK);
g.drawString("Test|great Yes ^.", 10, 100 + textHeight);
}
public void guiLoop()
{
for(;;) { try { Thread.sleep(1000); } catch(Exception e) { } }
}
public static void main(String [] args)
{
new test().guiLoop();
}
}
I tried the following code as well:
public void paint(Graphics g)
{
final int windowWidth = getSize().width;
final int windowHeight = getSize().height;
g.setColor(Color.BLUE);
g.fillRect(0, 0, windowWidth, windowHeight);
g.setColor(Color.WHITE);
g.fillRect(0, 100, windowWidth, 110);
int textHeight = 100;
String str = "Test|great Yes ^.";
Font f = new Font("Arial", Font.PLAIN, textHeight);
Rectangle2D boundingRectangle = f.getStringBounds(str, 0, str.length(), new FontRenderContext(null, false, false));
f = f.deriveFont((float)(textHeight * (textHeight / boundingRectangle.getHeight())));
boundingRectangle = f.getStringBounds(str, 0, str.length(), new FontRenderContext(null, false, false));
g.drawString(str, 10, 100 + (int)boundingRectangle.getHeight());
g.setFont(f);
g.setColor(Color.BLACK);
g.drawString(str, 10, 100 + textHeight);
}
This is somewhat better: the text is smaller so it might fit, but there's still the problem that the y-position is incorrect.
All help is appreciated!
What about using FontMetrics? You can obtain it from Graphics object with g.getFontMetrics().
Than you can retrieve max descent or ascent or directly height (using getHeight), so your implementation will be font-indipendent and it should work fine.. check documentation here!
EDIT (to explain comments):
there is no a direct way to tell to a string to draw itself in a manner that can fit a box. You have to do it by yourself.. like start from a max font size and check if width fits the box, otherwise decrement size and try again. For height you should FIRST decide (or obtain) max font height, then you can set how many pixel should the box be.
I think I solved it somewhat:
boundingBoxHeight: height of box in which the text should fit
yOffset where to start drawing the font
Font f = new Font("Arial", Font.PLAIN, boundingBoxHeight);
g.setFont(f);
FontMetrics fm = g.getFontMetrics();
double shrink = ((double)textHeight / (double)fm.getHeight());
double newSize = (double)textHeight * shrink;
double newAsc = (double)fm.getAscent() * shrink;
int yOffset = (int)newAsc - fm.getLeading();
f = f.deriveFont((float)newSize);
g.setFont(f);
g.drawString(str, 10, 100 + yOffset);
There's quite a bit of whitespace above the text though.

Categories