Multi-colored text in libgdx - java

I found out there is a new component in LibGDX in nightly builds - TextArea which is part of the scene2d.ui package. It's nice to have a component like this, very easy to use, but what I'm missing is some support for a multi-colored text.
I want to highlight some keywords in a text with a different color but I don't know how to do it with current api. There is one method in BitmapFontCache class:
public void setColors (Color tint, int start, int end)
Javadoc for this method says following:
Sets the color of the specified characters. This may only be called after setText(CharSequence, float, float) and is reset every time setText is called.
But I don't know how to use it through TextArea object or if it's even possible to do it that way. Someone who tried to figure it out? Every hint will be appreciated.

Libgdx offers color markup, which must first be enabled on the BitmapFont with
font.getData().markupEnabled = true;
Text rendered with that font will look for color markup, where colors are surrounded in brackets. Each used color is pushed onto a stack.
Named colors (case sensitive): [RED]red [ORANGE]orange
Hex colors with optional alpha: [#FF0000]red [#FF000033]transparent
A set of empty brackets pops a color off the stack: [BLUE]Blue text[RED]Red text[]Blue text
A double bracket [[ represents an escaped bracket character, however it will not work as expected when followed by a closing bracket.
Named colors are defined in the class com.badlogic.gdx.graphics.Colors, and can be added with Colors.put("NAME", color);.

Hopefully this isn't super late.
I haven't tried it your way, but I bet you would have to overwrite the setText method and then set the colors for the specific points you want. start and end are indices for the pieces of text you want in that particular color.
I have implemented a MulticolorTextArea here: https://github.com/AnEmortalKid/MulticolorTextArea/tree/mta-release
Hopefully this helps out.

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.

Again having invisible text coming from PdfTextStripper

File example: file.
Problem - when extracting text using PdfTextStripper, there is token "9/1/2017" and "387986" after "ASSETS" in the page start which should be removed, and some others hidden tokens.
I have already applied this solution (so I do not copy-paste it here, because actually problem is exactly the same) and still that hidden text is appearing on page. Could it be hidden by something else except clip path?
thanks!
Could it be hidden by something else except clip path?
Yes. In case of your new document the text is written in white on white, e.g. the 387986 after ASSETS is drawn like this:
1 1 1 rg
/TT0 16 Tf
-1011.938 115.993 Td
(#A,BAC)Tj
The initial 1 1 1 rg sets the fill color to RGB WHITE. (Additionally that text is quite tiny but would still be visible if drawn in e.g. BLACK.)
The solution you refer to was implemented for documents like the sample document presented in that issue in which the invisible text is made invisible by defining clip paths (outside the bounds of which the text is) and by filling paths (hiding the text underneath). Thus, your white text won't be recognized by it as hidden.
Unfortunately recognizing invisibility of WHITE on WHITE text is more difficult to determine than that of clipped or covered text because one not only needs to know the a property of the current graphics state (like the clip path) or remove all text inside a given path, one also needs to know the color of the part of the page right before the text is drawn (to check the on WHITE detail).
If, on the other hand, you assume the page background to be essentially WHITE, it is fairly simple to ignore all white text: Simply also detect the current fill color in processTextPosition:
PDColor fillColor = gs.getNonStrokingColor();
and compare it to the flavors of WHITE you want to consider invisible. (Usually it should suffice to compare with RGB, CMYK, and Grayscale WHITE; in seldom cases you'll also have to correctly interpret more complex color spaces. Additionally you might also consider nearly WHITE colors invisible, (.99, .99, .99) RGB can hardly be distinguished from WHITE.)
If you find the current color to be WHITE, ignore the current TextPosition.
Be aware, though, just like the solution you referenced this is not yet the final solution recognizing all WHITE text: For that you'll also have to check the text rendering mode: If it is just filling (the default), the above holds, but if it is (also) stroking, you'll (also) have to consider the stroking color; if it is rendered invisible, there is no color to consider; and if the text rendering mode includes adding to path for clipping, you'll have to wait and determine what will be later drawn in this part of the page as long as the clip path holds, definitely not trivial!

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.

LibGDX WrappedText but by using colors within the text (java)

I have made some code in the past to check through text to find color codes that will change the color of the text. Ex:
Drawing this:
Hello my name&b is john
would give this as a result when drawn: Hello my name is john but "is john" would be in blue since i used the &b color code. I am basically imitating ansi but for java.
Now I would like to wrap the text exactly like LibGDX's BitMapFont.drawWrapped(...) but still use the color codes. Anyone know how to do this? I would probobly be able to figure it out eventually but I just wanted to know if there was a better way than mine.
There is support for color markup: Color Markup Language:
The BitmapFontCache class supports in-string colored text through a simple markup language.
Markup is disabled by default. Use the method BitmapFont.setMarkupEnabled() to turn it on/off.
The markup syntax is really simple but still versatile:
[name] Sets the color by name. There are a few predefined colors, see the Colors.reset() method for an exhaustive list. Users can define their own colors through the methods of the Colors class.
[#xxxxxxxx] Sets the color specified by the hex value xxxxxxxx in the form RRGGBBAA where AA is optional and defaults to 0xFF.
[] Sets the color to the previous color (kind of optional end tag)
[[ Escapes the left bracket.
Notice that color names are case-sensitive, cannot be empty, cannot start with neither # nor [, and cannot contain ]. Also, any occurrence of [ in the color name must not be escaped.
For a sample code see the test class BitmapFontTest.

How to find true visible size of a text string in Java

Is it possible to find the true bounding box of a string in Java? ie the smallest rectangle which includes the pixels which actually get painted?
I have looked at FontMetrics and LineMetrics, and although they allow a string to be passed in, they don't appear to take account of the characters themselves, eh "a", "p" and "P" all return the same height.
Specifically, they seem to include the descent in the string height even if the actual character does not descend below the baseline. Are there other metrics I can access which return a true bounding box?
Alternatively, is there any way to tell if a particular character has a descender?
See this tutorial on measuring text, which is heavily focused on FontMetrics.
The more advanced measurements (to get the bounding box of a particular string), then TextLayout is your friend, as explained here.
In addition to that tutorial on TextLayout, the javadoc contains examples of its use.
You can use javax.swing.SwingUtilities.layoutCompoundLabel. Do not be deterred by the many parameters. There are two versions, the version with the JComponent (may be null) does more flags. It is used for JLabel, so quite versatile, and yields a Rectangle.
BTW That even on "a" a descender might be added to the bounds, is likely to happen here too. You could take the GlyphVector and calculate a bounding box there, but what when font hinting is on, so the pixel positions are slightly off, which error might accumulate over several chars?

Categories