Texture2d with strings

Member
Posts: 306
Joined: 2009.03
Post: #1
I got fonts rendering well thanks to some post from Anotherjake and kTexture2DPixelFormat_A8 voodoo. Draws on transparency and everything. Awsome. However I don't understand the following:

texture2D=[[Texture2D alloc] initWithString:inputText dimensions:CGSizeMake(256., 16.) alignment:UITextAlignmentLeft font:[UIFont systemFontOfSize:14.0]];

The question is this, if i specify a small size, like 32x16 it cuts it off. What I really want is it to tell me the size based on the font size. Am I missing something here?
Ideally it should be autosized so that I can just call drawAtPoint. The other thing is that the content width seems to match that passed value and not the actual content size of whatever it rendered on the temporary buffer.

If anyone knows what I need to do to get the "needed size" so that I can do things like centering etc, that would be great. Thanks!
Quote this message in a reply
Member
Posts: 306
Joined: 2009.03
Post: #2
Doing some digging, I found the original crash landing code. They do:
_statusTexture = [[Texture2D alloc] initWithString:string dimensions:CGSizeMake(256, 256) alignment:UITextAlignmentLeft fontName:kFontName fontSize:kScoreFontSize];


That seems like an awfully big texture. I guess they are just guessing on what the max size will be? Very strange. They center it which I guess puts it in the center of the texture. Then because the drawAtPoint function also centers it the text will be centered correctly. They don't seem to know or need to know what the dimensions are. Obviously this won't work if your trying to position things based on the size of the string, but if you know exactly where it needs to go in absolute co-ordinates then this would work.
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #3
drawAtPoint is going to be the reason it's centered, since the requested alignment is UITextAlignmentLeft according to that snippet.

I swear there's a routine for getting the dimension of what the text will be after it's rendered (before you actually render it), but I can't for the life of me recall where I saw that, sorry. Annoyed

What I do is just oversize my texture a little bit, guessing at a max size, like 32x512 for one long line, and then doing like a drawInRect and using UITextAlignmentLeft so at least I know where the left edge is, and I can position it based on that edge.
Quote this message in a reply
Member
Posts: 306
Joined: 2009.03
Post: #4
I just stumbled across the solution from another forum
Code:
- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions
alignment:(UITextAlignment)alignment fontName:(NSString*)name
fontSize:(CGFloat)size
{
    NSUInteger                width,
                            height,
                            i;
    CGContextRef            context;
    void*                    data;
    CGColorSpaceRef            colorSpace;
    UIFont *                font;
// NEW FEATURE - START
    CGSize                    textSize;
    
    font = [UIFont fontWithName:name size:size];
    textSize = [string sizeWithFont:font forWidth:dimensions.width
lineBreakMode:UILineBreakModeWordWrap];
    if (textSize.width == 0 || textSize.height == 0)
    {
        textSize.width = 1;
        textSize.height = 1;
    }
    if (dimensions.width > textSize.width)
        dimensions.width = textSize.width;
    if (dimensions.height > textSize.height)
        dimensions.height = textSize.height;
// NEW FEATURE - END

and then to support line breaking you need to work this in
Code:
dimensions = [string sizeWithFont:font constrainedToSize:dimensions
lineBreakMode:UILineBreakModeWordWrap];
    if (dimensions.width == 0 || dimensions.height == 0)
    {
        textSize.width = 1;
        textSize.height = 1;
    }
Quote this message in a reply
Member
Posts: 306
Joined: 2009.03
Post: #5
Hey Jake. The 2nd snippet was with centering. I believe you put all these pieces together with what I just posted and the problem can be solved. Yipeee
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #6
Yes, I think sizeWithFont may have been what I was thinking of.
Quote this message in a reply
Member
Posts: 306
Joined: 2009.03
Post: #7
Hey while you are here... I want to track my color last set to avoid calls to opengl when i am setting the color to what already is(eg two setColors to 1,1,1,1 in a row). My question is the following:
1)Is checking the floats (4 of them rgba) faster then making a set color call
2)Are floats accurate enough that they will == often enough to actually save time. For example sometimes 1 is really 0.9999999999994 or something
3)if i use ints to avoid #2, then i have to divide by 255 to get a 0-1 range. That introuduces extra math when it would not always be needed.
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #8
That is a really darn good question! I don't know the answer to that either, but I can tell you that I cache color too and it doesn't seem to *hurt* performance as far as I've been able to tell. Generally speaking, shadowing (or caching if you will) the GL state is a good thing, so it would make sense on the outside.

I just use the if (float1 == float2) and I do get plenty of hits, especially with 0's and 1's. Hopefully somebody with better knowledge of this will stop by here, because I've often wondered if it's actually worth the trouble. And if it is, I've then often wondered if I should go further and do a cache of colors if they're "close enough", like 0.111 is close enough to 0.112 to say they're the same.
Quote this message in a reply
Member
Posts: 166
Joined: 2009.04
Post: #9
kendric Wrote:Hey while you are here... I want to track my color last set to avoid calls to opengl when i am setting the color to what already is(eg two setColors to 1,1,1,1 in a row). My question is the following:
1)Is checking the floats (4 of them rgba) faster then making a set color call
2)Are floats accurate enough that they will == often enough to actually save time. For example sometimes 1 is really 0.9999999999994 or something
3)if i use ints to avoid #2, then i have to divide by 255 to get a 0-1 range. That introuduces extra math when it would not always be needed.

There is always some overhead when calling OpenGL methods ( and not just because of the call itself - internally it has to retrieve the current context and generally do some bookkeeping code)
Personally,I only check for things like textures ,vertex buffers and blend states .... in general if some other state indicates that I have to set a color value I just do it without checking.

Comparing floats with == is quite problematic, it really depends on the value itself ... generally people use something like this ( there are more optimized ways to do that ... ie by messing with the internal float format)

Code:
        static inline bool Equal(float a, float b, float tolerance = std::numeric_limits<float>::epsilon())
        {
            if (fabs(b-a) <= tolerance)
                    return true;
            else
                return false;
        }

If you really want to do that , I think it would be more beneficial to have an int value precomputed and use that for comparison - generally you don't have to recompute it on every frame ... only when the underlying color value changes ( which should only happen when you are animating or interpolating as opposed to on every frame)


You can use code like this to turn 4 floats into a single int:

Code:
        inline unsigned int getRGBA() const
        {
            unsigned char val8;
            unsigned int val32 = 0;
    
            val8 = static_cast<unsigned int>(a* 255);
            val32 = val8 << 24;

            val8 = static_cast<unsigned int>(b * 255);
            val32 += val8 << 16;

            val8 = static_cast<unsigned int>(g * 255);
            val32 += val8 << 8;

            val8 = static_cast<unsigned int>(r * 255);
            val32 += val8;

            return val32;
        }
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #10
You can also use a call like glColor4ub instead of glColor4f, so that you cut floating point numbers out of the picture entirely.
Quote this message in a reply
Member
Posts: 166
Joined: 2009.04
Post: #11
ThemsAllTook Wrote:You can also use a call like glColor4ub instead of glColor4f, so that you cut floating point numbers out of the picture entirely.

Yeah, but floats tend to be useful when interpolating or doing some kind of color transformations ( you could do that with ints and fixed point only but it is a waste on a cpu equipped with a decent floating point unit)

In any case, I don't think glColor* calls will make or break a game ...
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Texture2d crash lander ajrs84 0 2,881 Apr 1, 2012 08:54 AM
Last Post: ajrs84
  Problem using Texture2D sub-section bendell 0 2,523 Mar 20, 2010 02:06 AM
Last Post: bendell
  Create a texture2d with contents of other textures godexsoft 6 4,782 Nov 12, 2009 10:24 PM
Last Post: godexsoft
  OpenGL ES and Texture2D Talyn 37 32,412 Jul 30, 2009 09:34 AM
Last Post: Splat21
  Texture2D and other transparent objects kappolo 9 6,610 Apr 17, 2009 12:07 PM
Last Post: AnotherJake