Core text exactly same as UITextView text format? - iphone

I'm trying to set up a CTFrame that exactly matches my UITextView's text format in iPad.
First of all, I converted UITextView's text to an attributed string. Then I set up a width and a height of drawing box in which Core Text will draw text.
I succeeded to draw text using Core Text, but UITextView and Core Text show slightly different results even though I used the same font and size.
Specifically, when I used [UIFont systemFontOfSize:21], each space in UITextView has one more pixel than Core Text's result.
It's okay for a short sentence or word, but if UITextView and Core Text have multiple lines, their result become very different. For example, UITextView performs word-wrapping for one word at the end of line, while Core Text keeps that word in the same line. If you see the attached picture, the start positions of the last word "paragraph" are already very different (8 pixel gap due to 8 space characters).
More badly, if I use different fonts such as a custom font added to my project, each character in UITextView has 1 pixel more.
I'm using Core Text to find the pixel-position of the current cursor in UITextView, so both of them should perfectly match each other, containing the same number of characters and words in each line.
Question: Is there a way to make Core Text object that perfectly matches UITextView's text format?
Thank you!
Here's a code how I set up attributed string. (I just followed Core Text Guide.)
CTFontRef font = CTFontCreateWithName((CFStringRef) [UIFont systemFontOfSize:21.0].fontName, 21.0, NULL);
CFMutableAttributedStringRef attrString2 = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (attrString2, CFRangeMake(0, 0), (CFStringRef) string);
CFAttributedStringSetAttribute(attrString2, CFRangeMake(0, [string length]),kCTFontAttributeName, font);
-
-
Here's a picture.

Your solution might work for a specific font at a specific point size, but you can't rely on it in general.
CoreText is simply not compatible with normal UILabels, UITextView:s or UIStringDrawing, so you can't mix them.
Either you have to use only CT functions for all string handling (including implementing custom input if that is what you need) or not use them at all.

Answer to myself.
I just found very simple solution! Using any font editor, you can just change the width of space character (ascii value 32); an original font for UITextView and a modified font for Core Text or vice versa. I used a freeware font editor FontForge. Though I still have to do some extreme-case tests such as writing Japanese characters and English alphabets in the same line and so on, now it becomes almost possible to find a pixel-position of a cursor/caret in UITextView.

Related

iText -- How do I identify a single font that can print all the characters in a string?

This is wrt iText 2.1.6.
I have a string containing characters from different languages, for which I'd like to pick a single font (among the registered fonts) that has glyphs for all these characters. I would like to avoid a situation where different substrings in the string are printed using different fonts, if I already have one font that can display all these glyphs.
If there's no such single font, I would still like to pick a minimal set of fonts that covers the characters in my string.
I'm aware of FontSelector, but it doesn't seem to try to find a minimal set of fonts for the given text. Correct? How do I do this?
iText 2.1.6 is obsolete. Please stop using it: http://itextpdf.com/salesfaq
I see two questions in one:
Is there a font that contains all characters for all languages?
Allow me to explain why this is impossible:
There are 1,114,112 code points in Unicode. Not all of these code points are used, but the possible number of different glyphs is huge.
A simple font only contains 256 characters (1 byte per font), a composite font uses CIDs from 0 to 65,535.
65,535 is much smaller that 1,114,112, which means that it is technically impossible to have a single font that contains all possible glyphs.
FontSelector doesn't find a minimal set of fonts!
FontSelector doesn't look for a minimal set of fonts. You have to tell FontSelector which fonts you want to use and in which order! Suppose that you have this code:
FontSelector selector = new FontSelector();
selector.addFont(font1);
selector.addFont(font2);
selector.addFont(font3);
In this case, FontSelector will first look at font1 for each specific glyph. If it's not there, it will look at font2, etc... Obviously font1, font2 and font3 will have different glyphs for the same character in common. For instance: a, a and a. Which glyph will be used depends on the order in which you added the font.
Bottom line:
Select a wide range of fonts that cover all the glyphs you need and add them to a FontSelector instance. Don't expect to find one single font that contains all the glyphs you need.

What does it mean for a CTLine to have "string access"?

I'm trying to solve a hairy problem with UILabel, and I've gotten most of it figured out, except for one thing: I'm having a challenge understanding what it means for a CTLine to have "string access".
The method that I'd like to use is CTLineGetOffsetForStringIndex. Here's a link to the documentation for the method.
Here's the part of the documentation that I don't understand (emphasis is mine):
The primary offset along the baseline for charIndex, or 0.0 if the
line does not support string access.
When I'm running this method, I'm getting 0.0 back, so I guess that means the line doesn't support string access - but what does that mean, exactly?
The statement "the line does not support string access" may be inferred as meaning that the line of text may not be treated as a sequence of characters that may be accessed by the index of each character.
This may open up a large discussion about visual characters versus non-visual characters, and glyphs versus characters. But to simplify the discussion, assume that a line of text may have one of the following states:
more than zero characters (characters which translate to either glyphs or whitespace within the same line) are present in the line of text in question
there are no characters in the line of text which occupy any "space"
Now to provide some rationale for this inference.
Apple's documentation provides a description of Text Kit, upon which UILabel is built:
The UIKit framework includes several classes whose purpose is to display text in an app’s user interface: UITextView, UITextField, and UILabel, as described in Displaying Text Content in iOS. Text views, created from the UITextView class, are meant to display large amounts of text. Underlying UITextView is a powerful layout engine called Text Kit. If you need to customize the layout process or you need to intervene in that behavior, you can use Text Kit. For smaller amounts of text and special needs requiring custom solutions, you can use alternative, lower-level technologies, as described in Lower Level Text-Handling Technologies.
Text Kit is a set of classes and protocols in the UIKit framework providing high-quality typographical services that enable apps to store, lay out, and display text with all the characteristics of fine typesetting, such as kerning, ligatures, line breaking, and justification. Text Kit is built on top of Core Text, so it provides the same speed and power. UITextView is fully integrated with Text Kit; it provides editing and display capabilities that enable users to input text, specify formatting attributes, and view the results. The other Text Kit classes provide text storage and layout capabilities. Figure 8-1 shows the position of Text Kit among other iOS text and graphics frameworks.
Figure 8-1 Text Kit Framework Position
Text Kit gives you complete control over text rendering in user interface elements. In addition to UITextView, UITextField and UILabel are built on top of Text Kit, and it seamlessly integrates with animations, UICollectionView and UITableView. Text Kit is designed with a fully extensible object-oriented architecture that supports subclassing, delegation, and a thorough set of notifications enabling deep customization.
The answer to the related question mentions several classes such as NSTextStorage, NSLayoutManager, and NSTextContainer.
Consider that the UILabel uses all the above classes to provide the end result of displaying text in the parent UIView, which the end user sees on the screen. A layout manager (an instance of NSLayoutManager) coordinates data flow between the text view, the text container, and the text storage, resulting in the display of characters in the view. The layout manager maps the characters to glyphs, and figures out which lines to use to lay out the glyphs. The layout manager also figures out how to display things like underline and strikethrough, which are not part of the glyphs.
Important to this discussion is the fact that the Layout Manager lays out lines of text. If that line of text is selectable, the user may select visible characters in the line. In this particular case, there is "string access" for the line.
A similar concept is the method posted in the solution to related question:
func boundingRect(forGlyphRange glyphRange: NSRange, in container: NSTextContainer) -> CGRect
Returns a single bounding rectangle (in container coordinates) enclosing all glyphs and other marks drawn in the given text container for the given glyph range, including glyphs that draw outside their line fragment rectangles and text attributes such as underlining.
Finally, the reference discussion for the function CTLineGetOffsetForStringIndex speaks about graphical offsets which are suitable for drawing custom carets. The carets may be used to show insertion points or text selection. The primary and secondary offsets may be thought of as beginning and end indices for a string -- a sequence of characters. If there is no sequence of characters for a given line, there can be no selected characters, no carets, no range of glyphs. Therefore no "string access".

store and fetch bold/italic font from sqlite database

I tried by make Excel file & import as a csv file in sqlite. But it shows me in normal font rather than bold or italic font.
In my app, I uses the sqlite database and fetches data from it. I want to display some text in italic font,How can i do that??
Does Sqlite supports Italic?
yOu should store data with rules, as in case html we store it as <b>topic/b><i>this is topic</i> i mean by adding proper tagging before save.
I am not share about ios or xcode how but you should add some extra information to text before saving the text.
When you read bold text, you are interpreting a "strong" meaning. This strong meaning can be emphasized in a number of different ways (for instance, all caps: BOLD). Your text shouldn't contain information about how the information is presented (style), but it SHOULD contain information about the meaning (structure). Keeping these two separate gives you more flexibility to change how the text is presented if, say, you wanted to change your website template or application design. You could choose to display strong text as bold, all caps, all caps and underlined, etc. on a whim.
I recommend some subset of HTML, as it is structural by nature and very widely used. In HTML, the bold tag exists (<b>; however, it is stylistic, so the <strong> tag is recommended to encode the strong meaning instead).
Databases don't support encoding; however, you can encode the text yourself before sticking it in the database. Here is an example of an HTML-encoded string:
<p><strong>An HTML-encoded string</strong> inside a paragraph.</p>
When you extract it, you could choose to represent the strong text as bold:
An HTML-encoded string inside a paragraph.
Or as CAPS:
AN HTML-ENCODED STRING inside a paragraph.
Or even italic caps:
AN HTML-ENCODED STRING inside a paragraph.
There are many other ways to encode structure, including Mark Down (I believe that's what StackOverflow uses).
where you want to display it? in some label , textfiled or some other? change font type there where you want to display it
For example if you want to display it in UILable
then change the font type of UILabel
[<lblname> setFont:[UIFont boldSystemFontOfSize:<whatever_you_want>]];
It's your bad logic to fetch bold text from database.
Enjoy Programming

Superscript, Subscript text with Core Text iPhone

Can anyone explain me, How to draw superscript and subscript alphabets with Core Text?
Thanks.
I noticed that this question is a bit old, I hope you still require assistance in this matter and that this post will help you.
you can use NSAttributedString (or its mutable counterpart NSMutableAttributedString) to assign different attributes (such as font, both name and size) to specific ranges of a single string.
Superscript and subscript are not natively supported by core text and to make them look good you might need to do quite a lot of work. Fortunately there is an open source project developed by Oliver Drobnik from cocoa genetics that allows you to easily convert HTML into NSAttributedString (or NSMutableAttributedString), feed it into a custom textview and show superscripts and subscripts (along with many other HTML and CSS) as they would appear in a UIWebview, but without the need to use a UIWebview. You can download the project from here.
While a lot of effort has been put into this project, there are two caveats:
The computations can be at times very performance intensive.
Not all HTML tags and CSS features are supported yet.
IF NSAttributedString is an acceptable solution you can create a superscript / subscript effect with NSAttributedString rather than Core Text. This is how I did it:
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:myString];
// Everything except the first character is rendered with the regular size / position
[str addAttribute:NSFontAttributeName
value:font
range:NSMakeRange(1, [amountString length]-1)]; // Everything except the first character is rendered with the regular size / position
// First character is 5/8 normal size
[str addAttribute:NSFontAttributeName
value:[UIFont fontWithName:initialFont.fontName
size:initialFont.pointSize/8*5]
range:NSMakeRange(0, 1)];
// Set the baseline offset to push the first character into a superscript position
[str addAttribute:#"NSBaselineOffset"
value:[NSNumber numberWithFloat:initialFont.pointSize*1/3]
range:NSMakeRange(0, 1)];
The key lines are the last two, which make the size of the super/sub script text smaller and change it's vertical position. It's worth noting that I'm using a string (#"NSBaselineOffset") instead of a defined attribute name constant (NSBaselineOffsetAttributeName). From what I was able to gather I believe that NSBaselineOffsetAttributeName is defined in the libraries for Mac but not for iOS (which I was developing for when I came up with this). As I result I used the name string itself rather than a constant for the attribute name.

How to make the 1st line in certain amount of text in a Label bold?

I have about 400 character length string with a heading called Details. In this 'Details' is to be bold and of fontsize 19. While all the remaining text starts in the next line and should be of fontSize 18 like the contents. How can I do all this by using a UILabel?
Plz help me...
You can't do it with a stock UILabel as of SDK 3.2. You can create an NSAttributedString that specifies particular styles (like bold) for particular parts of the string, but there isn't a simple way to actually render it. This is unlike In Max OS X, which has NSAttributedString(AppKitAdditions), which allows you to draw an attributed string in a single line of code. If you want to render it, you can, but you'll have to delve into one of the lower level APIs (such as Core Text).
You're probably much better off using two UILabels. Make the first one bold, and make the second one cover multiple lines.
Since UILabel does not support attributed strings, you have two options:
Subclass UILabel and override -drawRect:
Create 2 UILabels, one of which will display the heading, the other showing the rest of your text. You can choose to wrap the two labels into your own view if necessary.
You could use a UIWebView with an HTMLString of <strong>First part</strong> second part