Label and LabelAtlas comparison? LabelAtlas is hard to use - objective-c

I have some confusion about how to use AtlasLabel. It seems Label consume a lot memory than LabelAtlas?
Such as if I create 100 line of text. Each of them is created by Label, then will it consume more memory than 100 line of text created by LabelAtlas?
Label *label1 = [[Label alloc] initWithString:#"text1" dimensions:CGSizeMake(0, 0) alignment:UITextAlignmentLeft fontName:#"Arial" fontSize:22];
.....
.....
Label *label100 = [[Label alloc] initWithString:#"text100" dimensions:CGSizeMake(0, 0) alignment:UITextAlignmentLeft fontName:#"Arial" fontSize:22];
will they be the same with
LabelAtlas *label1 = [LabelAtlas labelAtlasWithString:#"text1" charMapFile:#"abc_22c.png" itemWidth:34 itemHeight:40 startCharMap:' '];
........
.......
LabelAtlas *label100 = [LabelAtlas labelAtlasWithString:#"text100" charMapFile:#"abc_22c.png" itemWidth:34 itemHeight:40 startCharMap:' '];
I assume LabelAtlas is less expensive than Label since it uses just one image. Label creates likely an image each time it created.
I would like to convert all the text from label to labelAtlas. But I still don;t really understand how to use LabelAtlas deeply. I hardly display the string I want. I read number of examples. It seems simple but when I tried....It does not give me what I expect. Could you show me some example for displaying a long text using LabelAtlas instead of Label. I used LabelAtlas before for my point counter. But it is so hard now to display a long string. Thanks in Advance

The main difference between CCLabel and CCLabelAtlas is that the atlas version (like all the other atlas classes) uses one big texture with all the letters pre-rendered to draw a string. This means that the drawing is much faster, because if you draw 100 labels, the graphics processor doesn't have to read in 100 textures but just keep one texture in memory. But it also means that all the letters will be of a fixed size. If you want to get around the fixed-size limitation, use CCBitmapFontAtlas.
And, yes, CCLabel creates one texture for every label, whereas CCLabelAtlas renders the text on the fly, using the provided texture (containing all the characters), so using CCLabelAtlas results in lower memory consumption.
In general, try to always use the *Atlas versions of classes. You can start by using the non-atlas versions and then switch to the atlas version when you've progressed a bit and had time to generate the atlas bitmaps. Don't worry too much about it if you're just starting out.

Related

Is there a direct way to set wx.TextCtrl size by characters rather than pixels?

The constructor for wx.TextCtrl takes a wx.Size argument, which is in units of pixels. Usually, I don't want to specify the size of a multiline TextCtrl in pixels, but rather in how many characters it can show without scrolling. I find that multiline TextCtrls are often the dominant component in my windows, thus stretching by Sizer is not an option.
The wxPython Phoenix documentation contains a hint as to how to do this, however this is meant more for short text on single line control.
I have started using this utility method:
def _set_textctrl_size_by_chars(self, tc, w, h):
sz = tc.GetTextExtent('X')
sz = wx.Size(sz.x * w, sz.y * h)
tc.SetInitialSize(tc.GetSizeFromTextSize(sz))
along with code like this:
tc = wx.TextCtrl(self, style=wx.TE_MULTILINE)
self._set_textctrl_size_by_chars(tc, 80, 20)
This works, but I consider it a hack. I have looked over the documentation but have not found any other way to do it.
I understand that fonts are not usually monospaced, and using 'X' as a representative character width is inexact, however it's plenty good enough for my usage. Still, it seems there should be some way to do this directly using the wx library.
Using something like text.GetSizeFromTextSize(text.GetTextExtent("99999").x) is indeed the best way to size the text control to fit exactly 5 digits (e.g. a ZIP code in some localities). Notice that this is slightly better than your code because the width of 80 "X"s is not necessarily quite the same as 80 times the width of a single "X". And I'd also recommend using "M" or "W" which can be noticeably wider than "X" in some fonts, but this is not going to changes matters much.
We thought about adding a helper method doing this and it might indeed be useful, but, again, this still won't make things as simple as you'd like because you really need to specify the characters you want to use: "W" for letters, "9" for digits and maybe something like "x" if you want the control to be wide enough to fit the given number of characters on average instead of being wide enough to guarantee fitting the given number of the widest characters because the difference may be noticeable.
The main place where we could make life simpler would be at XRC level and this would be worth doing ("just" a question of time...), but for the code I really don't think we can make things much simpler than what they're now.

Cannot change polygon 'size' every repeat in Builder

I'm using Builder v1.80.06
I can vary the position of a polygon every repeat easily enough
e.g. I have a Positions list
positions=[[1,1],[1.1,0.9],...]
and in the 'Position field' have :
$positions[0]
and then change it's value in a code block on each repeat.
BUT I want to vary the size in a similar manner with a $sizes list but get an error.
Looking at the generated code, the problem is at the object creation stage. the code generated is:
for a hard coded polygon (ie ok)
polygon_1 = visual.Rect(win=win, name='polygon_1',
width=[1.5, .2][0], height=[1.5, .2][1],
ori=0, pos=[0, -0.6],
lineWidth=1, lineColor=[1,1,1], lineColorSpace=u'rgb',
fillColor=[0,1,0], fillColorSpace=u'rgb',
opacity=1,interpolate=True)
for one populated by a variable (not working):
polygon_2= visual.Rect(win=win, name='polygon_2',
width=1.0[0], height=1.0[1],
ori=0, pos=[0,0],
lineWidth=1, lineColor=[1,1,1], lineColorSpace=u'rgb',
fillColor=[1,0,0], fillColorSpace=u'rgb',
opacity=1,interpolate=True)
It complains (rightly) that 1.0[0] makes no sense on the width and height parameters
Even though I have my sizes list instantiated in a code block right at the beginning of the experiment instead of reading $sizes[0] a default float value of 1.0 is used.
Any other suggestions for how to vary the polygon size dynamically at runtime using builder?
I could just take the generated code and drop it into coder I suppose and fix the problem but I want to hand this over to a researcher so would like for them to be able to maintain it.
thanks,
If you set size to be a tuple/list with a pair values [1.2,1.5] or [1,1] does that not fix it?
When you change attributes at runtime, just change the attribute of an existing stimulus instead of instantiating a full new stimulus. The latter is quite heavy on ressources, causing unreliable timing. So do
stim = visual.Rect(win) # instantiation, ressource heavy
stim.attribute = newValue # change attribute. lighter.
I can think of two ways you could do it in a pretty neat way. The first is to set width and height explicitly instead of the size attribute, but using a size-like value. So (removing all parameters not of interest):
polygon_2 = visual.Rect(win)
# Unpack the x,y-sizes to the stimulus .width and .height attributes
newSize = (1.5, 0.2)
polygon_2.width, polygon_2.height = newSize
The second, if the size attribute is really important to use, is to use the Polygin with edges=4 to make it a rectangle:
polygon_2 = visual.Polygon(win=win, edges=4, size=(1.5, 0.2))
# Setting size
polygon_2.size = (0.8, 0.4)
Do try Jon's suggestion first. But the idea with visual.Rect and visual.Circleis to use substitute Polygon's size and vertices for something more relevant. So size can do unexpected things if width/height etc. are not 1.

Two NSTextFields with interdependent widths in autolayout

I’m trying to put together what seems to be a simple case of two NSTextFields with dynamic width and fixed spacing in between. I cannot figure out an effective way to do so though.
I’m looking to get something like this:
The blue boxes are the NSTextFields. When more text is entered into one, it should grow and thus make the other one shrink, maintaining the lead space, trailing space and the spacing in between the fields. The first one should take the priority if both of the fields have too much text. Each field will also clearly have a maximum and a minimum possible width it can reach.
How would I go around handling this, preferably utilising IB autolayout as much as possible?
It seems to me that all of constraints you mentioned directly translate into interface builder --
First view has width >= something.
First view has width <= something
Same for Second view.
Space between views is fixed.
Second view wants to be as small as possible (have its width at 0) but this has lower lower priority than the previous constraints and lower priority than inner content size constraints.
The code I had to add to my view controller, after applying the constraints as per the ilya’s answer:
In controlTextDidChange (_controlWidthConstraint refers to the fixed width constraint of the input; it’s probably 0 by default for the second input):
// Get the new width that fits
float oldWidth = textControl.frame.size.width;
[input sizeToFit];
float controlWidth = textControl.frame.size.width;
// Don’t let the sizeToFit method modify the frame though
NSRect controlRect = textControl.frame;
controlRect.size.width = oldWidth;
textControl.frame = controlRect;
_controlWidthConstraint.constant = controlWidth;
The key lies in invalidating the intrinsicContentSize for the text field when text is input.
You can check a sample project here, to get you on the right track.

Storing bitmap data in an integer array for speed?

I am using Cocoa/Objective-C and I am using NSBitmapImageRep getPixel:atX:y: to test whether R is 0 or 255. That is the only piece of data I need (the bitmap is only black and white).
I am noticing that this one function is the biggest draw on CPU power in my application, accounting for something like 95% of the overhead. Would it be faster for me to preload the bitmap into a 2 dimensional integer array
NSUInteger pixels[1280][1024];
and read the values like so:
if(pixels[x][y]!=0){
//....do stuff
}
?
One thing that might be helpful could be converting the data into something more "dense". Since you're only interested in a single bit per pixel location, it doesn't make sense to store more than that. Storing more data than necessary means you get less usage out of your cache, which can really slow things down if the image is big and/or the accesses very random.
For instance, you could use the platform's largest "native" integer and pack in the pixels to use a single bit for each pixel. That will make the access a bit more involved since you need to do a single-bit testing, but it might be a win.
You would do something like this:
uint32_t image[HEIGHT * ((WIDTH + 31) / 32)];
Then initialize this array by using the slow getter method, once per pixel. Then you can read out the value of a pixel using something like image[y * ((WIDTH + 31) / 32) + (x / 32)] & (1 << (x & 31)).
I'm being vague ("might", "can" and so on) since it really depends on your access pattern, the size of the image, and other things. You should probably test it.
I'm not familiar with Objective-C or the NSBitmapImageRep object, but a reasonable guess is that the getPixel routine employs clipping to avoid reading outside of memory, which could a possible slowdown (among other things).
Have a look inside it and see what it does.
(update)
Having learnt that this is Apple code, you probably can't take a look inside it.
However, the documentation for NSBitmapImageRep_Class seems to indicate that getPixel:atX:y: performs at least some type magic. You could test if the result is clipped by accessing a pixel outside of the image boundary and observing the result.
The bitmapData seems to be something you'd be interested in: get the pointer to the data, then read the array yourself avoiding type conversion or clipping.

NSImage loading a portion of image

The requirement is like this,
I would get a single large PNG Images for a button, this single image will contain images for hOver, button clicked , mouse exit that need to be displayed,
Single PNG File size would be 1024 X 28, so each image have size about 256 X 28,
I am googling the best possible approach but couldn't make out how to achieve this,
I have following approach in mind,
NSImage *pBtnImage[MAX_BUTTON_IMAGES]
for ( i = 0; i < 4 ; i++) {
pBtnImage[i] = [[NSImage alloc]initWithData:??????];
}
I want to know what should i give in the NSData parameter,
Is it possible to load a Single Image and clipped image accordingly as and when it needed.
Thanks in advance
There's no simple Cocoa-supported way to read only a sub-rectangle of the image from its data. It's a simple matter, however, to read the whole image in and only use a select rectangle of the image when compositing. Thing is, with all the available API, you might be better off just to use the standard +[NSImage imageNamed:] method to read the images in individually and let the OS handle caching.
What actual, measured performance problem are you trying to solve? Does one really exist, or is this a case of premature optimization?