Drawing strings with slick2d and TTF - string

I've been experimenting with String printing in LWJGL using slickutils. Generally when browsing the web I found two approaches to this. First being bitmaps where you have an entire alphabet and print each letter as a Texture, the other being using TrueTypeFonts and the truetypefont.drawString(20f,20f,"LWJGL String Test", Color.green) method.
However, most of the literature I found was a few years old. What is the right way to do this at the current time?
At the moment I'm using the TrueTypeFont method, however my result confuses me.
//It doesn't matter which Font I try to load, I get the same green bar.
//I think it has something to do with not finding the Fonts?
Font awtFont = new Font("Times New Roman", Font.BOLD, 24);
TrueTypeFont font = new TrueTypeFont(awtFont, true);
font.drawString(20f, 20f, "LWJGL TEST STRING",Color.green);
I've also copied an example from the internet and get the same result(just a bar).
Tried googling but couldn't find any fixes.

TrueTypeFont is deprecated. Use UnicodeFont instead.
Check this:
// Create a font with the size of 20, and not bold or italic.
Unicode font = new UnicodeFont("res/font.ttf", 20, false, false);
font.addAsciiGlyphs();
font.getEffects().add(new ColorEffect());
font.loadGlyphs();
g.setFont(font);
g.drawString("Shit example", 100, 100);

Related

How to insert a button into a window specified by a Fl_Window*?

Fl_Window *win = new Fl_Window(width, height, "title");
b1 = new Fl_Button(0, 0, 120, 30);
win->end();
b2 = new Fl_Button(130, 0, 120, 30);
win->show();//argc,argv);
Fl::run();
Here, second button b2 will not be shown, because after the call to end(), it is inserted into somewhere else not into win. After browsing through official docs and googling I still cannot understand the idea behind it, and how am I supposed to insert a new button into the window that is not currently selected for insertion? Is there something like win->begin() ?
By the way FLTK docs are rather a machine generated reference, very inconvenient for a learner, any good unofficial resource known?
Widgets can be added either between begin() and end() or using add.
Fl_Window *win = new Fl_Window(width, height, "title");
win->begin();
b1 = new Fl_Button(0, 0, 120, 30);
win->end();
b2 = new Fl_Button(130, 0, 120, 30);
win->add(b2)
The FLTK docs are generated by doxygen so basically they are only as good as the comments in the code (which is not bad for doxygened documentation). You'll get the same problem with code documented with javadocs and the C# autogenerated XML documentation.
Have you had a look at http://seriss.com/people/erco/fltk/ and http://seriss.com/people/erco/fltk-videos/ . They are the official "helper" web pages. I learnt a lot just by looking at the cheat sheet and examples in the distribution tarball test directory.

SKIA - Inaccurate value returned by measureText()

I have a problem measuring text using skia measureText() function.
The value returned is inaccurate.
SkPaint *skPaint = new SkPaint();
SkTypeface* myFont = SkTypeface::CreateFromName("Impact", SkTypeface::kNormal);
skPaint->setTypeface(myFont);
skPaint->setAntiAlias(true);
skPaint->setTextAlign(SkPaint::kLeft_Align);
skPaint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
skPaint->setTextSize(SkIntToScalar(120));
skPaint->setColor(0xff000001);
canvas->drawText(text, length, SkIntToScalar(x) , SkIntToScalar(y) , *skPaint);
SkScalar width = skPaint->measureText(text, length);
The width returned by measureText() is 451.
I checked the generated bitmap text via a photo editor app, the actual width is only 438.
Any thoughts on getting the accurate width of text in SKIA?
Thank you!
I believe what you are trying to match will come from "bounds"
SkRect bounds;
SkScalar textWidth = paint.measureText("some", 4, &bounds);
which is a minimum rectangle to fit a given text, whereas textWidth is slightly larger than that.
I faced this issue too. Dont know why exactly it happens, maybe because of kerning differences, but i came to this:
SizeF RenderTextAndroid::GetStringSizeF() {
UpdateFont();
const base::string16& text = GetLayoutText();
std::vector<SkScalar> widths(text.length());
paint_.getTextWidths(text.c_str(), GetStrByteLen(text), &widths[0], NULL);
return SizeF(std::accumulate(widths.begin(), widths.end(), 0),
font_metrics_.fBottom - font_metrics_.fTop);
}
Where UpdateFont just sets new parameters to SkPaint

setting line height for text element in raphael

I'd like to increase the line height for a multiline text element generated with raphael. This does not appear to work:
text_element.attr({"line-height": "16" });
How can this be done? Thanks
You can do the following, but it's not pretty and breaks the encapsulation provided by Raphael. Consider the following:
text_element = r.text(10, 10, "Text in\nRaphael\nis a pain");
text_element.node.childNodes[0].setAttribute('dy', 0);
text_element.node.childNodes[1].setAttribute('dy', 5);
text_element.node.childNodes[2].setAttribute('dy', 5);
This will yield overlapping lines of text with the default font settings.
If I discover a better way, I'll update my answer.

Custom font does not render correctly when using ShowText

I have a custom view in which I am trying to draw text using a Windows font (calibri.ttf). However, I am getting different behaviour between using the DrawString & ShowText functions.
I have embedded the font as part of the app (added it to the UIAppFonts list & set it's build action to Content) and I all works fine when I use the DrawString method from my custom UIView e.g.
Code
public override void Draw (System.Drawing.RectangleF rect)
{
base.Draw (rect);
DrawString("Calibri font via DrawString", new RectangleF(10, 10, 100, 100), UIFont.FromName("Calibri", 16f));
}
Result
However, if I attempt to draw the same text this time using ShowText it appears as if the font isn't encoding the text correctly, or the character mapping is wrong.
Code
public override void Draw (System.Drawing.RectangleF rect)
{
base.Draw (rect);
var ctx = UIGraphics.GetCurrentContext();
ctx.SelectFont("Calibri", 16f, MonoTouch.CoreGraphics.CGTextEncoding.FontSpecific);
ctx.ShowTextAtPoint(10, 10, "Calibri font via ShowText using SelectFont");
}
Result
UPDATE - Here is what I get if I use MacRoman encoding instead of FontSpecific:
I have also tried loading in the font manually and using that but then I get nothing at all, it's like it doesn't recognise the font e.g.
var fontPath = NSBundle.MainBundle.PathForResource("calibri", "ttf");
var provider = new CGDataProvider(fontPath);
var font = CGFont.CreateFromProvider(provider);
var ctx = UIGraphics.GetCurrentContext();
ctx.SetFont(font);
ctx.ShowTextAtPoint(10, 20, "Calibri font via ShowText using SetFont");
I know that DrawString is UIKit & ShowText is CG (Quartz) so I understand that there may be differences. However, from what I gathered the only difference with DrawString was it corrected the issue with the difference in Offset (CG being at the bottom left/UIKit being at the top left).
NOTE - The underlying problem I have is I need to use this font to draw text onto a layer via a custom CALayerDelegate. I don't have access to the DrawString function from in there, therefore, the only way I can see to draw the text is via ShowText. Alternative solutions are welcome!
This really looks like an encoding issue. Try using CGTextEncoding.MacRoman instead of CGTextEncoding.FontSpecific (even Arial wouldn't render, as expected, with FontSpecific).
UPDATE Oct 12th
a) your last code sample won't work because Apple doc specifically states not to use SetFont and ShowText together. Quote follow:
Quartz uses font data provided by the system to map each byte of the array through the encoding vector of the current font to obtain the glyph to display. Note that the font must have been set using CGContextSelectFont. Don’t use CGContextShowText in conjunction with CGContextSetFont.
b) the CGTextEncoding.MacRoman code works with several other iPhone-supplied fonts. I'm beginning to suspect it's something about the Calibri.ttf font itself that is not supported by iOS.

SVG Word Wrap - Show stopper?

For fun I am trying to see how far I can get at implementing an SVG browser client for a RIA I'm messing around with in my spare time.
But have hit what appears to be a HUGE stumbling block. There is no word wrap!!
Does anyone know of any work around (I'm thinking some kind of JavaScript or special tag I don't know)?
If not I'm either going to have to go the xhtml route and start sticking HTML elements in my SVG (ouch), or just come back again in ten years when SVG 1.2 is ready.
This SVG stuff is baffling, isn't it ?
Thankfully, you can achieve some good results, but it takes more work than using the HTML 5 .
Here's a screenshot of my ASP.Net / SVG app, featuring a bit of "faked" word wrapping.
The following function will create an SVG text element for you, broken into tspan pieces, where each line is no longer than 20 characters in length.
<text x="600" y="400" font-size="12" fill="#FFFFFF" text-anchor="middle">
<tspan x="600" y="400">Here a realy long </tspan>
<tspan x="600" y="416">title which needs </tspan>
<tspan x="600" y="432">wrapping </tspan>
</text>
It's not perfect, but it's simple, fast, and the users will never know the difference.
My createSVGtext() JavaScript function takes three parameters: an x-position, y-position and the text to be displayed. The font, maximum-chars-per-line and text color are all hardcoded in my function, but this can be easily changed.
To display the right-hand label shown in the screenshot above, you would call the function using:
var svgText = createSVGtext("Here a realy long title which needs wrapping", 600, 400);
$('svg').append(svgText);
And here's the JavaScript function:
function createSVGtext(caption, x, y) {
// This function attempts to create a new svg "text" element, chopping
// it up into "tspan" pieces, if the caption is too long
//
var svgText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
svgText.setAttributeNS(null, 'x', x);
svgText.setAttributeNS(null, 'y', y);
svgText.setAttributeNS(null, 'font-size', 12);
svgText.setAttributeNS(null, 'fill', '#FFFFFF'); // White text
svgText.setAttributeNS(null, 'text-anchor', 'middle'); // Center the text
// The following two variables should really be passed as parameters
var MAXIMUM_CHARS_PER_LINE = 20;
var LINE_HEIGHT = 16;
var words = caption.split(" ");
var line = "";
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + " ";
if (testLine.length > MAXIMUM_CHARS_PER_LINE)
{
// Add a new <tspan> element
var svgTSpan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
svgTSpan.setAttributeNS(null, 'x', x);
svgTSpan.setAttributeNS(null, 'y', y);
var tSpanTextNode = document.createTextNode(line);
svgTSpan.appendChild(tSpanTextNode);
svgText.appendChild(svgTSpan);
line = words[n] + " ";
y += LINE_HEIGHT;
}
else {
line = testLine;
}
}
var svgTSpan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
svgTSpan.setAttributeNS(null, 'x', x);
svgTSpan.setAttributeNS(null, 'y', y);
var tSpanTextNode = document.createTextNode(line);
svgTSpan.appendChild(tSpanTextNode);
svgText.appendChild(svgTSpan);
return svgText;
}
The logic for word-wrapping is based on this HTML5 Canvas tutorial
I hope you find this useful !
Mike
http://www.MikesKnowledgeBase.com
UPDATE
One thing I forgot to mention.
That "Workflow diagram" screen that I've shown above was originally just written using an HTML 5 canvas. It worked beautifully, the icons could be dragged, popup menus could appear when you clicked on them, and even IE8 seemed happy with it.
But I found that if the diagram became "too big" (eg 4000 x 4000 pixels), then the would fail to initialise in all browsers, nothing would appear - but - as far as the JavaScript code was concerned, everything was working fine.
So, even with error-checking, my diagram was appearing blank, and I was unable to detect when this showstopper problem was occurring.
var canvasSupported = !!c.getContext;
if (!canvasSupported) {
// The user's browser doesn't support HTML 5 <Canvas> controls.
prompt("Workflow", "Your browser doesn't support drawing on HTML 5 canvases.");
return;
}
var context = c.getContext("2d");
if (context == null) {
// The user's browser doesn't support HTML 5 <Canvas> controls.
prompt("Workflow", "The canvas isn't drawable.");
return;
}
// With larger diagrams, the error-checking above failed to notice that
// the canvas wasn't being drawn.
So, this is why I've had to rewrite the JavaScript code to use SVG instead. It just seems to cope better with larger diagrams.
There is also foreignObject tag. Then you can embed HTML in SVG which gives the greatest flexibility. HTML is great for document layout and has been hacked to no end to support application layout, drawing, and everything us developers want. But it's strength is word wrapping and document layout. Let HTML do what it does best, and let SVG do what it does best.
http://www.w3.org/TR/SVG/extend.html
This works for most browsers FireFox, Opera, Webkit, except IE (as of IE11). :-( Story of the web ain't it?
SVGT 1.2 introduces the textArea element http://www.w3.org/TR/SVGTiny12/text.html#TextInAnArea , but it is only experimentally supported by Opera 10 at the moment. I don't know if other browsers will ever plan on implementing it, though I hope they will.
Per this document, it appears that tspan can give the illusion of word wrap:
The tspan tag is identical to the text tag but can be nested inside text tags and inside itself. Coupled with the 'dy' attribute this allows the illusion of word wrap in SVG 1.1. Note that 'dy' is relative to the last glyph (character) drawn.
The svg.js library has a svg.textflow.js plugin. It's not ultra fast but it does the trick. It even stores overflowing text in a data attribute so you can use it to create continuously flowing columns. Here the text flow example page.
An alternative method is to use Andreas Neuman's text box object.
These days, flowPara can do word wrapping, but I have yet to find a browser that supports it properly.
I've been looking for a solution about word wrapping in svg so many hours (or many days).
If you can in your app, edit your code to put some tspan, or any other method, go in it.
Text wrapping will be implement in the 1.2 version but except opera, no browser fully implement it yet (4 years, the specification are on the W3 ...).
Because I had to use some alignment settings, i couldn't use any of the code that many forum can provide (no foreign object, no carto script or anything).
If I post this message, it's just in order to be usefull to some other people when googling word wrapping svg because this post on the top result and in many case, this post doesn't help.
Here is a cool, easy and light solution :
http://dev.w3.org/SVG/profiles/1.1F2/test/svg/text-dom-01-f.svg

Resources