Autoscaling TLF Text in AS3 - actionscript-3

I'm needing an actionscript solution that will allow dynamic text to drop into a text box with pre-determined dimensions (x, y, width, height), and then will scale the text up or down so that it is as large as it can be within those dimensions without scrolling. Wordwrap would be automatic, and there would not be any paragraph breaks.
I have a working model using Flash's Classic text, but I would like to be able to utilize the in-line styling that TLF provides. I just don't quite have my mind wrapped around all the TLF features yet.
Does anyone know if there is an already existing solution to this situation - or could perhaps steer me in the right direction?

#phil: This should help: http://aaronhardy.com/flex/size-text-to-container/
Online demo, right click for source code.

Hm - this should work, but I am not sure over how precise the TLF font size is... Anyways:
newFormat:TextFormat = new TextFormat();
newFormat.size *= myText.width / myText.textWidth;
myText.setTextFormat(newFormat);
Now - this basically creates a TextFormat object and sets it's font size to myText's (the TextField) container width (the maximal width) divided by the actual text width. Again - if the TLF font size is NOT so precise, the size line must be:
newFormat.size *= Math.round(myText.width / myText.textWidth * 100) / 100;
100 means it is rounded to hundredths.
edit: I really believe this method is not only much simpler, but also efficient... I mean - that is the point of TextField.textWidth...

Related

Setting QTextDocument painter's rectangle (where to paint)

I am painting on a window simple html using QTextDocument::drawContents(painter)
I want to do the drawing inside some margins in the window but I don't see a direct way to specify the target rectangle of the painting (in the painter/window).
I guess a few ways to do it:
Using the QTextDocuments::setMargin (although this does not allow different values for left/top.
Placing the html into an styled <div>
Applying a translation transform to the painter.
But all this seems a bit too much for what I want to do and I guess if I a missing something straight (as you do with QPainter::drawText where you tell the target rectangle)
Set the textWidth property to the width of the area where the text is supposed to fit. The clipping rectangle you pass to drawContents will cut the text off vertically if there's too much of it to fit; you can't do much about that of course.
So, this would be the missing function you're after:
void drawContents(QPainter * p, QTextDocument & doc, const QRectF & rect) {
p->save();
p->translate(rect.topLeft());
doc.setTextWidth(rect.width());
doc.drawContents(p, rect);
p->restore();
}
Yes, you do need to jump through a few hoops, that's why it needs to be factored out. It's perhaps lamentable that a similar overload of drawContents doesn't exist.

Text scaling and positioning in libgdx

I am working with libgdx. I need to scale and position text. Let's say I want to draw X that is 30 pixels hight and I want it to be in the middle of the screen. I want to draw more of those in diffrent locations and with different scales.
Is there any way how could I achieve that? I can't find the solution anywhere. I dont want to create more BitmapFonts if possible.
If you want to handle all platforms (android, html, ios, desktop) you need to use several BitmapFonts in order to avoid ugly scaling. Otherwise, if you don't need to deploy to HTML, you can use the gdx-freetype extension (see here https://github.com/libgdx/libgdx/wiki/Gdx-freetype).
Assuming you go with BitmapFont, you can simply use code similar to this to center your text:
String text = "Your text here!";
TextBounds bounds = font.getBounds(text);
font.draw(batch, text, (width - bounds.width) / 2.0f, (height - bounds.height) / 2.0f);
For scaling, you can set the scale in font.draw, but you probably want several BitmapFont of various sizes to avoid ugly artifacts.

html5 canvas animation, rotating the text is not smooth enough

The idea is simple, create a star with text and rotate it.
But its not smooth after making a quick script
here is my fiddle
The star is moving oke, but the text is shaking like a snake :)
Cause
The reason why this happening is due to the browser's text rendering engine. They are translating each point in the text path using the same rotation matrix but due to the engine you will get rounding errors in there causing the text to "jibber".
This is not only happening for canvas but for CSS transformations as well, with text.
Solution
Simply render the text to a canvas "layer" and use that as an image which you rotate instead of the text itself. This rasterizes the text in its normal position and the transformation happens on the bitmap instead which most browsers handle pretty well.
Here is one example integrating the answer I linked to in the comments. I'm showing only the main text as it works as a comparer as well, before and after:
// canvas layer
var tcanvas = document.createElement('canvas'); //tcanvas must be in global scope
var tctx = tcanvas.getContext('2d');
tcanvas.width = canvas.width;
tcanvas.height = canvas.height;
tctx.translate(250, 250);
tctx.fillStyle = "black";
tctx.font = "bold 60px Arial";
tctx.textAlign = 'center';
tctx.fillText('€ 1215,34', 0, 0);
Now the layer is ready and we can replace the text drawing methods with a single drawImage instead:
c.drawImage(tcanvas, -x, -y);
Result of this modification
To draw the "extra" just move those lines down to the layer creation as well. Note that tcanvas in the example must be accessible globally.
If the rotation speed of the text is not intentional just remove the second call to rotate you have there before rendering the text.
Tip: instead of redrawing gradients and the star just render it once to another layer and rotate that as an image as well. This will be much more efficient. You could also avoid save/restore (which are relative costly) by just accumulating the step on rotate() itself and use setTransform to transform the matrix using absolute values.
Ways to optimize memory usage: for text layer use a canvas size where the text fits in exact (don't use fixed values as text size may vary in size and position from browser to browser depending on the text rendering engine), same for star if you go with a layer for that as well.
Hope this helps!
The shake in your text comes from the fact that the context is not in a proper state when you draw the text : you just did quite some operations on it before.
I just added a
c.restore();
c.save();
c.translate(x,y);
before the text part of your code, and the text is solidly hung to the star now :
http://jsfiddle.net/gamealchemist/xUr4f/1/
Edit : There are in fact 2 issues at stake here : 1) the text rotation is not quite on track with the star and 2) the rounding of the text coordinates makes the text shake.
Both Chrome and FF exhibit 1) of course, and with a clean context 1) disappear on both.
For 2) : Chrome is ok with non-integer coordinates text, but FF does round, which creates a shake on a rotating text.
Only solution i see it to 'print' the text on a canvas, then have the canvas rotate. I did it for the 'extra' in this fiddle :
http://jsfiddle.net/xUr4f/4/
There's a loss of quality compared to the fillText, but unless the coordinates rounding can be avoided, it seems as the best solution.

Making a AS3 "Textfield" with buttonMode and useHandCursor

Sorry for the bad title. Couldn't think of a better one...
I'm doing a software that is configurable with loaded data from XML.
User can define the max "width" of an TextField and the TextFields are multiline and wrapping happens when the text wouldn't fit the width. Text for the TextFields is also loaded from the XML file and the length is arbitrary.
Because TextField doesn't have neither buttonMode or useHandCursor properties I made TextFields children of sprites. So for every TextField there is a sprite as a parent.
Then the real problem:
("TextFields" are actually the sprites with a TextField as a child)
The "TextFields" should not be clickable outside of the text in them. At the moment it seems like that the sprites extend to the full width of the TextFields and therefore user can actually click the "TextFields" from an area where there is no text.
I "tried" to change the size of the sprite, checked the AS3 reference and now I know why everything disappeared after that.
So I need a solution in which, the "TextFields" have buttomMode and useHandCursor enabled and the container should be able to cut off the area where there is no text.
The TextField object has some default sizing characteristics. You need to apply one of these:
TextFieldAutoSize
to this property:
TextField.autoSize
to get it to form fit your text. Then by adding it into an empty Sprite, said Sprite will also be the exact size of your text.
Changing the size of the Sprite is the wrong approach as what you're actually doing in that case is scaling its interior content. Sprites automatically size themselves to fit the objects they contain. As long as you deal with making sure the TextField is sized properly, the parent Sprite will be sized properly as well.
Im sure you dont need it anymore but someone may do, so here it is.
As you have a sprite as parent them you can make him to desable the mouseChildren.
yourSprite.tf.text = 'something';
yourSprite.buttonMode = true;
yourSprite.mouseChildren = false;

TextField autoSize+italics cuts of last character

In actionscript 3, my TextField has :
CSS styling
embedded fonts
textAlign : CENTER
autoSize : CENTER
... when italics are used the very right character gets slightly cut off (specially caps).
It basically seems that it fails detecting the right size.
I've had this problem before but just wondered is there a nice workaround (instead of checking textWidth or offsetting text etc.)?
Initialize your textField as you always do, using multiline, autosize, htmlText...
Then do this little trick :
// saving wanted width and height plus 1px to get some space for last char
var savedWidth = myTextField.width + 1;
var savedHeight = myTextField.height + 1;
// removing autoSize, wich is the origin of the problem i think
myTextField.autoSize = "none";
// now manually autoSizing the textField with saved values
myTextField.width = savedWidth;
myTextField.height = savedHeight;
Not that it is much comfort to you, but Flash sometimes has trouble with this seemingly simple task. CSS styling of html TextField was a nice addition but it has caused headaches for text-rendering. In fact I very rarely use CSS for styling text for that reason. I can only imagine that combining bold, italic and normal type faces within the HTML causes Flash to get some of the width calculations wrong which causes autoSize to set the mask a tiny bit short. I hope very much that the new text rendering engine in Flash Player 10 will finally fix these issues (it certainly looks better in theory).
So my solution is never to use HTML with the exception being when I require <a> links in my text ... and there are even some tricky text shifting issues there. In those cases I avoid mixing different font weights and font styles within the same text field. All other cases I use TextFormat directly on TextField.
I suppose if you can't get out of your current architecture (for some reason) you could try adding to the end of your html encoded strings. Or you could manually set the width of the field and not rely on autoSize (as you have mentioned). But if you keep on the CSS/HTML route you may find another new and painful limitation just when you don't want it.
I've had issues with TextField masks behaving differently in the Flash preview, and in the actual browser plugin. Usually, and this is strange to me, it would appear more correctly in the browser. Have you tried running the swf in a browser to see if the problem is actually an annoyance rather than a permanent problem?
I had said this:
My in-ideal approach to solving this is to attach a change event to the TextField which always adds a space after the last character of the field. And then to remember to trim this space off when using the value.
But that didn't take into account that this probably doesn't have a change event and that it's an HTML rendered text field. To add a trailing space in the HTML text field throw in an again, that's not really fixing the problem.