fontina 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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