Graphics2d draw text with partial bold text - java

I was wondering if I can make a partial bold text for example:
Please make your assignment before 21 of july
I have not tried anything yet, because i just have no clue how to do this.
Here is my code currently for rendering text:
public void renderText(int page, String text, String font, int fontSize, Color color, int width, int height) {
final Graphics2D g;
if (page == 1) {
g = (Graphics2D) outsideFlyer.getGraphics();
g.drawImage(outsideFlyer, 0, 0, null);
} else {
g = (Graphics2D) insideFlyer.getGraphics();
g.drawImage(insideFlyer, 0, 0, null);
}
if (font == null) {
g.setFont(new Font(font, Font.PLAIN, fontSize));
} else if ("bold".equals(font)) {
g.setFont(new Font(null, Font.BOLD, fontSize));
} else {
g.setFont(new Font(font, Font.PLAIN, fontSize));
}
g.setColor(color);
for (String txt : text.split("\n")) {
g.drawString(txt, width, height += g.getFontMetrics().getHeight());
}
g.dispose();
}
Is it possible to split the text in some way?
I would love to have something like what happens on a lot of websites like everything inbetween * gets bold or in some way.

Related

How to hide JToolTip background when exceeding borders?

I've created this custom JToolTip for my application. When the tooltip is entirely diplayed inside a JFrame, no background is visible (expected), but when the tooltip is displayed outside the JFrame, the background will be visible. How can I have it removed either way?
I've tried setBackground(new Color(255, 255, 255, 0)); with the '0' alpha value to make sure the background is transparent, but that didn't do the trick.
The tooltip inside the frame, as expected:
The tooltip exceeding the JFrame, with the unwanted background:
The custom JTooltip:
public class DefaultToolTip extends JToolTip {
public DefaultToolTip() {
setOpaque(false);
setPreferredSize(new Dimension(275, 30));
setBackground(new Color(255, 255, 255, 0));
}
#Override
public void addNotify() {
super.addNotify();
setOpaque(false);
Component parent = this.getParent();
if (parent != null) {
if (parent instanceof JComponent) {
JComponent jparent = (JComponent) parent;
jparent.setOpaque(false);
}
}
}
#Override
public void paint(Graphics g) {
String text = getComponent().getToolTipText();
addNotify();
Graphics2D g2d = drawComponent(g);
drawText(text, g2d);
g2d.dispose();
}
private void drawText(String text, Graphics2D g2d) {
//Draw the text
int cHeight = getComponent().getHeight();
FontMetrics fm = g2d.getFontMetrics();
g2d.setColor(Color.WHITE);
if (cHeight > getHeight())
g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (getHeight() + fm.getAscent()) / 2 + 2);
else
g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (cHeight + fm.getAscent()) / 2 + 2);
}
private Graphics2D drawComponent(Graphics g) {
//Create a round rectangle
Shape round = new RoundRectangle2D.Float(0, 8, getWidth(), getHeight(), 8, 8);
//Draw the background
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.GRAY);
g2d.fill(round);
//Draw the left triangle
Point p1 = new Point(getWidth() / 2, getHeight() - 30);
Point p2 = new Point(getWidth() / 2 + 8, getHeight() - 20);
Point p3 = new Point(getWidth() / 2 - 8, getHeight() - 20);
int[] xs = {p1.x, p2.x, p3.x};
int[] ys = {p1.y, p2.y, p3.y};
Polygon triangle = new Polygon(xs, ys, xs.length);
g2d.fillPolygon(triangle);
return g2d;
}
}
Solution
A few things have changed to have the tooltip behave as expected. the paint method has been replaced by the paintComponent method, the addNotify call was removed, the method updated to fetch the window of the component and to give it a transparent background. setBorder(BorderFactory.createEmptyBorder()); was also needed to remove the components default border.
public class DefaultToolTip extends JToolTip {
public DefaultToolTip() {
setOpaque(false);
setPreferredSize(new Dimension(275, 30));
setBackground(new Color(255, 255, 255, 0));
setBorder(BorderFactory.createEmptyBorder());
}
#Override
public void addNotify() {
super.addNotify();
setOpaque(false);
Component parent = this.getParent();
if (parent != null) {
if (parent instanceof JComponent) {
JComponent jparent = (JComponent) parent;
jparent.setOpaque(false);
}
}
Window window = SwingUtilities.windowForComponent(this);
try {
window.setBackground(new Color(255, 255, 255, 0));
} catch (IllegalComponentStateException e) {
//Do nothing
}
}
#Override
public void paintComponent(Graphics g) {
//super.paintComponent(g);
String text = getComponent().getToolTipText();
Graphics2D g2d = drawComponent(g);
drawText(text, g2d);
g2d.dispose();
}
private void drawText(String text, Graphics2D g2d) {
//Draw the text
int cHeight = getComponent().getHeight();
FontMetrics fm = g2d.getFontMetrics();
g2d.setColor(Color.WHITE);
if (cHeight > getHeight())
g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (getHeight() + fm.getAscent()) / 2 + 2);
else
g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (cHeight + fm.getAscent()) / 2 + 2);
}
private Graphics2D drawComponent(Graphics g) {
//Create a round rectangle
Shape round = new RoundRectangle2D.Float(0, 8, getWidth(), getHeight(), 8, 8);
//Draw the background
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.GRAY);
g2d.fill(round);
//Draw the left triangle
Point p1 = new Point(getWidth() / 2, getHeight() - 30);
Point p2 = new Point(getWidth() / 2 + 8, getHeight() - 20);
Point p3 = new Point(getWidth() / 2 - 8, getHeight() - 20);
int[] xs = {p1.x, p2.x, p3.x};
int[] ys = {p1.y, p2.y, p3.y};
Polygon triangle = new Polygon(xs, ys, xs.length);
g2d.fillPolygon(triangle);
return g2d;
}
}
A note however, super.paintComponent(g) was commented out, since it would draw text another time.
Don't know if any of these will help but:
Don't override paint(...). Custom painting is done by overriding paintComponent(...).
Invoke super.paintComponent(...) as the first statement
Don't invoke addNotify() in a painting method. A painting method is for painting only.
with the '0' alpha value to make sure the background is transparent,
Swing components don't know how to handle transparent backgrounds. Just make the component non-opaque.
When the tooltip overlaps the component. The tooltip is actually added to a JWindow before it is displayed. So in your addNotify() logic, you can search for the window and make it transparent.
Check out:
Window window = SwingUtilities.windowForComponent(...);

Get list of english fonts only

I'm trying to get a list of all english fonts and print some strings with them.
This is the code I use to create the images of the strings:
public static BufferedImage imageForString (String str, Font font) {
font = new Font(font.getName(), font.getStyle(), 400); //Can't trust people to size their own font -_-
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
int width = fm.stringWidth(str);
int height = fm.getHeight();
g2d.dispose();
try {
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
} catch (Exception e) {
System.err.println("Problem printing: " + str + " " + "with font: " + font);
e.printStackTrace();
}
g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(str, 0, fm.getAscent());
g2d.dispose();
return img;
}
I'm trying to print every letter of the alphabet separately in every font the system has that is capable of displaying english text. That's obviously not working because I keep getting exceptions thrown on the line I put the try/catch block around.
I'm using this to get a list of all fonts the system has (apparently it includes other languages?):
public static final Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
Here's the exception being thrown:
Problem printing: ' with font: java.awt.Font[family=Al Bayan,name=AlBayan,style=plain,size=400]
java.lang.IllegalArgumentException: Width (0) and height (601) cannot be <= 0
at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:999)
at java.awt.image.BufferedImage.<init>(BufferedImage.java:326)
at HashMaker.imageForString(HashMaker.java:48)
at HashMaker.getImgs(HashMaker.java:69)
at HashMaker.main(HashMaker.java:83)
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!
at sun.awt.image.IntegerInterleavedRaster.getDataElements(IntegerInterleavedRaster.java:201)
at java.awt.image.BufferedImage.getRGB(BufferedImage.java:911)
at ImageUtils.colIsWhite(ImageUtils.java:23)
at ImageUtils.parseImage(ImageUtils.java:40)
at Letter.<init>(Letter.java:24)
at HashMaker.main(HashMaker.java:85)`
It's not just the single quote, the exception is also thrown on latin characters such as a 'J'

Java: Adjust outline thickness

I use this code: to outline a font:
public class MyText extends JPanel {
String text1 = null;
public MyText (String text) {
text1 = text;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.white);
int w = getSize().width;
int h = getSize().height;
Graphics2D g2d = (Graphics2D) g;
FontRenderContext fontRendContext = g2d.getFontRenderContext();
Font font = new Font("Verdana", 1, 72);
String st = new String(text1);
TextLayout text = new TextLayout(st, font, fontRendContext);
Shape shape = text.getOutline(null);
Rectangle rect = shape.getBounds();
AffineTransform affineTransform = new AffineTransform();
affineTransform = g2d.getTransform();
affineTransform.translate(w / 2 - (rect.width / 2), h / 2
+ (rect.height / 2));
g2d.transform(affineTransform);
g2d.setColor(Color.black);
g2d.draw(shape);
g2d.setClip(shape);
}
The problem is I have no idea how to adjust the thickness of the outline.
I tried displaying another bigger string over the first string, but the result is quite bad (wrong pixels...).
Hav you got any ideas?
Thanks in advance.
You can use setStroke. For example
g2d.setStroke(new BasicStroke(4));
Start by taking a look at Stroking and Filling Grapcs Primitives and Fun with Java2D - Strokes

How do I turn off text antialiasing in this Java function?

Basically I would like to turn off antialias in the following:
public BufferedImage createText(String text) {
//create image
BufferedImage image = new BufferedImage(95, 20,
BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = (Graphics2D) image.getGraphics();
//set background
graphics.setColor(Color.white);
graphics.fillRect(0, 0, 95, 20);
//draw text
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
graphics.setColor(Color.black);
graphics.setFont(new Font("volter", Font.PLAIN, 9));
graphics.drawString(text, 0, 10);
return image;
}
but it's not working, here is something this function generates:
I just want black and white to be used, nothing else so it's important I get antialias disabled!
Try this instead:
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);

how can I get Font X offset width in java2D?

I need print two words: "A" and "B" using java 2D
font size = 100;
"A" font family: Bodoni MT Poster Compressed
"B" font family: Arial
I writed below codes to do it:
BufferedImage image = new BufferedImage(400, 300, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
{//fill bg color
g.setColor(new Color(255,255,255));
g.fillRect(0, 0, image.getWidth(), image.getHeight());
}
int FONT_SIZE=100;//set font size
{//print A
g.setColor(new Color(0,0,0));
g.setFont(new Font("Bodoni MT Poster Compressed", Font.PLAIN ,FONT_SIZE));
g.drawString("A",0,FONT_SIZE);
}
{//print B
g.setColor(new Color(0,0,0));
g.setFont(new Font("Arial", Font.PLAIN ,FONT_SIZE));
g.drawString("B",FONT_SIZE,FONT_SIZE);
}
g.dispose();
I get the result image:
but I need like this (make by PhotoShop):
I think the question at g.drawString("B",FONT_SIZE,FONT_SIZE);
How can I get the font X offset width?
thanks for help :)
After you do the setFont, declare a variable like
FontMetrics fm = g.getFontMetrics();
int strA = fm.stringWidth("A"),
strB = fm.stringWidth("B"),
strH = fm.getHeight();
Now that you have all the dimensions of the letters, set their positions (px is distance from the left edge to the letter, py from the top to the baseline of the font)
int px = ..., py = ...
g.drawString ("A", px, py);
And similarly for "B". Hope that helps, - M.S.

Categories

Resources