UIFont and Diacriticals - iphone

I'm writing a iPhone app that needs to render i18n text that includes diacriticals (tildes, accents, etc.). Apple provides the UIFont class which can be used to get a given typeface/font-size combination's leading, ascent, descent, etc.
The problem is that this information does not accurately reflect diacriticals. Specifically, diacriticals on capital letters often exceed the lineHeight (the UIFont property formerly known as leading).
The same problem exists throughout the frameworks, ie. NSString:sizeWithFont has the same issue.
I need to know the true bounding box for text as I am using OpenGL which does not have text drawing support and therefore requires rendering text to a texture.
Currently, I'm using a hack to get around this issue. Is there a better way?

It's not possible with NSString, since it just returns a size. You can try CoreText which seems to support returning bounding boxes, but that's a bit overkill.
It's a difficult problem when Unicode supports things like è̀̀̀ (see also: zalgo); things can render above the top of a line so you can't just draw the characters. Some text-drawing APIs make you specify the baseline and give you the bounding box so you can get both ascenders and descenders, but UIKit doesn't do this.
Then, you have crazy cursive fonts with the occasional huge ascender. It's unclear how to handle these either.
The lazy way is to render to a texture with margins at the top and bottom (0.5 lines? 1 line?) and not care too much about the extra overhead of some transparent pixels.
I haven't looked at CoreText much, but it doesn't look particularly promising.

Related

How to bend / crook a Flutter widget? (non-affine widget render transform)

Let's say you have some flutter widget, for example, a TabBar. It is rendered in a rectangular box. I need it to be rendered in an arc so that the text and the underline follow part of a circle (or better still, a bezier curve).
How can that be achieved?
This illustrates what I am trying to achieve - bent TabBar widget:
Please note that in this case, the TabBar bends following and an arc (edge of a circle). This is what I need immediately. However, in the future, I might need bending that follows the edge of an eclipse so a solution that allows it would be preferable.
Also, a solution that works for different widgets is preferred.
IMPORTANT: I do NOT want to clip a curved shape of the widget. The entire area of the widget should stay visible. Instead, I need to bend the content of the widget (=bend its render image).
Apologies for the bold font but without it, people will keep posting answers about how to clip a widget which is trivial in comparison and useless for my problem.
An answer "this is currently not supported by Flutter" from authority (e.g. high reputation in Flutter tag or Flutter a team member) will also be accepted.
One approach: Use a CustomPaint to draw lines/areas/etc freely
You can use a CustomPaint to draw whatever curved lines, areas, etc freely. Therefore, you can definitely achieve your goal - since they are nothing but curved lines, areas with curved edges, rotated texts, etc.
That will take a bit of work, but if you encapsulate it well enough, it is not that hard to implement. For example, draw a Path with filled red area, then draw a white arc, then draw several texts with calculated rotations, etc. Sounds like you can do that within maybe hundreds of lines. If you find difficulty implementing this please comment and I will explain.
Another approach: Hack Canvas such that the call to drawLine becomes indeed calls to drawPath, etc.
You may do the following to allow bend/crook for any widget (and their combination, of course), but this may need a bit of engineering. You can make your own Canvas, say, class BendCanvas implements Canvas {}. The BendCanvas.drawLine, for example, has an implementation of Canvas.drawPath with a curved path cooresponding to the input "line". Similar things hold for drawing rectangles, etc. Then you need to hack Flutter's painting logic, such that it takes in your own BendCanvas instead of the original canvas. This is a universal solution, and it is much more efficient (less code) if you plan to have a lot of bend UI; but if only on bend TabBar, maybe use the first approach.
As for the bend text
In the two approaches above, we have mainly described how you draw the bended rectangle (i.e. draw an arbitrary shaped widget). As for bending text, see: https://github.com/flutter/flutter/issues/16477 , which is still an open issue.
Remarks
It is not possible using transformations. As explained in the comments, you already see Transform does not work - it is affine or perspective, which, by definition, will not bend. Then what about other transforms? After some research there seems to be none. Then, what about looking under the scene. We know Flutter uses Skia under it to draw the UI with high performance, then let us search through Skia. However, it does not provide any transformations like bending. So there seems no use.
P.S. I am not that high reputation in Flutter tag, but I did answer >100 Flutter questions (including some dig-into-source-code style ones), and have developed >100k lines of Flutter code in the production app.

Shrink text horizontally if width exceeds container size with Unity2D

So, I am trying to use Unity2D to create a TCG/CCG video game, and I seem to have hit a light bump: I cannot seem to efficiently resize horizontally text that ends up being larger than its container. (Example: Text has a width of 200, I want to fit it in 170). I mean, Unity did have a "fixing" with the option "Best Fit", but it didn't quite work as well as it should have, instead changing the font size to better fit it (Which is not the expected result.)
Now, I know that I could just find the width of a text, check if it overflows, and then apply simple math to scale it on the width side. That's something I'm currently trying to put into the code: But! I am looking for something I would have overlooked within Unity. Something that would do it faster, without me having to hard code it.
Now, what I have tried thus far (to avoid repeat of those offers):
Best Fit (actually changed the font size, which didn't fit my needs)
Both "Horizontal Overflow" settings
Content Size Fitter (Additionally, I seem to not be able to GetComponent<> that one.)
If you know of any trick I should probably know, feel free to let me know: It'd help my coding a lot.
Thanks in advance!
TextMesh Pro is a free Unity Asset that has support for Auto-Sizing and fitting text in specified areas, both as text floating in 3D Space, and as UI Text. Upon creation of a TextMesh Pro object, there is a setting called "Auto-Size" which is what you're looking for.
Details on how Auto-Size works can be found here.

iphone - How to implement the effect of "float" for image, just like in CSS style

In HTML, with CSS, one can do "float" for images, just like this
the image is surrounded by text.
How can I do it WITHOUT UIWebView?
I can't use UIWebview, because
UIWebView has a slight lag after you loadHTML. Its content doesn't show immediately, not like UILabel or UIImage
The image is async loaded, so I need a white space holder there with UIActivityView spinning
Is that possible I just use a UIImageView & UILabel to do float?
Thanks
The "easy" way is probably to use two labels and an image. If your text/images are static, then you can split the text at the right place beforehand. If not, you'll have to do some text size measurements; see UIStringDrawing.h. Figuring out where all the line breaks should be is non-trivial.
The "hard" way is to create your own subclass of UIView with text and image properties and have it do all the string/image layout and drawing. It's not actually that much harder than figuring out where the line breaks should be dynamically.
The "harder" way is to use Core Text (iOS 3.2+); the Columnar Layout example in the Core Text Programming Guide should work, but also note that CTFramesetterCreateFrame() can take an arbitrary CGPath, so you can just pass it a path of the available area. This might actually be slightly easier than using UIKit string-sizing and trying to find out where all the line breaks are (you just need to write a lot of Core Text boilerplate instead).

Creating a custom text-drawing view

I am creating a syntax highlighter for the iPhone and in order to display text with multiple formats, I have sub-classed UIView and modified the drawRect: method so that each line is displayed with the proper syntax highlighting (highlighting is done earlier with RegEx, text is drawn with CGContextShowTextAtPoint() one line at a time). Everything works ok, I store each line of text as an NSString in an NSMutableArray, I handle the keyboard through a hidden UITextField and its delegate methods, the cursor is a blinking CALayer that can be moved around with touches and I have a custom scroll view that handles scrolling. However, I have two problems that I can't seem to wrap my head around:
Word wrap, right now the text just keeps going off the left end of the screen. To keep things fast I only redraw the portions of the view that have changed (usually just the line being edited, but sometimes the lines below as well e.g. if you press return halfway through the document) with setNeedsDisplayInRect:. This makes word wrap complicated because then you have to draw more than one line on the screen, even though it still is only one object in the array.
UIViews have a maximum content size of 1024x1024 which equates to about 64 lines. I need the ability to display more than that. I am thinking about using multiple CALayers one after another, but I am having trouble drawing content to the layers (using drawLayer:inContext: and drawInContext:).
So my questions are:
Does anyone have any, even general, suggestions about how to accomplish either of these two points. Or,
Has someone already written a custom text-drawing view that handles these things that I could use instead.
Thanks,
Kyle
EDIT: The scrolling problem is pretty much solved, however I am still having trouble with word-wrap. My trouble is that everything is done by line: the view updates one line at a time, the text is stored as an array of lines, the highlighter highlights one line at a time, etc. and having a single index in the array (one line of text) take up multiple lines on the screen raises some problems, for example, I had to implement my own movable cursor and when you move the cursor it needs to be able to turn a display line (found by dividing touch.x by the line height) into a text line (an index in the array). Any ideas?
You should first spend some quality time understanding how this problem was solved on Mac:
http://developer.apple.com/documentation/Cocoa/Conceptual/TextArchitecture/Tasks/AssembleSysByHand.html
http://developer.apple.com/documentation/Cocoa/Conceptual/TextLayout/TextLayout.html
In particular, you should become familiar with line fragment generation, which is the problem you're trying to solve for word-wrap, and you should understand glyph generation in order to do rich text well. You don't need to implement all of the flexibility of NSTypesetter or NSLayoutManager of course, but the text system on Mac is incredibly powerful, and you should learn from its example. Implementing something similar to NSAttributedString for iPhone may be valuable to you and improve your performance.
Unless you're moving things around a lot (for which this would best work in a UIScrollView), I don't think you should need to use CALayers here. That seems overkill for the problem, and may actually adversely impact the optimizations already provided by UIScrollView. If you're seeing performance problems, first make sure you're not doing redundant calculations within your drawRect:.
Check out TTStyledText in Three20 library. Not sure how well it matches your goals, but might serve you as an example. (The library itself is a bit bloated, but is a wonderful source to look at.)
It may be best to draw your text within a CATiledLayer hosted within your UIView, in order to get around the 1024x1024 texture size limit (which appears to actually be 2048x2048 on all existing devices). For an example of text drawing within a CALayer, I'd refer you to the CPTextLayer class within the Core Plot framework. This layer (which inherits from the CPLayer class within that same framework) does cross-platform (Mac and iPhone) text rendering in a CALayer. You might be able to extend it to work as a CATiledLayer for longer text blocks.
One thing to be aware of is that platform-specific drawAtPoint: methods are used in this layer, instead of the CGContextShowTextAtPoint() function you are using. The reason for this is that CGContextShowTextAtPoint() only works on ASCII text, meaning that you can't do Unicode text rendering with it. There is an example of using CGContextShowTextAtPoint() to draw text, within a #define'd out portion at the bottom of the renderAsVectorInContext: method.

How are these two iPhone UI pieces accomplished?

This might be trivial for some of you, but I have two screenshots from the Lose It! app in which I'm curious how two different screens were put together.
The first:
That middle graph which shows the statistics chart. Is that a custom image being drawn on top of with Core Graphics / Quartz to achieve the desired numbers? Is the yellow line that's being dynamically allocated all the work of Quartz?
And second:
This one might be a bit easier, but the whole bar which looks like a native UIKit widget, which contains [Budget, Food, Exercise, Net, Under]. There appears to be a drop shadow above it. Are they doing a drop shadow on the UINavigationBar? Is the menu below it just a UIImage that a designer was able to craft to look like the UINavigationBar?
If there's a blog out there which teaches UI tricks such as these, I'd love to read more.
1) Yes, it's likely a view that uses the chart as a background and then uses core graphics to render the line,
2) This could be a single view divided into four sections. Each section has two lines of text drawn with different colors. It's possible that each section may be a view that encapsulates this behavior.
I'm not aware of any blog that teaches these "tricks". It's really a case of understanding what functionality is available and then using it creatively to develop your UI.
For example we know it's possible to;
Draw images at different sizes/positions.
Draw text in different fonts, sizes, colors, alignment
Draw primitives
Really, when you have those you can create pretty much anything.
I think there's an SDK sample that demonstrates using custom views to create a fancy timezone style applications. That might be one worth checking out.
Update: found it, it's here.