Java- textwrap with drawString() - java

The normal syntax for java.awt.Graphics.drawString() includes defining the X and Y coordinates for the string. I want to draw a string that has a width and height attribute for text wrapping. Is there a way to specify a java.awt.Rectangle for the string you are trying to draw? Would I have to write something to decide where the word wrap should cut it off or is their an easier way?
Thanks!

This is actually a little bit complicated and somewhat convoluated, but essentially, you need to make use of the LineBreakMeasurer class to help you break the text down into manageable chunks based on the available width
See Drawing Multiple Lines of Text for more details and an example

I don't think there's a built in way to do that, but you can implement your own wrapping if you get the width of the string with something like below:
FontMetrics fontMetrics = new FontMetrics(Graphics.getFont());
int width = fontMetrics.stringWidth("Potentially needs wrapping");
Then split the message into multiple strings as necessary.

Related

How to render text on right side of screen in Java

I'm currently making a Minecraft mod, and I need to render text so that it aligns with the right side of the screen. I know the way to do this in CSS is by setting the right property to 0, or however many pixels you need the text off the right side of the screen.
However, I can't seem to find anything relating to this in Java. Minecraft comes with some default functions you can use to render text. I am using mc.fontRendererObj.drawString(<text>, <x>, <y>, <color>) to draw text. You can also use the variable GlStateManager to modify the text using it's variables and functions.
I'm fairly certain that with these I can achieve what I'm trying to do, but I can't find a way to do it. Does anyone know how I can do this?
Using the drawString method, you need to calculate <x> and <y> such that the end of the text aligns with the right side of the area in which you are drawing the text. So you need to obtain the width of that area as well as the width of the text you are writing. Then you can calculate <x>. Of-course the <y> does not affect right-alignment. In pure java there are methods for obtaining the width and for the length of the text, both in pixels.

Android Text with Spannable image on top/bottom of text

I am developing a simple devotional app, which has a Kannada (a language in India) sentence to be displayed. I am successful in using typeface and displaying the content.
In few places I have word which has a line on top/bottom of the word as shown below. I tried with a spannable image but I am still not able to achieve it properly.
This is a sample of the code which I am referring to. Here I am using a small icon to display it in between the string.
Spannable span1 = new SpannableString("The imageplace");
Drawable android = TestImageActivity.this.getResources().getDrawable(R.drawable.end);
android.setBounds(5, 0, 20, 5);
ImageSpan image = new ImageSpan(android, ImageSpan.ALIGN_BASELINE);
span1.setSpan(image, 3, 4, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
tvTextImage3.setText(span1);
ImageSpan extends ReplacementSpan so any characters you are spanning won't get rendered, as the TextLayout is expecting that the span itself will be doing all the rendering.
What I would recommend is implementing your own ReplacementSpan subclass. Since it looks like your graphics are associated with one character, you would wrap the single character.
In the getSize override, you would use start and end to index into text and get the character(s) you are spanning, then use paint.getTextBounds() to measure the width of the text and return that value. You want the width calculation to work in a way that the width of the span doesn't affect the default spacing of the text.
Another thing this method might need to do is change the FontMetrics by increasing the ascent and descent in order to give you some space to draw the lines.
In the draw override, you use the paint to render the text that isn't being rendered within the span. The paint and font metrics should already have the proper values so that your text render looks like the surrounding text. Of course, you'll also render the line graphics you want.
For some sample code, take a look at my answer to a similar question. This has all the pieces I just discussed.
If you want me to write some code for this, you'll need to provide some code that gives me a starting point with some actual Kannada text along with what the lines are and where they go. I don't even know if Kannada text is LTR or RTL; that might affect how the span subclass is coded. Preferably the text would correspond to the image you posted so I can see how it should look when it's working.

Java "MONOSPACED" font width

I'm creating a game and I'd like to use Java's Font.MONOSPACED font, because it is easy to use (even though it looks disgusting). The problem is that I have no idea about the fonts width-height-ratio, which is very important. I couldn't find a answer online after searching for a while.
If someone knows it or how to find it out, I'd be very grateful.
java.awt.FontMetrics is going to be your friend here.
You get access to it through a Graphics2d object:
Graphics2D gfx = ...;
gfx.setFont(...); // select your preferred font, monospaced or otherwise
FontMetrics metrics = gfx.getFontMetrics();
having done so you can get: (all from the above link to docs)
The width of any single char:
charWidth(char ch)
Returns the advance width of the specified character in this Font.
The width of a string:
stringWidth(String str)
Returns the total advance width for showing the specified String in this Font.
The height of a line
getHeight()
Gets the standard height of a line of text in this font.
I assume you can figure out how to get a width-height ratio from the above, and you can get lots of other information from different FontMetrics methods - check it out.

How can I truncate text within a bounding box?

I am writing content to a PdfContentByte object directly using PdfContentByte.showTextAligned, I'd like to know how I can stop the text overflowing a given region when writing.
If possible it would be great if iText could also place an ellipsis character where the text does not fit.
I can't find any method on ColumnText that will help either. I do not wish the content to wrap when writing.
Use this:
int status = ColumnText.START_COLUMN;
ColumnText ct = new ColumnText(cb);
ct.setSimpleColumn(rectangle);
status = ct.go();
Make sure that you define rectangle in a way so that only one line fits, use ColumnText.hasMoreText(status) to find out if you need to add an ellipsis character.

How to specify behavior of Java BufferedImage resize: need min for pixel rows instead of averaging

I would like to resize a Java BufferedImage, making it smaller vertically but without using any type of averaging, so that if a pixel-row is "blank" (white) in the source image, there will be a white pixel-row in the corresponding position of the destination image: the "min" operation. The default algorithms (specified in getScaledInstance) do not allow me a fine-grained enough control. I would like to implement the following logic:
for each pixel row in the w-pixels wide destination image, d = pixel[w]
find the corresponding j pixel rows of the source image, s[][] = pixel[j][w]
write the new line of pixels, so that d[i] = min(s[j][i]) over all j, i
I have been reading on RescaleOp, but have not figured out how to implement this functionality -- it is admittedly a weird type of scaling. Can anyone provide me pointers on how to do this? In the worse case, I figure I can just reserve the destination ImageBuffer and copy the pixels following the pseudocode, but I was wondering if there is better way.
The RescaleOp methods include a parameter called RenderingHints. There is a hint called KEY_INTERPOLATION that decides the color to use when scaling an image.
If you use the value VALUE_INTERPOLATION_NEAREST_NEIGHBOR for the KEY_INTERPOLATION, Java will use the original colors, rather than using some type of algorithm to recalculate the new colors.
So, instead of white lines turning to gray or some mix of color, you'll get either white lines, or you won't get any lines at all. It all depends on the scaling factor, and if it's an even or odd row. For example, if you are scaling by half, then each 1 pixel horizontal line has at least a 50% change of appearing in the new image. However, if the white lines were two pixels in height, you'd have a 100% chance of the white line appearing.
This is probably the closest you're going to get besides writing your own scaling method. Unfortunately, I don't see any other hints that might help further.
To implement your own scaling method, you could create a new class that implements the BufferedImageOp interface, and implement the filter() method. Use getRGB() and setRGB() on the BufferedImage object to get the pixels from the original image and set the pixels on the new image.

Categories