How do you change the letter-spacing/tracking in core text? - cocoa

This could probably also be asked as "Is kCTKernAttributeName a misnomer?"
I need to change the letter spacing/tracking of some text in iOS. (The font I'm using is a little too tight at small sizes.) There are core graphics routines that will change character spacing, but those routines don't handle Unicode. There are other core graphics routines that are defined in terms of glyphs but those seem like a world of hurt, among other things, not having the safety net of reverting back to system fonts for glyphs that don't exist in my font.
So core text seems like the way to do this and core text supports kCTKernAttributeName on CFAttributedString. I think this will do what I want, though this really isn't kerning since kerning is a generally a character-pair attribute and this (appears to be, from the docs) just a uniform adjustment to the glyph advance for all glyphs, i.e., tracking.
If anyone knows before I go down the rather painful path of converting to the core text API ...

kCTKernAttribute name should do what you want. Setting it over a range of text adjusts the inter-glyph spacing consistently, irrespective of the specific glyphs.
I think part of the problem is that kerning seems to have been a virtual synonym of tracking (it's still just "adjust the spacing between (letters or characters) in a piece of text to be printed" in the dictionary that comes with OS X), and is now adopting just the meaning of pair kerning because of the redundancy. Probably an etymologist would be better placed to comment on that side of things...

Related

transform a svg into a copy/paste-able emoticon like this one 🦄

Not sure if SO is the best place for this question, but don't know where else to ask.
Is there any way to transform a svg like this one for ex: (https://svgsilh.com/image/1775543.html) into something that i can use inside an editor with copy/paste like this one? 🦄
No, because the unicorn emoticon is one example of a character. And just as with letters, digits, and punctuation, the appearance of emoticons and other plain-text symbols is decided by fonts.
LSerni wrote the following:
The reason you can "copy and paste" that icon is that the icon already has a UTF-8 code and your editor is UTF-8 aware. And this is why the same emoticon is slightly different between Apple, Android and so on: it's because it's always code XYZ, but code XYZ is rendered with different icons on different platforms.
But that's not entirely correct. The difference in rendering lies more in the font than in the operating system that displays emoticons. Unless the font supplies its own version of a symbol, that symbol will usually be supplied by the font specified by default by the operating system, and different operating systems supply different symbol fonts.

Low Level Text Output

I have not done any MACOS programming in several years. However, I now need to test out some algorithms for formatting text as paragraphs. For these tests, I need to be able to display characters with absolute position control.
These tests need to determine where line breaks are to go within a paragraph and the amount of work spacing, while taking into account hyphenation, ligatures, page breaks, kerning and the like.
When I last did such things, I was using the text functions of the CGContext class. Upon returning from my hiatus, I find all of these function are marked "deprecated" in the documentation—which conveniently leaves out what the current acceptable replacement is.
What is the current, approved process for drawing single glyphs on Mac OS?
Functions that deal with formatting strings would defeat the purpose of the academic experiment here.

Is there a way to query CTRun if it includes emoji characters?

I'm doing color transformations on glyphs rendered with CTFontDrawGlyphs, but I do not want to do those transformations to the emoji glyphs, since they have already a meaningful color information.
So, when I have a CTRun of glyphs, can I detect if it is actually emoji/color font?
I can do a string compare to the postscript name with "AppleColorEmoji", but seems awfully wasteful to do all the time, and somewhat hacky if there ever happens to be another font with the same features.
Ah, I can get the symbolic traits with CTFontGetSymbolicTraits, and check for kCTFontTraitColorGlyphs (or kCTFontColorGlyphsTrait), which, while undocumented, is available in the public headers.

Why does Core Text return Myriad Pro Semibold when requesting a bold version of Myriad Pro

I have the common Adobe Myriad Pro fonts installed. These include Myriad Pro Regular, Myriad Pro Bold and Myriad Pro Semibold. Assume that I have a CTFontRef baseFont that points to Myriad Pro Regular, and that the font size I desire is size. I run the following code:
CTFontRef boldFont = CTFontCreateCopyWithSymbolicTraits(baseFont, size, NULL, kCTFontBoldTrait, kCTFontBoldTrait);
The returned font is Myriad Pro Semibold, not Myriad Pro Bold.
Is there a way of coercing this to return Myriad Pro Bold instead, other than requesting the named style 'Bold'? I wanted to keep this code entirely generic without hard-wiring style names.
I have tried this in various permutations, including passing the bold trait as part of an attribute dictionary when I initially create my font, avoiding the two-step process described here, but it still returns the semibold font in preference to the normal bold. I've also poked around the fonts themselves a little. The full bold font has a weight of 700 in its <OS/2> table, and the semibold font has a weight of 600. The PANOSE weights correspond with this. However, the macStyle fields in the <head> table of the semibold and bold fonts both have the bold flag set, so presumably this is what Core Text is using. But is there any way to make it more discriminating?
Based on a reading of the documentation, backed up by some knowledge of font handling in general but not Core Text specifically, I'd say it may be possible, but it's not straightforward.
The CTFontCreateCopyWithSymbolicTraits() documentation specifies that the symTraitValue and symTraitMask parameters have type CTFontSymbolicTraits. The CTFontDescriptor() documentation defines that "Bold" value that you are using as
kCTFontBoldTrait = (1 << 1)
So this is clearly a boolean trait. However, as you've seen, font weight is a spectrum, not a boolean trait, even though decades of "bold" buttons in word processor UIs have presented it as a boolean trait. CTFontCreateCopyWithSymbolicTraits() doesn't have the expressive power you need.
One other approach which might work is to try calling CTFontDescriptorCreateMatchingFontDescriptors(). You pass this function a CTFontDescriptorRef to an initial font, and a CFSetRef with attributes which must be present. This function returns an array of font descriptors, all of which match the attributes you requested.
So, you could pass it a CTFontDescriptorRef for Myriad Pro Regular, and maybe a CFSetRef saying you want bold, and then look through every font descriptor in the returned array to find the one with the heaviest weight.
I haven't written this code, and my ignorance of Core Text means I may be missing something, but that seems like a plausible approach.
For the CTFontDescriptor you can specify an attribute kCTFontTraitsAttribute which should be an CFDictionaryRef where you can specify the kCTFontWeightTrait which takes a CFNumberRef that represents floating point between -1 and 1, giving you a spectrum of weights, 1 being the most bold variant, and 0 being the regular/medium.

Display of Asian characters (with Unicode): Difference in character spacing when presented in a RichEdit control compared with using ExtTextOut

This picture illustrates my predicament:
All of the characters appear to be the same size, but the space between them is different when presented in a RichEdit control compared with when I use ExtTextOut.
I would like to present the characters the same as in the RichEdit control (ideally), in order to preserve wrap positions.
Can anyone tell me:
a) Which is the more correct representation?
b) Why the RichEdit control displays the text with no gaps between the Asian Characters?
c) Is there any way to make ExtTextOut reproduce the behaviour of the RichEdit control when drawing these characters?
d) Would this be any different if I was working on an Asian version of Windows?
Perhaps I'm being optimistic, but if anyone has any hints to offer, I'd be very interested to hear.
In case it helps:
Here's my text:
快的棕色狐狸跳在懶惰狗1 2 3 4 5 6 7 8 9 0
apologies to Asian readers, this is merely for testing our Unicode implemetation and I don't even know what language the characters are taken from, let alone whether they mean anything
In order to view the effect by pasting these characters into a RichEdit control (eg. Wordpad), you may find you have to swipe them and set the font to 'Arial'.
The rich text that I obtain is:
{\rtf1\ansi\ansicpg1252\deff0\deflang2057{\fonttbl{\f0\fnil\fcharset0 Arial;}}{\colortbl ;\red0\green0\blue0;}\viewkind4\uc1\pard\sa200\sl276\slmult1\lang9\fs22\u24555?\u30340?\u26837?\u33394?\u29392?\u29432?\u36339?\u22312?\u25078?\u24816?\u29399?1 2 3 4 5 6 7 8 9 0\par\pard\'a3 $$ \'80\'80\cf1\lang2057\fs16\par}
It doesn't appear to contain a value for character 'pitch' which was my first thought.
I don't know the answer, but there are several things to suspect:
There are several versions of the rich edit control. Perhaps you're using an older one that doesn't have all the latest typographic improvements.
There are many styles and flags that affect the behavior of a rich editcontrol, so you might want to explore which ones are set and what they do. For example, look at EM_GETEDITSTYLE.
Many Asian fonts come in two versions on Windows. One is optimized for horizontal layout, and the other for vertical layout. That latter usually has the same name, but has # prepended to it. Perhaps you are using the wrong one in the rich edit control.
UPDATE: By messing around with Wordpad, I was able to reproduce the problem with the crowded text in the rich edit control.
Open a new document in Wordpad on Windows 7. Note that the selected font is Calibri.
Paste the sample text into the document.
Text appears correct, but Wordpad changed the font to SimSun.
Select the text and change the font back to Calibri or Arial.
The text will now be overcrowded, very similar to your example. Thus it appears the fundamental problem is with font linking and fallback. ExtTextOut is probably selecting an appropriate font for the script automatically. Your challenge is to figure out how to identify the right font for the script and set that font in the rich edit control.
This will only help with part of your problem, but there is a way to draw text to a DC that will look exactly the same as it does with RichEdit: what's called the windowless RichEdit control. It not exactly easy to use: I wrote a CodeProject article on it a few years back. I used this to solve the problem of a scrollable display of blocks of text, each one of which can be edited by clicking on it: the normal drawing is done with the windowless RichEdit, and the editing by showing a "real" RichEdit control on the top of it.
That would at least get you the text looking the same in both cases, though unfortunately both cases would show too little character spacing.
One further thought: if you could rely on Microsoft Office being installed, you could also try later versions of RichEdit that come with office. There's more about these on Murray Sargent's blog, as well as some interesting articles on font binding that might also help.
ExtTextOut allows you to specify the logical spacing between records. It has the parameter lpDx which is a const pointer to an array of values that indicate the distance between origins of adjacent character cells. The Microsoft API documentation notes that if you don't set it, then it sets it's own default spacing. I would have to say that's why ExtTextOut is working fine.
In particular, when you construct a EMR_EXTTEXTOUTW record in EMF, it populates an EMR_TEXT structure with this DX array - which looking at one of your comments, allowed the RichEdit to insert the EMF with the information contained in the record, whereby if you didn't set a font binding then the RTF record does some matching to work out what font to use.
In terms of the RichEdit control, the following article might be useful:
Use Font Binding in a Rich Edit Control
After character sets are assigned, Rich Edit scans the text around the
insertion point forward and backward to find the nearest fonts that
have been used for the character sets. If no font is found for a
character set, Rich Edit uses the font chosen by the client for that
character set. If the client hasn't specified a font for the character
set, Rich Edit uses the default font for that character set. If the
client wants some other font, the client can always change it, but
this approach will work most of the time. The current default font
choices are based on the following table. Note that the default fonts
are set per-process, and there are separate lists for UI usage and for
non-UI usage.
If you haven't set the characterset, then it further explains that it falls back to ANSI_CHARSET. However, it's most definitely a lot more complicated than that, as that blog article by Murray Sargent (a programmer at Microsoft) shows.

Resources