Get All Available Characters from a Font

Get all available characters from a font

For each UIFont, you have to get characterSet of that font. For example, I take first UIFont.

let firsttFont = UIFont.familyNames.first

let first = UIFont(name: firsttFont!, size: 14)
let fontDescriptor = first!.fontDescriptor
let characterSet : NSCharacterSet = fontDescriptor.object(forKey: UIFontDescriptorCharacterSetAttribute) as! NSCharacterSet

Then, use this extension to get all characters of that NSCharacterSet:

extension NSCharacterSet {
var characters:[String] {
var chars = [String]()
for plane:UInt8 in 0...16 {
if self.hasMemberInPlane(plane) {
let p0 = UInt32(plane) << 16
let p1 = (UInt32(plane) + 1) << 16
for c:UTF32Char in p0..<p1 {
if self.longCharacterIsMember(c) {
var c1 = c.littleEndian
let s = NSString(bytes: &c1, length: 4, encoding: String.Encoding.utf32LittleEndian.rawValue)!
chars.append(String(s))
}
}
}
}
return chars
}
}

(Ref: NSArray from NSCharacterset)

So, at last, just call characterSet.characters to get all characters (in String)

How to get all characters of the font with CTFontCopyCharacterSet() in Swift?

CFCharacterSet is toll-free bridged with the Cocoa Foundation counterpart NSCharacterSet, and can be bridged to the corresponding Swift value type CharacterSet:

let charset = CTFontCopyCharacterSet(ctFont) as CharacterSet

Then the approach from NSArray from NSCharacterSet can be used to enumerate all Unicode scalar values of that character set (including non-BMP points, i.e. Unicode scalar values greater than U+FFFF).

The CTFontGetGlyphsForCharacters() expects non-BMP characters as surrogate pair, i.e. as an array of UTF-16 code units.

Putting it together, the function would look like this:

func createUnicodeFontMap(ctFont: CTFont) ->  [CGGlyph : UnicodeScalar] {

let charset = CTFontCopyCharacterSet(ctFont) as CharacterSet

var glyphToUnicode = [CGGlyph : UnicodeScalar]() // Start with empty map.

// Enumerate all Unicode scalar values from the character set:
for plane: UInt8 in 0...16 where charset.hasMember(inPlane: plane) {
for unicode in UTF32Char(plane) << 16 ..< UTF32Char(plane + 1) << 16 {
if let uniChar = UnicodeScalar(unicode), charset.contains(uniChar) {

// Get glyph for this `uniChar` ...
let utf16 = Array(uniChar.utf16)
var glyphs = [CGGlyph](repeating: 0, count: utf16.count)
if CTFontGetGlyphsForCharacters(ctFont, utf16, &glyphs, utf16.count) {
// ... and add it to the map.
glyphToUnicode[glyphs[0]] = uniChar
}
}
}
}

return glyphToUnicode
}

Finding out what characters a given font supports

Here is a method using the fontTools Python library (which you can install with something like pip install fonttools):

#!/usr/bin/env python
from itertools import chain
import sys

from fontTools.ttLib import TTFont
from fontTools.unicode import Unicode

with TTFont(
sys.argv[1], 0, allowVID=0, ignoreDecompileErrors=True, fontNumber=-1
) as ttf:
chars = chain.from_iterable(
[y + (Unicode[y[0]],) for y in x.cmap.items()] for x in ttf["cmap"].tables
)
if len(sys.argv) == 2: # print all code points
for c in chars:
print(c)
elif len(sys.argv) >= 3: # search code points / characters
code_points = {c[0] for c in chars}
for i in sys.argv[2:]:
code_point = int(i) # search code point
#code_point = ord(i) # search character
print(Unicode[code_point])
print(code_point in code_points)

The script takes as arguments the font path and optionally code points / characters to search for:

$ python checkfont.py /usr/share/fonts/**/DejaVuSans.ttf
(32, 'space', 'SPACE')
(33, 'exclam', 'EXCLAMATION MARK')
(34, 'quotedbl', 'QUOTATION MARK')


$ python checkfont.py /usr/share/fonts/**/DejaVuSans.ttf 65 12622 # a ㅎ
LATIN CAPITAL LETTER A
True
HANGUL LETTER HIEUH
False

c# get all characters of a font as array or list

Please check the following code by Jawahar Suresh Babu in CodeProject. I believe it does what you want.

Character Map in WPF

http://www.codeproject.com/Articles/396811/Character-Map-in-WPF

To get the character escaped code, you can change the Select event handler method in the code above as follows:

    private void Select(object sender, RoutedEventArgs e)
{
if (currentindex != -1)
{
text.BeginChange();
if (text.Selection.Text != string.Empty)
{
text.Selection.Text = string.Empty;
}

var ch = new Run(((SymbolView) canvas.Children[currentindex]).charcter.Text)
{
FontFamily = fonts.SelectedItem as FontFamily
};

text.CaretPosition.Paragraph.Inlines.Add(ch);

text.EndChange();

// Displays escaped char code
MessageBox.Show(string.Format("&#x{0:X4}", (int) ch.Text[0]));
}
}

EDIT: Included change to get the character escaped code.



Related Topics



Leave a reply



Submit