Getting Font Size of NSAttributed string - objective-c

I'm trying to get the font size of an NSAttributedString, however, I'm having trouble doing this.
How do you get the font size of an NSAttributedString in objective-c?

An attributed string does not have "a font size". The used font is an attribute, which can vary over the String. Look at your Q: There are two different fonts in one paragraph. (One for the usual text and one for the keywords.)
Therefore you can only ask for the existing attributes (including font) at a specific location. I. e. - attributesAtIndex:effectiveRange: does this job for you. The attribute key for the font is NSFontAttributeName. If yo do not find this key in the attributes dictionary, it is Helvetica(Neue), 12 pt.

Related

Why is it so hard to convert PDF to plain text?

I needed to convert some PDF back to text. I tried many soft and online tools and result was always mediocre.
Why is it so difficult technically speaking ?
Let's not assume you are talking about PDFs which merely wrap some bitmap image because it should be clear that in that case you can only resort to OCR with all its restrictions.
Let's instead assume that text is drawn in the PDF at hand.
What is drawn on a PDF page is determined by a sequence of instructions in the content stream of that page. "Text is drawn" on a page means that among those instructions there are some setting the font to use by the instructions to come, some setting the text position and direction to use by the instructions to come, and some actually drawing text given by "string arguments".
Text extraction is the task of taking the sequence of instructions from a content stream and instead of drawing the text as indicated by the font and position setting instructions, to export it in a sensible order using a standard encoding, usually the encoding of the character type of the used programming language / platform.
The first problem is to understand the encoding of the string arguments of those text drawing instructions:
each font can have its own encoding; to extract the text one cannot simply ignore everything but the instructions drawing text and concatenate their string contents, you always have to take the current font into account (some extremely simple text extractors ignore this and, therefore, fail pretty often to return something sensible);
there are a large number of predefined encodings, some reminding of encodings you know, e.g. WinAnsiEncoding, many you likely don't know, e.g. Add-RKSJ-H; these encodings may use a constant number of bytes per glyph or they may be mixed-multibyte; so a text extractor must support very many encodings to start with;
encodings also may be completely ad-hoc and arbitrary; in particular in case of embedded subset fonts one often sees ad-hoc encodings generated by dealing out character codes from some starting value whenever one is needed; i.e. the first glyph in a given font used on a page is given the starting value as code, the next, different glyph is given the starting value plus one, the next, different one the starting value plus two, etc; "Hello World" and a starting value of 48 (ASCII value of '0') would result in "01223453627"; these fonts may contain a mapping to Unicode but they are not required to.
The next problem is to make sense out of the order of the strings:
the string drawing instructions may occur in an arbitrary order, e.g "Hello" might be drawn "lo" first, then after moving back "el", then after again moving back "H"; to extract the text one cannot ignore text positioning instructions and simply concatenate text strings, you always have to take the current position into account (some simple text extractors ignore this and, therefore, can fail to return something sensible);
multi-columnar text may present a difficulty, text may be drawn line by line, e.g. first the text of the top line of the first column, then the top line of the second column, then the second line of the first column, then the second line of the second column, etc.; there need not be any hints in the PDF that the text is multi-columnar.
Another problem is to recognize formatting or styling artifacts:
spaces between words need not be created by drawing a space glyph, it may also be done by text position changing instructions; text extractors not trying to recognize gaps created by text positioning instructions may return a result without spaces; on the other hand the same technique can be used to draw adjacent glyphs at an optimal distance, aka kerning; text extractors trying to recognize gaps created by text positioning instructions may falsely return spaces where there should be none;
sometimes selected words are printed s p a c e d o u t for extra emphasis; in the extracted text these gaps might be presented as space characters which automatic postprocessing of the text may see as word separators;
usually for bold text one uses a different, bold font program; if that is not at hand, people sometimes get creative and emulate bold by printing the same text twice with a minute offset; with a slightly larger offset (or a different transformation) and a different color a shadow effect can be emulated; if the text extractor does not try to recognize this, you end up having some duplicate characters in the output.
More problems arise due to incomplete or wrong extra information:
ToUnicode maps of fonts (optional maps from character code to Unicode) may be incomplete or contain errors; there e.g. are many questions here on stack overflow dealing with incorrect ToUnicode maps for Indian writings; the text extraction results reflect these errors;
there even are PDFs with contradictory information, e.g. with an error in the ToUnicode map but the correct information in an ActualText entry; this is used by some PDF creators to allow correct copy&paste from some programs (preferring an ActualText entry in such a situation) while injecting errors in the output of other programs (preferring ToUnicode information then).
Yet another problem arises if you expect the text extractor to extract only text eventually visible in the page:
text may be drawn outside the current clipping area or outside the visible page area; text extractors need to keep these in mind;
text may be drawn using the rendering mode "invisible"; text extractors have to keep an eye on the rendering mode;
text may be drawn using the same color as the background; to recognize this, a text extractor can not only look at the current instruction and a few graphics state details, it has to take into account anything drawn beforehand in the location of the text;
text may be drawn as a clip path; to recognize whether this text is visible in the end, a text extractor must keep track of what is drawn in the text area as long as the clip path is active;
text may be covered by something else later; a text extractor must drop recognized text in such a case; but depending on blend modes and transparency settings these coverings might or might not allow the text to shine through; thus, for a correct result the text extractor must for each glyph keep track of the color its drawn with, the color of the backdrop, and what all those spiffy effects do with those colors later on; and of course, both glyph color and backdrop color can be interesting, e.g. some shading colors; and the color spaces involved may differ, requiring one to convert back and forth between color spaces; and so on.
Furthermore, text may be drawn where text extractors usually don't look:
some tools hide text from text extraction by putting it into a pattern and filling the page area with that pattern;
similarly there are type 3 fonts; each character in a type 3 font is represented by its own content stream; thus, a tool can draw all text in the content stream of a single type 3 font glyph and then draw that glyph on the page.
...
You surely have meanwhile gotten an idea why text extraction results can be less than optimal. And be assured, the list above is not complete, there still are more complications for text extraction.

Do PDF files generally use "correct" character codes for font glyphs?

Say I have a PDF file that contains one or more embedded fonts. Here's my understanding of how a single character of text is rendered:
First, determine which font the character uses.
Use the font's "cmap," embedded in the PDF, to determine the font's glyph name for the given character. For example, the character '&' in PDF text might map to a glyph that the font internally calls 'ampersand'.
Use the font's "glyf" table to determine the bounding box / drawing instructions for the glyph name.
Here's my question: is a PDF cmap generally consistent? Put another way, if I encounter the character "&" in a PDF, can I be assured that the cmap will always map "&" to the ampersand glyph? Or does some PDF-generation software create its own arbitrary mapping between character codes and glyph names (which would be rather evil and possibly break in-PDF searching and text selection)?
Of course I realize it's possible for the cmap to use an unintuitive mapping -- I guess I'm asking, does this actually happen in the Real World?
My specific use-case is in the world of music fonts. I'm analyzing characters in a PDF to determine which music glyph each one represents (e.g., treble clef, notehead, etc.). I want to know how confident I can be that the combination of font name and character code will always result in the same glyph. For example, if I know the font name is "Opus" and the glyph is "#", can I assume that will always be mapped to the treble clef glyph? Or do I have to analyze the glyph's metrics to make sure it's actually a treble clef?
It differs from one PDF creator to another.
A fairly common method (alas!) is "order encountered", where the first character in the text stream gets mapped to \001, the next to \002 and so on. So the text "Hello" would be encoded as \001\002\003\003\004.
I want to know how confident I can be that the combination of font name and character code will always result in the same glyph.
In a single PDF document, if the same font object is used in different contexts, it will be true -- the mapping is defined inside the font object. If you encounter another font object that uses the same font but it points to another font stream (i.e., the font subset is embedded twice), then it may not be true. Each subset may have an encoding of its own.
Only if the font object contains a /ToUnicode mapping, you can be confident that values map to the correct characters.

Does CGGlyph depend on the font size?

CGGlyph is a typedef for unsigned short.
Every font can (or at least could) specify a different CGGlyph value for the same character. But within the same font, will the value of CGGlyph depend on the font size?
Basically I want to show the same character with different font sizes. Can I set the font size with CGContextSetFontSize() and reuse the CGGlyph value?
CGGlyph holds the index of a glyph inside a font. This is because inside a font, the order of glyphs (individual character designs) can be anything -- in particular, unrelated to the character code it represents.
That is, the order of characters in fonts is unrelated to any encoding. The character code of an "A" is 65 (in ASCII) but that does not mean "the 65th character in a font is the glyph "A". For Unicode it's nearly impossible to make it work that way: the Unicode of a curly left double quote, for example, is U+201C, or 8220 in decimal.
So there are one or more tables inside each font that translate between the logical index of a glyph (simply counting characters as they appear in the file itself) and one or more encodings. (Where an encoding is a predefined set, such as "Unicode", "MacRoman", or "Windows Latin1".)
This has several advantages: first of all, the characters in a font file don't need to appear in any particular order. The font designer can add as many encodings to the file as needed. Also, it's perfectly possible for a font to contain glyphs that appear in no encoding at all (think of rare ligatures).
All said and done:
Every font can (or at least could) specify a different CGGlyph value for the same character.
Neither can nor should. Since CGGlyph is an index value, it simply always starts at 0 and the last valid valid is the number of characters in the font, minus 1.
The index of a glyph is not determined by its size, which is set at a very different level. So indeed you can re-use the value for different sizes.
But, noteworthy: the index of a particular character is uniquely tied to one font only. The ordering of individual characters inside each font should be considered unique (if only because one font may contain more or less charcaters than another).
See CGGlyph toUniChar for a related discussion.

How should I determine the height of an NSAttributedString for a fixed width

I have an attributed string with "Date: Heading - Description."
The Date, Heading, and Description text values are dynamically generated, and all have different attributed fonts which I've assigned to the appropriate substring.
How should I determine the total width, and then consequentially the determine the height for a given width which this content should fill?
I've found this SO post but it is from 2010 and a more current solution seems like it would be available.
Additionally, how should the width of an attributed string with content changing text style by substring be determined? The iOS7 sizeWithAttributes method seems to apply the attributes for the entire string.
This is an attributed string, so the place to look is the NSAttributedString documentation. In particular:
https://developer.apple.com/library/ios/documentation/uikit/reference/NSAttributedString_UIKit_Additions/Reference/Reference.html#//apple_ref/occ/instm/NSAttributedString/boundingRectWithSize:options:context:
As to your last paragraph: simply make this a mutable attributed string, change the styles as desired, and proceed as above.

Altering an embedded TrueType font so it will be usable by Windows GDI

I am trying to render PDF content to a GDI device context (a 24bit bitmap to be exact). Parsing the PDF stream into PDF objects and rendering the PDF commands from the content dictionary works well, including font rendering.
Embedded fonts are decompressed from their FontFile streams and "loaded" using AddFontMemResourceEx. Now some embedded fonts remove some TrueType tables that are needed by GDI, like the 'name' table. Because of this, I tried to modify the font by parsing the TrueType subset font into it's tables and modify those tables that have data missing / missing tables are regenerated with as correct information as possible.
I use the Microsoft Font Validator tool to see how "correct" the generated font is. I still get a few errors, like for the maxp table the max values are usually too large (it is a subset) or the xAvgCharWidth field does not equal the calculated value of the 'OS/2' table is not correct but this does not stop other embedded fonts to be useable. The fonts embedded using PDFCreator are the ones that are problematic.
Questions:
How can I determine what I need to
change to the font file in order for
GDI to be able to use it?
Are there any other font validation
tools that might give me insight
into what is still wrong with the
fontfile?
If needed: I can make an original fontfile and an altered fontfile available for download somewhere.
What modifications are made so far:
Make sure there is a 'head', 'hhea', 'maxp' and 'OS/2' section.
If we have a symbol font, clear out Panose and Unicode fields in the 'OS/2' section
Fill in correct values for WInAscent/Desc and TypoAsc/Desc if they we're zero.
Fill in acceptable values for super/subscript/underline positions and sizes.
Scan all glyphs that are left en fill in X/Y min/max values in head.
Rebuild the name section with information from the PDF file it came from.
Almost a year late, but I found the answer:
The font kind (symbol or not) should be the same for the 'cmap' table and the 'name' table. So if the cmap has a 3,0,4 cmap (MS, symbol, segment delta coding) and the name table contains 3,1,$0409 (MS, Unicode, enUS) entries, the font will not load.
It looks like the presence of a 'symbol cmap' determines if the font is considered a symbol font by Windows; flags in 'OS/2' don't seem to matter.
So if a font seems correct using 'Microsoft Font Validator', check if the symbol/unicode fields line up in the 'cmap' and 'name' tables.
With AddMemoryFont in GDI+ you can check it's Status for any errors in the memory font, like NotTrueTypeFont for example.
One option for GDI may be to try to load the embedded font into a document/form yourself with TTLoadEmbeddedFont and then check any errors returned from the error messages. The only functions that supply more information than this one are CreateFontPackage/MergeFontPackage, and their error codes, but I do fail to see how they can be used in your situation.
Barring all this, have you had a chance to review PDFCreator's source code (assuming you're using the open source one as opposed to the commercial one)?