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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1709e3c73ce8a624a911a47e6eb00f0648a690e3
4
+ data.tar.gz: 9d743b1f8a9fc918afccfca1c42cf21aaef3f561
5
+ SHA512:
6
+ metadata.gz: 839971dac95f57ffb1a0ba3883ebbab127c03276f2d2bd2bebc78660ab63e8891dbb67f76e81418c1ee42b41c1b42727d2d2204a78583f11aea58d2116656850
7
+ data.tar.gz: 1dbab3c0e87be89f91a8a3adb403195100ec2b014af31507dbb49cdf273b4e11cec9e65b6fcd40d6b11187430e4a3c072f645a002f2c9e16769d29f9c4cbd21d
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Michael Petter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Fontina
2
+
3
+ [![Version](http://img.shields.io/gem/v/fontina.svg) ](https://rubygems.org/gems/fontina)
4
+ [![Travis ](https://img.shields.io/travis/michaeljpetter/fontina/master.svg)](https://travis-ci.org/michaeljpetter/fontina)
5
+
6
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/fontina`. To experiment with that code, run `bin/console` for an interactive prompt.
7
+
8
+ TODO: Delete this and the text above, and describe your gem
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'fontina'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install fontina
25
+
26
+ ## Usage
27
+
28
+ TODO: Write usage instructions here
29
+
30
+ ## Development
31
+
32
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
33
+
34
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
35
+
36
+ ## Contributing
37
+
38
+ 1. Fork it ( https://github.com/[my-github-username]/fontina/fork )
39
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
40
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
41
+ 4. Push to the branch (`git push origin my-new-feature`)
42
+ 5. Create a new Pull Request
data/fontina.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ require_relative 'lib/fontina/version'
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'fontina'
5
+ gem.version = Fontina::VERSION
6
+ gem.author = 'Michael Petter'
7
+ gem.email = 'michaeljpetter@gmail.com'
8
+
9
+ gem.summary = 'A cheesy font utility'
10
+ gem.description = <<-END
11
+ Fetches, parses, and describes font files.
12
+ END
13
+ gem.homepage = 'http://github.com/michaeljpetter/fontina'
14
+ gem.license = 'MIT'
15
+
16
+ gem.platform = Gem::Platform::RUBY
17
+ gem.files = Dir.glob %w(lib/**/* Gemfile *.gemspec LICENSE* README*)
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_dependency 'bindata', '>=2.3.5'
21
+ gem.add_dependency 'faraday', '< 1.0'
22
+ gem.add_dependency 'faraday_middleware', '~> 0.10.0'
23
+ gem.add_dependency 'mores', '>=0.1.5'
24
+
25
+ gem.add_development_dependency 'bundler', '~> 1.7'
26
+ gem.add_development_dependency 'rake', '~> 10.0'
27
+ gem.add_development_dependency 'rspec', '~> 3.4'
28
+ gem.add_development_dependency 'rspec-its', '~> 1.2'
29
+ end
@@ -0,0 +1,34 @@
1
+ module Fontina
2
+
3
+ module Fetcher
4
+ Result = Mores::ImmutableStruct.new(:content, :filename, :mime_type)
5
+
6
+ class << self
7
+ extend Forwardable
8
+
9
+ delegate :fetch => :succession
10
+
11
+ private
12
+
13
+ def succession
14
+ @succession ||= Mores::Succession.new do
15
+ line :fetch do |location|
16
+ raise "Location '#{location}' is not supported"
17
+ end
18
+ end
19
+ end
20
+
21
+ def included(base)
22
+ succession >> base.new
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ %w[
30
+ preprocessor
31
+ http
32
+ local_file_uri
33
+ local_file_path
34
+ ].each { |fetcher| require_relative "fetchers/#{fetcher}" }
@@ -0,0 +1,43 @@
1
+ require 'uri'
2
+
3
+ module Fontina
4
+
5
+ class Fetchers::HTTP
6
+ include Fetcher
7
+
8
+ def fetch(location)
9
+ return super unless location.is_a? URI::HTTP
10
+
11
+ response = connection.get(location)
12
+
13
+ Result[response.body, get_filename(response), get_mime_type(response)]
14
+ end
15
+
16
+ private
17
+
18
+ def connection
19
+ @connection ||= Faraday.new do |c|
20
+ c.use FaradayMiddleware::FollowRedirects, limit: 2
21
+ c.use Faraday::Response::RaiseError
22
+ c.adapter Faraday.default_adapter
23
+ end
24
+ end
25
+
26
+ def get_filename(response)
27
+ get_attachment_filename(response) || File.basename(response.env.url.path)
28
+ end
29
+
30
+ def get_attachment_filename(response)
31
+ disposition = response.headers[:content_disposition] and
32
+ match = disposition.match(/^attachment; *filename=(?<q>"?)(?<filename>(\w| |\.|\\")*)\k<q>$/) and
33
+ match[:filename].gsub('\"', '"')
34
+ end
35
+
36
+ def get_mime_type(response)
37
+ type = response.headers[:content_type] and
38
+ match = type.match(/^(?<type>[\w-]+\/[\w-]+)(;.*)?$/) and
39
+ match[:type]
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,15 @@
1
+ require 'pathname'
2
+
3
+ module Fontina
4
+
5
+ class Fetchers::LocalFilePath
6
+ include Fetcher
7
+
8
+ def fetch(location)
9
+ return super unless location.is_a? String
10
+
11
+ Result[Pathname.new(location).binread, File.basename(location)]
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,21 @@
1
+ require 'uri'
2
+ require 'pathname'
3
+
4
+ module Fontina
5
+
6
+ class Fetchers::LocalFileURI
7
+ include Fetcher
8
+
9
+ def fetch(location)
10
+ return super unless
11
+ location.is_a?(URI::Generic) &&
12
+ location.scheme == 'file' &&
13
+ [nil, 'localhost'].include?(location.host)
14
+
15
+ path = URI.decode location.path
16
+
17
+ Result[Pathname.new(path).binread, File.basename(path)]
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,18 @@
1
+ require 'uri'
2
+
3
+ module Fontina
4
+
5
+ class Fetchers::Preprocessor
6
+ include Fetcher
7
+
8
+ def fetch(location)
9
+ begin
10
+ uri = URI.parse location
11
+ location = uri if uri.scheme && !uri.opaque
12
+ rescue URI::Error; end
13
+
14
+ super
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,39 @@
1
+ module Fontina
2
+
3
+ module Format
4
+ class << self
5
+ def for(criteria)
6
+ criteria.lazy
7
+ .map { |key, value| registry[key][value] }
8
+ .find(&:itself) or fail "no format matches #{criteria}"
9
+ end
10
+
11
+ private
12
+
13
+ def register(format, criteria)
14
+ criteria.each do |key, args|
15
+ args.each { |arg| registry[key][arg] = format }
16
+ end
17
+ end
18
+
19
+ def registry
20
+ @registry ||= %i[extension mime_type]
21
+ .reduce(Hash.new({}.freeze)) { |h, k| h[k] = {}; h }
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ registry.each_key do |key|
28
+ define_method key do |*args|
29
+ Format.send :register, self, key => args
30
+ end
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ %w[
37
+ fon
38
+ open_type
39
+ ].each { |format| require_relative "formats/#{format}" }
@@ -0,0 +1,12 @@
1
+ module Fontina::Formats::FON
2
+
3
+ IMAGE_DOS_SIGNATURE = 0x5a4d # MZ
4
+ IMAGE_OS2_SIGNATURE = 0x454e # NE
5
+
6
+ RT_FONTDIR = 7
7
+ RT_FONT = 8
8
+ RT_VERSION = 16
9
+
10
+ WORD_HIGHBIT = 0x8000
11
+
12
+ end
@@ -0,0 +1,24 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_Container < BinData::Record
4
+ search_prefix :fon
5
+
6
+ dos_header :dos
7
+
8
+ skip to_abs_offset: -> { dos.new_addr }
9
+ ne_header :ne
10
+
11
+ skip to_abs_offset: -> { ne.abs_offset + ne.restab_offs }
12
+ ne_exported_name_table :restab
13
+ virtual :restab_count, assert: -> { restab.count == 2 }
14
+
15
+ skip to_abs_offset: -> { ne.nrestab_addr }
16
+ ne_exported_name_table :nrestab
17
+ virtual :nrestab_num_bytes, assert: -> { nrestab.num_bytes == ne.nrestab_len }
18
+ virtual :nrestab_count, assert: -> { nrestab.count == 2 }
19
+ virtual :nrestab_first, assert: -> { nrestab.first.start_with?('FONTRES ') }
20
+
21
+ delayed_io :rsrctab, type: :ne_resource_table, read_abs_offset: -> { ne.abs_offset + ne.rsrctab_offs }
22
+ end
23
+
24
+ end
@@ -0,0 +1,14 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_DOSHeader < BinData::Record
4
+ endian :little
5
+ hide :magic, :reloc_addr
6
+
7
+ uint16 :magic, assert: IMAGE_DOS_SIGNATURE
8
+ skip length: 22
9
+ uint16 :reloc_addr, assert: 0x40
10
+ skip length: 34
11
+ int32 :new_addr
12
+ end
13
+
14
+ end
@@ -0,0 +1,24 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_NEExportedName < BinData::Primitive
4
+ p_string :name
5
+ uint8 :enttab_idx, assert: 0
6
+
7
+ def get
8
+ name
9
+ end
10
+
11
+ def set(value)
12
+ name = value
13
+ end
14
+ end
15
+
16
+ class FON_NEExportedNameTable < BinData::Array
17
+ search_prefix :fon
18
+
19
+ default_parameter read_until: -> { element.empty? }
20
+
21
+ ne_exported_name
22
+ end
23
+
24
+ end
@@ -0,0 +1,50 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_NEFontDirEntry < BinData::Record
4
+ endian :little
5
+
6
+ uint16 :version
7
+ uint32 :len
8
+ string :copyright, length: 60, trim_padding: true
9
+ uint16 :font_type
10
+ uint16 :points
11
+ uint16 :vert_dpi
12
+ uint16 :horiz_dpi
13
+ uint16 :ascent
14
+ uint16 :internal_leading
15
+ uint16 :external_leading
16
+ uint8 :italic
17
+ uint8 :underline
18
+ uint8 :strikeout
19
+ uint16 :weight
20
+ uint8 :char_set
21
+ uint16 :pix_width
22
+ uint16 :pix_height
23
+ uint8 :pitch_and_family
24
+ uint16 :avg_width
25
+ uint16 :max_width
26
+ uint8 :first_char
27
+ uint8 :last_char
28
+ uint8 :default_char
29
+ uint8 :break_char
30
+ uint16 :width_len
31
+ uint32 :device_addr
32
+ uint32 :face_addr
33
+ skip length: 4
34
+ stringz :device_name
35
+ stringz :face_name
36
+ end
37
+
38
+ class FON_NEFontDir < BinData::Record
39
+ endian :little
40
+ search_prefix :fon
41
+ hide :dir_count
42
+
43
+ uint16 :dir_count
44
+ array :dir, initial_length: :dir_count do
45
+ uint16 :ordinal
46
+ ne_font_dir_entry :entry
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,25 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_NEHeader < BinData::Record
4
+ FLAGS_MASK = 0b1000100000000011
5
+ VALID_FLAGS = 0b1000000000000000
6
+
7
+ endian :little
8
+ hide :magic, :enttab_len, :flags
9
+
10
+ uint16 :magic, assert: IMAGE_OS2_SIGNATURE
11
+ skip length: 4
12
+ uint16 :enttab_len, assert: -> { value.between?(1, 2) }
13
+ skip length: 4
14
+ uint16 :flags, assert: -> { value & FLAGS_MASK == VALID_FLAGS }
15
+ skip length: 18
16
+ uint16 :nrestab_len
17
+ skip length: 2
18
+ uint16 :rsrctab_offs
19
+ uint16 :restab_offs
20
+ skip length: 4
21
+ int32 :nrestab_addr
22
+ skip length: 16
23
+ end
24
+
25
+ end
@@ -0,0 +1,14 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_NEResource < BinData::Choice
4
+ search_prefix :fon
5
+
6
+ default_parameter selection: -> { type_id & ~WORD_HIGHBIT }
7
+
8
+ ne_font_dir RT_FONTDIR
9
+ ne_vs_version_info RT_VERSION
10
+
11
+ virtual :default
12
+ end
13
+
14
+ end
@@ -0,0 +1,18 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_NEResourceNameInfo < BinData::Record
4
+ endian :little
5
+ search_prefix :fon
6
+
7
+ uint16 :data_blkaddr
8
+ uint16 :data_blklen
9
+ skip length: 2
10
+ uint16 :id
11
+ skip length: 4
12
+
13
+ delayed_io :data, read_abs_offset: -> { data_blkaddr << align_shift } do
14
+ buffer type: :ne_resource, length: -> { data_blklen << align_shift }
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,12 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_NEResourceTable < BinData::Record
4
+ endian :little
5
+ search_prefix :fon
6
+
7
+ uint16 :align_shift, assert: -> { value > 1 }
8
+ array :types, type: :ne_resource_type_info, read_until: -> { element.type_id.zero? }
9
+ array :rsrc_names, type: :p_string, read_until: -> { element.empty? }
10
+ end
11
+
12
+ end
@@ -0,0 +1,21 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_NEResourceTypeInfo < BinData::Record
4
+ VALID_TYPE_IDS = ([0] + [
5
+ RT_FONTDIR,
6
+ RT_FONT,
7
+ RT_VERSION,
8
+ 15 # unknown; occurs in some system fonts
9
+ ].map!(&WORD_HIGHBIT.method(:|))).freeze
10
+
11
+ endian :little
12
+ search_prefix :fon
13
+ hide :rsrc_count
14
+
15
+ uint16 :type_id, assert: -> { VALID_TYPE_IDS.include? value }
16
+ uint16 :rsrc_count, onlyif: -> { type_id.nonzero? }
17
+ skip length: 4, onlyif: -> { type_id.nonzero? }
18
+ array :name_info, type: :ne_resource_name_info, initial_length: :rsrc_count, onlyif: -> { type_id.nonzero? }
19
+ end
20
+
21
+ end
@@ -0,0 +1,70 @@
1
+ module Fontina::Formats::FON
2
+
3
+ class FON_NEVersionData < BinData::Choice
4
+ endian :little
5
+
6
+ default_parameter selection: -> {
7
+ return STRINGZ if path[1...-2] == ['StringFileInfo']
8
+ return TRANSLATION if path[1..-1] == ['VarFileInfo', 'Translation']
9
+ :default
10
+ }
11
+
12
+ stringz STRINGZ = 1
13
+
14
+ array TRANSLATION = 2, read_until: :eof do
15
+ uint16 :locale
16
+ uint16 :codepage
17
+ end
18
+
19
+ virtual :default
20
+ end
21
+
22
+ class FON_NEVersionNode < BinData::Record
23
+ endian :little
24
+ search_prefix :fon
25
+ hide :node_len, :data_len, :children_len
26
+
27
+ uint16 :node_len
28
+ uint16 :data_len
29
+ stringz :name
30
+ virtual byte_align: 4
31
+
32
+ buffer :data, length: :data_len, type: :ne_version_data, onlyif: -> { data_len.nonzero? }
33
+ virtual :data_end
34
+ virtual byte_align: 4
35
+
36
+ virtual :children_len, initial_value: -> { node_len - data_end.rel_offset }
37
+
38
+ buffer :children, length: :children_len, onlyif: -> { children_len.nonzero? } do
39
+ array type: :ne_version_node, read_until: :eof
40
+ end
41
+ virtual byte_align: 4
42
+
43
+ def path
44
+ @path ||= (parent_node.path + [name]).freeze
45
+ end
46
+
47
+ private
48
+
49
+ def parent_node
50
+ @parent_node ||= begin
51
+ value = self
52
+ loop { value = value.parent; break if value.is_a? self.class }
53
+ value
54
+ end
55
+ end
56
+ end
57
+
58
+ class FON_NEVsVersionInfo < FON_NEVersionNode
59
+ virtual :root_name, assert: -> { name == 'VS_VERSION_INFO' }
60
+
61
+ virtual :root_num_bytes,
62
+ byte_align: -> { 1 << align_shift },
63
+ assert: -> { num_bytes == data_blklen << align_shift }
64
+
65
+ def path
66
+ @path ||= [name].freeze
67
+ end
68
+ end
69
+
70
+ end
@@ -0,0 +1,79 @@
1
+ module Fontina
2
+
3
+ module Formats::FON
4
+ extend Format
5
+ extension '.fon'
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/windows
18
+ shared/p_string
19
+ fon/constants
20
+ fon/dos_header
21
+ fon/ne_header
22
+ fon/ne_exported_name_table
23
+ fon/ne_font_dir
24
+ fon/ne_vs_version_info
25
+ fon/ne_resource
26
+ fon/ne_resource_name_info
27
+ fon/ne_resource_type_info
28
+ fon/ne_resource_table
29
+ fon/container
30
+ ].each { |file| require_relative file }
31
+
32
+ Class.new(FON_Container) { auto_call_delayed_io }
33
+ end
34
+ end
35
+
36
+ def package(fon)
37
+ language = get_language(fon)
38
+
39
+ Package[
40
+ [QualifiedName[
41
+ fon.nrestab.first.name.sub(/^.*:\s*/, ''), :windows, language
42
+ ]],
43
+
44
+ get_rsrc_data(fon, RT_FONTDIR)
45
+ .flat_map(&:dir).map(&:entry)
46
+ .map do |e|
47
+ Font[
48
+ [QualifiedName[e.face_name, :windows, language]],
49
+ e.font_type[0] == 1 ? :vector : :raster,
50
+ e.points,
51
+ e.weight,
52
+ e.italic[0] == 1,
53
+ e.underline[0] == 1,
54
+ e.strikeout[0] == 1,
55
+ ]
56
+ end
57
+ ]
58
+ end
59
+
60
+ def get_language(fon)
61
+ language_id = get_rsrc_data(fon, RT_VERSION)
62
+ .flat_map(&:children).find_all { |c| c.name == 'VarFileInfo' }
63
+ .flat_map(&:children).find_all { |c| c.name == 'Translation' }
64
+ .flat_map(&:data).map(&:locale)
65
+ .first
66
+
67
+ Formats::Shared::LanguageCodes::WINDOWS[language_id]
68
+ end
69
+
70
+ def get_rsrc_data(fon, type)
71
+ fon.rsrctab
72
+ .types.find_all { |t| t.type_id == WORD_HIGHBIT | type }
73
+ .flat_map(&:name_info)
74
+ .map(&:data)
75
+ end
76
+ end
77
+ end
78
+
79
+ end