背景
画像の代わりにフォントを使用に書いた通り、僕はベクター画像データとしてフォントを多用しています。フォントを使う場合に厄介なのが、文字(NSString)と、フォント(UIFont)を組み合わせないと適切なアイコンにならないことです。
アイコンは様々な種類を使うので、シンプルにアイコンを定義する方法が欲しくなりました。
文字+フォント=?
NSString + UIFontのテーブルを作るのはいけてません。。。そこで思いついたのが、Unicodeのコードポイント(32bit)を使う方法です。
基本的に「普通の1文字」は、32bit整数の「1コードポイント」で表現できます。そして、コードポイントは下位21ビットしか使用していないので、使われていない上位ビットにフォント情報を入れることができます。
この方法なら32bit整数で文字+フォントが表現できるので、普通にenumとしてアイコンが定義できます。
あとは、このenumからNSAttributedStringや、UIImageを生成すれば良い訳です。
下記のように一度enumを定義すれば、あとはこのenumだけで一意にアイコンを決めることが出来ます。
typedef enum PPIconFontType : uint32_t{
PPIconFontType_SS_PIKA = 1 << 24,
//フォントも本当は数種類
}PPIconFontType;
typedef enum PPIconCodePoint : uint32_t{
// SS-PIKA
PPIconCodePoint_PIKA_CURSOR = PPIconFontType_SS_PIKA | 0xE001,
PPIconCodePoint_PIKA_CROSSHAIR = PPIconFontType_SS_PIKA | 0x2316,
PPIconCodePoint_PIKA_SEARCH = PPIconFontType_SS_PIKA | 0x1F50E,
//以下定義が続く...
Unicode Code PointからNSStringへの変換
32bitのコードポイントを16bitのunicharで表現すると1文字か、2文字になります。これは扱いにくいので、僕はNSStringに変換して使用しています。言うまでもないですが、フォント情報はマスクしてから処理する必要があります。
//
// NSString+BTKUnicode.h
// BTKCommons
//
// Created by Tomohisa Ota on 3/5/14.
//
//
#import <Foundation/Foundation.h>
@interface NSString (BTKUnicode)
+ (NSString*) btkStringWithCodePoint : (int32_t) codePoint;
@end
//
// NSString+BTKUnicode.m
// BTKCommons
//
// Created by Tomohisa Ota on 3/5/14.
//
//
#import "NSString+BTKUnicode.h"
@implementation NSString (BTKUnicode)
+ (NSString*) btkStringWithCodePoint : (int32_t)codePoint;
{
unichar characters[2];
NSUInteger length;
if (codePoint <= 0xD7FF || (0xE000 <= codePoint && codePoint <= 0xFFFF) ) {
characters[0] = codePoint;
length = 1;
}
else if (0x10000 <= codePoint && codePoint <= 0x10ffff ) {
codePoint -= 0x10000;
characters[0] = 0xD800 + (codePoint >> 10);
characters[1] = 0xDC00 + (codePoint & 0x3ff);
length = 2;
}
else {
return nil;
}
return [NSString stringWithCharacters:characters length:length];
}
@end