fontina 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +42 -0
  5. data/fontina.gemspec +29 -0
  6. data/lib/fontina/fetcher.rb +34 -0
  7. data/lib/fontina/fetchers/http.rb +43 -0
  8. data/lib/fontina/fetchers/local_file_path.rb +15 -0
  9. data/lib/fontina/fetchers/local_file_uri.rb +21 -0
  10. data/lib/fontina/fetchers/preprocessor.rb +18 -0
  11. data/lib/fontina/format.rb +39 -0
  12. data/lib/fontina/formats/fon/constants.rb +12 -0
  13. data/lib/fontina/formats/fon/container.rb +24 -0
  14. data/lib/fontina/formats/fon/dos_header.rb +14 -0
  15. data/lib/fontina/formats/fon/ne_exported_name_table.rb +24 -0
  16. data/lib/fontina/formats/fon/ne_font_dir.rb +50 -0
  17. data/lib/fontina/formats/fon/ne_header.rb +25 -0
  18. data/lib/fontina/formats/fon/ne_resource.rb +14 -0
  19. data/lib/fontina/formats/fon/ne_resource_name_info.rb +18 -0
  20. data/lib/fontina/formats/fon/ne_resource_table.rb +12 -0
  21. data/lib/fontina/formats/fon/ne_resource_type_info.rb +21 -0
  22. data/lib/fontina/formats/fon/ne_vs_version_info.rb +70 -0
  23. data/lib/fontina/formats/fon.rb +79 -0
  24. data/lib/fontina/formats/open_type/constants.rb +79 -0
  25. data/lib/fontina/formats/open_type/container.rb +10 -0
  26. data/lib/fontina/formats/open_type/head_table.rb +17 -0
  27. data/lib/fontina/formats/open_type/name_table.rb +34 -0
  28. data/lib/fontina/formats/open_type/offset_table.rb +15 -0
  29. data/lib/fontina/formats/open_type/os2_table.rb +14 -0
  30. data/lib/fontina/formats/open_type/table.rb +15 -0
  31. data/lib/fontina/formats/open_type/table_directory.rb +26 -0
  32. data/lib/fontina/formats/open_type.rb +77 -0
  33. data/lib/fontina/formats/shared/language_codes/mac.rb +125 -0
  34. data/lib/fontina/formats/shared/language_codes/windows.rb +211 -0
  35. data/lib/fontina/formats/shared/p_string.rb +16 -0
  36. data/lib/fontina/meta_package.rb +32 -0
  37. data/lib/fontina/package.rb +18 -0
  38. data/lib/fontina/version.rb +3 -0
  39. data/lib/fontina.rb +29 -0
  40. metadata +194 -0
@@ -0,0 +1,79 @@
1
+ module Fontina::Formats
2
+
3
+ module OpenType
4
+ OT_VERSION = 0x4f54544f # OTTO
5
+ TT_VERSION = 0x00010000
6
+
7
+ FW_NORMAL = 400
8
+ FW_BOLD = 700
9
+
10
+ PLATFORMS = {
11
+ 0 => :unicode,
12
+ 1 => :mac,
13
+ 3 => :windows,
14
+ }.freeze
15
+
16
+ ENCODINGS = {
17
+ unicode: {
18
+ 0 => :unicode_1_0,
19
+ 1 => :unicode_1_1,
20
+ 3 => :unicode_2_0_bmp,
21
+ 4 => :unicode_2_0,
22
+ }.freeze,
23
+
24
+ mac: {
25
+ 0 => :roman,
26
+ 1 => :japanese,
27
+ 2 => :chinese_traditional,
28
+ 3 => :korean,
29
+ 4 => :arabic,
30
+ 5 => :hebrew,
31
+ 6 => :greek,
32
+ 7 => :russian,
33
+ 8 => :r_symbol,
34
+ 9 => :devanagari,
35
+ 10 => :gurmukhi,
36
+ 11 => :gujarati,
37
+ 12 => :oriya,
38
+ 13 => :bengali,
39
+ 14 => :tamil,
40
+ 15 => :telugu,
41
+ 16 => :kannada,
42
+ 17 => :malayalam,
43
+ 18 => :sinhalese,
44
+ 19 => :burmese,
45
+ 20 => :khmer,
46
+ 21 => :thai,
47
+ 22 => :laotian,
48
+ 23 => :georgian,
49
+ 24 => :armenian,
50
+ 25 => :chinese_simplified,
51
+ 26 => :tibetan,
52
+ 27 => :mongolian,
53
+ 28 => :geez,
54
+ 29 => :slavic,
55
+ 30 => :vietnamese,
56
+ 31 => :sindhi,
57
+ 32 => :uninterpreted,
58
+ }.freeze,
59
+
60
+ windows: {
61
+ 0 => :symbol,
62
+ 1 => :unicode_ucs2_bmp,
63
+ 2 => :shift_jis,
64
+ 3 => :prc,
65
+ 4 => :big5,
66
+ 5 => :wansung,
67
+ 6 => :johab,
68
+ 10 => :unicode_ucs4,
69
+ }.freeze,
70
+ }.freeze
71
+
72
+ LANGUAGES = {
73
+ unicode: { 0 => nil }.freeze,
74
+ mac: { 0xffff => nil }.merge!(Shared::LanguageCodes::MAC).freeze,
75
+ windows: Shared::LanguageCodes::WINDOWS,
76
+ }.freeze
77
+ end
78
+
79
+ end
@@ -0,0 +1,10 @@
1
+ module Fontina::Formats::OpenType
2
+
3
+ class OT_Container < BinData::Record
4
+ search_prefix :ot
5
+
6
+ offset_table :offset_table
7
+ table_directory :table_directory
8
+ end
9
+
10
+ end
@@ -0,0 +1,17 @@
1
+ module Fontina::Formats::OpenType
2
+
3
+ class OT_HeadTable < BinData::Record
4
+ endian :big
5
+ hide :checksum_adjustment, :magic
6
+
7
+ uint16 :major_version
8
+ uint16 :minor_version
9
+ skip length: 4
10
+ uint32 :checksum_adjustment
11
+ uint32 :magic, assert: 0x5f0f3cf5
12
+ skip length: 28
13
+ uint16 :mac_style
14
+ skip length: 8
15
+ end
16
+
17
+ end
@@ -0,0 +1,34 @@
1
+ module Fontina::Formats::OpenType
2
+
3
+ class OT_NameRecord < BinData::Record
4
+ endian :big
5
+ hide :len, :offs, :platform_id, :encoding_id, :language_id
6
+
7
+ uint16 :platform_id, assert: -> { PLATFORMS.key? value }
8
+ virtual :platform, initial_value: -> { PLATFORMS[platform_id] }
9
+ uint16 :encoding_id, assert: -> { ENCODINGS[platform.value].key? value }
10
+ virtual :encoding, initial_value: -> { ENCODINGS[platform.value][encoding_id] }
11
+ uint16 :language_id, assert: -> { LANGUAGES[platform.value].key? value }
12
+ virtual :language, initial_value: -> { LANGUAGES[platform.value][language_id] }
13
+ uint16 :name_id
14
+ uint16 :len
15
+ uint16 :offs
16
+
17
+ delayed_io :string, read_abs_offset: -> { addr + string_offs + offs } do
18
+ string length: :len
19
+ end
20
+ end
21
+
22
+ class OT_NameTable < BinData::Record
23
+ endian :big
24
+ search_prefix :ot
25
+ hide :name_count, :string_offs
26
+
27
+ uint16 :format
28
+ uint16 :name_count
29
+ uint16 :string_offs
30
+
31
+ array :names, type: :name_record, initial_length: :name_count
32
+ end
33
+
34
+ end
@@ -0,0 +1,15 @@
1
+ module Fontina::Formats::OpenType
2
+
3
+ class OT_OffsetTable < BinData::Record
4
+ endian :big
5
+ search_prefix :ot
6
+ hide :table_count
7
+
8
+ uint32 :version, assert: -> { [OT_VERSION, TT_VERSION].include? value }
9
+ uint16 :table_count
10
+ uint16 :search_range
11
+ uint16 :entry_selector
12
+ uint16 :range_shift
13
+ end
14
+
15
+ end
@@ -0,0 +1,14 @@
1
+ module Fontina::Formats::OpenType
2
+
3
+ class OT_OS2Table < BinData::Record
4
+ endian :big
5
+
6
+ uint16 :version
7
+ skip length: 2
8
+ uint16 :weight_class
9
+ skip length: 56
10
+ uint16 :fs_selection
11
+ skip length: 14
12
+ end
13
+
14
+ end
@@ -0,0 +1,15 @@
1
+ module Fontina::Formats::OpenType
2
+
3
+ class OT_Table < BinData::Choice
4
+ search_prefix :ot
5
+
6
+ default_parameter selection: :tag
7
+
8
+ name_table 'name'
9
+ head_table 'head'
10
+ os2_table 'OS/2'
11
+
12
+ virtual :default
13
+ end
14
+
15
+ end
@@ -0,0 +1,26 @@
1
+ module Fontina::Formats::OpenType
2
+
3
+ class OT_TableDirectoryEntry < BinData::Record
4
+ endian :big
5
+ search_prefix :ot
6
+ hide :checksum
7
+
8
+ string :tag, length: 4
9
+ uint32 :checksum
10
+ uint32 :addr
11
+ uint32 :len
12
+
13
+ delayed_io :table, read_abs_offset: :addr do
14
+ buffer type: :table, length: :len
15
+ end
16
+ end
17
+
18
+ class OT_TableDirectory < BinData::Array
19
+ search_prefix :ot
20
+
21
+ default_parameter initial_length: -> { offset_table.table_count }
22
+
23
+ table_directory_entry
24
+ end
25
+
26
+ end
@@ -0,0 +1,77 @@
1
+ module Fontina
2
+
3
+ module Formats::OpenType
4
+ extend Format
5
+ extension '.otf', '.ttf'
6
+
7
+ class << self
8
+ def read(io)
9
+ package container.read io
10
+ end
11
+
12
+ private
13
+
14
+ def container
15
+ @container ||= begin
16
+ %w[
17
+ shared/language_codes/mac
18
+ shared/language_codes/windows
19
+ open_type/constants
20
+ open_type/name_table
21
+ open_type/head_table
22
+ open_type/os2_table
23
+ open_type/table
24
+ open_type/table_directory
25
+ open_type/offset_table
26
+ open_type/container
27
+ ].each { |file| require_relative file }
28
+
29
+ Class.new(OT_Container) { auto_call_delayed_io }
30
+ end
31
+ end
32
+
33
+ def package(ot)
34
+ name_records = get_table(ot, 'name').names
35
+
36
+ Package[
37
+ name_records.find_all { |n| n.name_id == 4 }
38
+ .map { |n| QualifiedName[n.string, n.platform, n.language] },
39
+
40
+ [Font[
41
+ name_records.find_all { |n| n.name_id == 1 }
42
+ .map { |n| QualifiedName[n.string, n.platform, n.language] },
43
+ :vector,
44
+ nil,
45
+ *get_style(ot)
46
+ ]]
47
+ ]
48
+ end
49
+
50
+ def get_table(ot, tag)
51
+ entry = ot.table_directory.find { |t| t.tag == tag } and
52
+ entry.table
53
+ end
54
+
55
+ def get_style(ot)
56
+ get_table(ot, 'OS/2').tap do |t|
57
+ return [
58
+ t.weight_class,
59
+ t.fs_selection[0] == 1,
60
+ t.fs_selection[1] == 1,
61
+ t.fs_selection[4] == 1
62
+ ] if t
63
+ end
64
+
65
+ get_table(ot, 'head').tap do |t|
66
+ return [
67
+ t.mac_style[0] == 1 ? FW_BOLD : FW_NORMAL,
68
+ t.mac_style[1] == 1,
69
+ t.mac_style[2] == 1,
70
+ nil
71
+ ]
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,125 @@
1
+ module Fontina::Formats::Shared::LanguageCodes
2
+
3
+ MAC = {
4
+ 0 => 'en',
5
+ 1 => 'fr',
6
+ 2 => 'de',
7
+ 3 => 'it',
8
+ 4 => 'nl',
9
+ 5 => 'sv',
10
+ 6 => 'es',
11
+ 7 => 'da',
12
+ 8 => 'pt',
13
+ 9 => 'no',
14
+ 10 => 'he',
15
+ 11 => 'ja',
16
+ 12 => 'ar',
17
+ 13 => 'fi',
18
+ 14 => 'el',
19
+ 15 => 'is',
20
+ 16 => 'mt',
21
+ 17 => 'tr',
22
+ 18 => 'hr',
23
+ 19 => 'zh',
24
+ 20 => 'ur',
25
+ 21 => 'hi',
26
+ 22 => 'th',
27
+ 23 => 'ko',
28
+ 24 => 'lt',
29
+ 25 => 'pl',
30
+ 26 => 'hu',
31
+ 27 => 'et',
32
+ 28 => 'lv',
33
+ 29 => 'smi',
34
+ 30 => 'fo',
35
+ 31 => 'fa',
36
+ 32 => 'ru',
37
+ 33 => 'zh',
38
+ 34 => 'nl',
39
+ 35 => 'ga',
40
+ 36 => 'sq',
41
+ 37 => 'ro',
42
+ 38 => 'cs',
43
+ 39 => 'sk',
44
+ 40 => 'sl',
45
+ 41 => 'yi',
46
+ 42 => 'sr',
47
+ 43 => 'mk',
48
+ 44 => 'bg',
49
+ 45 => 'uk',
50
+ 46 => 'be',
51
+ 47 => 'uz',
52
+ 48 => 'kk',
53
+ 49 => 'az',
54
+ 50 => 'az',
55
+ 51 => 'hy',
56
+ 52 => 'ka',
57
+ 53 => 'mo',
58
+ 54 => 'ky',
59
+ 55 => 'tg',
60
+ 56 => 'tk',
61
+ 57 => 'mn',
62
+ 58 => 'mn',
63
+ 59 => 'ps',
64
+ 60 => 'ku',
65
+ 61 => 'ks',
66
+ 62 => 'sd',
67
+ 63 => 'bo',
68
+ 64 => 'ne',
69
+ 65 => 'sa',
70
+ 66 => 'mr',
71
+ 67 => 'bn',
72
+ 68 => 'as',
73
+ 69 => 'gu',
74
+ 70 => 'pa',
75
+ 71 => 'or',
76
+ 72 => 'ml',
77
+ 73 => 'kn',
78
+ 74 => 'ta',
79
+ 75 => 'te',
80
+ 76 => 'si',
81
+ 77 => 'my',
82
+ 78 => 'km',
83
+ 79 => 'lo',
84
+ 80 => 'vi',
85
+ 81 => 'id',
86
+ 82 => 'tl',
87
+ 83 => 'ms',
88
+ 84 => 'ms',
89
+ 85 => 'am',
90
+ 86 => 'ti',
91
+ 87 => 'om',
92
+ 88 => 'so',
93
+ 89 => 'sw',
94
+ 90 => 'rw',
95
+ 91 => 'rn',
96
+ 92 => 'ny',
97
+ 93 => 'mg',
98
+ 94 => 'eo',
99
+ 128 => 'cy',
100
+ 129 => 'eu',
101
+ 130 => 'ca',
102
+ 131 => 'la',
103
+ 132 => 'qu',
104
+ 133 => 'gn',
105
+ 134 => 'ay',
106
+ 135 => 'tt',
107
+ 136 => 'ug',
108
+ 137 => 'dz',
109
+ 138 => 'jv',
110
+ 139 => 'su',
111
+ 140 => 'gl',
112
+ 141 => 'af',
113
+ 142 => 'br',
114
+ 143 => 'iu',
115
+ 144 => 'gd',
116
+ 145 => 'gv',
117
+ 146 => 'ga',
118
+ 147 => 'to',
119
+ 148 => 'el',
120
+ 149 => 'kl',
121
+ 150 => 'az',
122
+ }.tap { |x| x.freeze.each_value(&:freeze) }
123
+
124
+ end
125
+
@@ -0,0 +1,211 @@
1
+ module Fontina::Formats::Shared::LanguageCodes
2
+
3
+ WINDOWS = {
4
+ 0x0401 => 'ar-SA',
5
+ 0x0402 => 'bg-BG',
6
+ 0x0403 => 'ca-ES',
7
+ 0x0404 => 'zh-TW',
8
+ 0x0405 => 'cs-CZ',
9
+ 0x0406 => 'da-DK',
10
+ 0x0407 => 'de-DE',
11
+ 0x0408 => 'el-GR',
12
+ 0x0409 => 'en-US',
13
+ 0x040a => 'es-ES_tradnl',
14
+ 0x040b => 'fi-FI',
15
+ 0x040c => 'fr-FR',
16
+ 0x040d => 'he-IL',
17
+ 0x040e => 'hu-HU',
18
+ 0x040f => 'is-IS',
19
+ 0x0410 => 'it-IT',
20
+ 0x0411 => 'ja-JP',
21
+ 0x0412 => 'ko-KR',
22
+ 0x0413 => 'nl-NL',
23
+ 0x0414 => 'nb-NO',
24
+ 0x0415 => 'pl-PL',
25
+ 0x0416 => 'pt-BR',
26
+ 0x0417 => 'rm-CH',
27
+ 0x0418 => 'ro-RO',
28
+ 0x0419 => 'ru-RU',
29
+ 0x041a => 'hr-HR',
30
+ 0x041b => 'sk-SK',
31
+ 0x041c => 'sq-AL',
32
+ 0x041d => 'sv-SE',
33
+ 0x041e => 'th-TH',
34
+ 0x041f => 'tr-TR',
35
+ 0x0420 => 'ur-PK',
36
+ 0x0421 => 'id-ID',
37
+ 0x0422 => 'uk-UA',
38
+ 0x0423 => 'be-BY',
39
+ 0x0424 => 'sl-SI',
40
+ 0x0425 => 'et-EE',
41
+ 0x0426 => 'lv-LV',
42
+ 0x0427 => 'lt-LT',
43
+ 0x0428 => 'tg-Cyrl-TJ',
44
+ 0x042a => 'vi-VN',
45
+ 0x042b => 'hy-AM',
46
+ 0x042c => 'az-Latn-AZ',
47
+ 0x042d => 'eu-ES',
48
+ 0x042e => 'hsb-DE',
49
+ 0x042f => 'mk-MK',
50
+ 0x0432 => 'tn-ZA',
51
+ 0x0434 => 'xh-ZA',
52
+ 0x0435 => 'zu-ZA',
53
+ 0x0436 => 'af-ZA',
54
+ 0x0437 => 'ka-GE',
55
+ 0x0438 => 'fo-FO',
56
+ 0x0439 => 'hi-IN',
57
+ 0x043a => 'mt-MT',
58
+ 0x043b => 'se-NO',
59
+ 0x043e => 'ms-MY',
60
+ 0x043f => 'kk-KZ',
61
+ 0x0440 => 'ky-KG',
62
+ 0x0441 => 'sw-KE',
63
+ 0x0442 => 'tk-TM',
64
+ 0x0443 => 'uz-Latn-UZ',
65
+ 0x0444 => 'tt-RU',
66
+ 0x0445 => 'bn-IN',
67
+ 0x0446 => 'pa-IN',
68
+ 0x0447 => 'gu-IN',
69
+ 0x0448 => 'or-IN',
70
+ 0x0449 => 'ta-IN',
71
+ 0x044a => 'te-IN',
72
+ 0x044b => 'kn-IN',
73
+ 0x044c => 'ml-IN',
74
+ 0x044d => 'as-IN',
75
+ 0x044e => 'mr-IN',
76
+ 0x044f => 'sa-IN',
77
+ 0x0450 => 'mn-MN',
78
+ 0x0451 => 'bo-CN',
79
+ 0x0452 => 'cy-GB',
80
+ 0x0453 => 'km-KH',
81
+ 0x0454 => 'lo-LA',
82
+ 0x0456 => 'gl-ES',
83
+ 0x0457 => 'kok-IN',
84
+ 0x045a => 'syr-SY',
85
+ 0x045b => 'si-LK',
86
+ 0x045d => 'iu-Cans-CA',
87
+ 0x045e => 'am-ET',
88
+ 0x0461 => 'ne-NP',
89
+ 0x0462 => 'fy-NL',
90
+ 0x0463 => 'ps-AF',
91
+ 0x0464 => 'fil-PH',
92
+ 0x0465 => 'dv-MV',
93
+ 0x0468 => 'ha-Latn-NG',
94
+ 0x046a => 'yo-NG',
95
+ 0x046b => 'quz-BO',
96
+ 0x046c => 'nso-ZA',
97
+ 0x046d => 'ba-RU',
98
+ 0x046e => 'lb-LU',
99
+ 0x046f => 'kl-GL',
100
+ 0x0470 => 'ig-NG',
101
+ 0x0478 => 'ii-CN',
102
+ 0x047a => 'arn-CL',
103
+ 0x047c => 'moh-CA',
104
+ 0x047e => 'br-FR',
105
+ 0x0480 => 'ug-CN',
106
+ 0x0481 => 'mi-NZ',
107
+ 0x0482 => 'oc-FR',
108
+ 0x0483 => 'co-FR',
109
+ 0x0484 => 'gsw-FR',
110
+ 0x0485 => 'sah-RU',
111
+ 0x0486 => 'quc-Latn-GT',
112
+ 0x0487 => 'rw-RW',
113
+ 0x0488 => 'wo-SN',
114
+ 0x048c => 'prs-AF',
115
+ 0x0801 => 'ar-IQ',
116
+ 0x0804 => 'zh-CN',
117
+ 0x0807 => 'de-CH',
118
+ 0x0809 => 'en-GB',
119
+ 0x080a => 'es-MX',
120
+ 0x080c => 'fr-BE',
121
+ 0x0810 => 'it-CH',
122
+ 0x0813 => 'nl-BE',
123
+ 0x0814 => 'nn-NO',
124
+ 0x0816 => 'pt-PT',
125
+ 0x081a => 'sr-Latn-CS',
126
+ 0x081d => 'sv-FI',
127
+ 0x082c => 'az-Cyrl-AZ',
128
+ 0x082e => 'dsb-DE',
129
+ 0x083b => 'se-SE',
130
+ 0x083c => 'ga-IE',
131
+ 0x083e => 'ms-BN',
132
+ 0x0843 => 'uz-Cyrl-UZ',
133
+ 0x0845 => 'bn-BD',
134
+ 0x0850 => 'mn-Mong-CN',
135
+ 0x085d => 'iu-Latn-CA',
136
+ 0x085f => 'tzm-Latn-DZ',
137
+ 0x086b => 'quz-EC',
138
+ 0x0c01 => 'ar-EG',
139
+ 0x0c04 => 'zh-HK',
140
+ 0x0c07 => 'de-AT',
141
+ 0x0c09 => 'en-AU',
142
+ 0x0c0a => 'es-ES',
143
+ 0x0c0c => 'fr-CA',
144
+ 0x0c1a => 'sr-Cyrl-CS',
145
+ 0x0c3b => 'se-FI',
146
+ 0x0c6b => 'quz-PE',
147
+ 0x1001 => 'ar-LY',
148
+ 0x1004 => 'zh-SG',
149
+ 0x1007 => 'de-LU',
150
+ 0x1009 => 'en-CA',
151
+ 0x100a => 'es-GT',
152
+ 0x100c => 'fr-CH',
153
+ 0x101a => 'hr-BA',
154
+ 0x103b => 'smj-NO',
155
+ 0x1401 => 'ar-DZ',
156
+ 0x1404 => 'zh-MO',
157
+ 0x1407 => 'de-LI',
158
+ 0x1409 => 'en-NZ',
159
+ 0x140a => 'es-CR',
160
+ 0x140c => 'fr-LU',
161
+ 0x141a => 'bs-Latn-BA',
162
+ 0x143b => 'smj-SE',
163
+ 0x1801 => 'ar-MA',
164
+ 0x1809 => 'en-IE',
165
+ 0x180a => 'es-PA',
166
+ 0x180c => 'fr-MC',
167
+ 0x181a => 'sr-Latn-BA',
168
+ 0x183b => 'sma-NO',
169
+ 0x1c01 => 'ar-TN',
170
+ 0x1c09 => 'en-ZA',
171
+ 0x1c0a => 'es-DO',
172
+ 0x1c1a => 'sr-Cyrl-BA',
173
+ 0x1c3b => 'sma-SE',
174
+ 0x2001 => 'ar-OM',
175
+ 0x2009 => 'en-JM',
176
+ 0x200a => 'es-VE',
177
+ 0x201a => 'bs-Cyrl-BA',
178
+ 0x203b => 'sms-FI',
179
+ 0x2401 => 'ar-YE',
180
+ 0x2409 => 'en-029',
181
+ 0x240a => 'es-CO',
182
+ 0x243b => 'smn-FI',
183
+ 0x2801 => 'ar-SY',
184
+ 0x2809 => 'en-BZ',
185
+ 0x280a => 'es-PE',
186
+ 0x2c01 => 'ar-JO',
187
+ 0x2c09 => 'en-TT',
188
+ 0x2c0a => 'es-AR',
189
+ 0x3001 => 'ar-LB',
190
+ 0x3009 => 'en-ZW',
191
+ 0x300a => 'es-EC',
192
+ 0x3401 => 'ar-KW',
193
+ 0x3409 => 'en-PH',
194
+ 0x340a => 'es-CL',
195
+ 0x3801 => 'ar-AE',
196
+ 0x380a => 'es-UY',
197
+ 0x3c01 => 'ar-BH',
198
+ 0x3c0a => 'es-PY',
199
+ 0x4001 => 'ar-QA',
200
+ 0x4009 => 'en-IN',
201
+ 0x400a => 'es-BO',
202
+ 0x4409 => 'en-MY',
203
+ 0x440a => 'es-SV',
204
+ 0x4809 => 'en-SG',
205
+ 0x480a => 'es-HN',
206
+ 0x4c0a => 'es-NI',
207
+ 0x500a => 'es-PR',
208
+ 0x540a => 'es-US',
209
+ }.tap { |x| x.freeze.each_value(&:freeze) }
210
+
211
+ end
@@ -0,0 +1,16 @@
1
+ module Fontina::Formats::Shared
2
+
3
+ class PString < BinData::Primitive
4
+ uint8 :len, value: -> { string.length }
5
+ string :string, read_length: :len
6
+
7
+ def get
8
+ string
9
+ end
10
+
11
+ def set(value)
12
+ string = value
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,32 @@
1
+ module Fontina
2
+
3
+ class MetaPackage
4
+ attr_reader :location
5
+
6
+ def initialize(location)
7
+ @location = location
8
+ end
9
+
10
+ def size
11
+ file.content.length
12
+ end
13
+
14
+ def format
15
+ @format ||= Format.for(
16
+ mime_type: file.mime_type,
17
+ extension: File.extname(file.filename).downcase
18
+ )
19
+ end
20
+
21
+ def package
22
+ @package ||= StringIO.open file.content, 'rb', &format.method(:read)
23
+ end
24
+
25
+ private
26
+
27
+ def file
28
+ @file ||= Fetcher.fetch location
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,18 @@
1
+ module Fontina
2
+
3
+ QualifiedName = Mores::ImmutableStruct.new(
4
+ *%i[name platform language],
5
+ strict: true
6
+ )
7
+
8
+ Font = Mores::ImmutableStruct.new(
9
+ *%i[family_names type points weight italic underline strikeout],
10
+ strict: true
11
+ )
12
+
13
+ Package = Mores::ImmutableStruct.new(
14
+ *%i[names fonts],
15
+ strict: true
16
+ )
17
+
18
+ end