Class: Fontisan::DfontCollection
- Inherits:
-
Object
- Object
- Fontisan::DfontCollection
- Defined in:
- lib/fontisan/dfont_collection.rb
Overview
DfontCollection represents an Apple dfont suitcase containing multiple fonts
dfont (Data Fork Font) is an Apple-specific format that stores Mac font suitcase resources in the data fork. It can contain multiple SFNT fonts (TrueType or OpenType).
This class provides a collection interface similar to TrueTypeCollection and OpenTypeCollection for consistency.
Instance Attribute Summary collapse
-
#num_fonts ⇒ Integer
(also: #font_count)
readonly
Number of fonts in collection.
-
#path ⇒ String
readonly
Path to dfont file.
Class Method Summary collapse
-
.from_file(path) ⇒ DfontCollection
Load dfont collection from file.
Instance Method Summary collapse
-
#extract_fonts(io) ⇒ Array<TrueTypeFont, OpenTypeFont>
Extract all fonts from dfont.
-
#font(index, io, mode: LoadingModes::FULL) ⇒ TrueTypeFont, OpenTypeFont
Get specific font from collection.
-
#initialize(path, num_fonts) ⇒ DfontCollection
constructor
private
Initialize collection.
-
#list_fonts(io) ⇒ Models::CollectionListInfo
List fonts in collection (brief info).
-
#valid? ⇒ Boolean
Check if collection is valid.
Constructor Details
#initialize(path, num_fonts) ⇒ DfontCollection
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Initialize collection
56 57 58 59 |
# File 'lib/fontisan/dfont_collection.rb', line 56 def initialize(path, num_fonts) @path = path @num_fonts = num_fonts end |
Instance Attribute Details
#num_fonts ⇒ Integer (readonly) Also known as: font_count
Number of fonts in collection
32 33 34 |
# File 'lib/fontisan/dfont_collection.rb', line 32 def num_fonts @num_fonts end |
#path ⇒ String (readonly)
Path to dfont file
28 29 30 |
# File 'lib/fontisan/dfont_collection.rb', line 28 def path @path end |
Class Method Details
.from_file(path) ⇒ DfontCollection
Load dfont collection from file
40 41 42 43 44 45 46 47 48 49 |
# File 'lib/fontisan/dfont_collection.rb', line 40 def self.from_file(path) File.open(path, "rb") do |io| unless Parsers::DfontParser.dfont?(io) raise InvalidFontError, "Not a valid dfont file: #{path}" end num_fonts = Parsers::DfontParser.sfnt_count(io) new(path, num_fonts) end end |
Instance Method Details
#extract_fonts(io) ⇒ Array<TrueTypeFont, OpenTypeFont>
Extract all fonts from dfont
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/fontisan/dfont_collection.rb', line 72 def extract_fonts(io) require "stringio" fonts = [] @num_fonts.times do |index| io.rewind sfnt_data = Parsers::DfontParser.extract_sfnt(io, index: index) # Load font from SFNT binary sfnt_io = StringIO.new(sfnt_data) signature = sfnt_io.read(4) sfnt_io.rewind # Create font based on signature font = case signature when [Constants::SFNT_VERSION_TRUETYPE].pack("N"), "true" TrueTypeFont.read(sfnt_io) when "OTTO" OpenTypeFont.read(sfnt_io) else raise InvalidFontError, "Invalid SFNT signature in dfont at index #{index}: #{signature.inspect}" end font.initialize_storage font.loading_mode = LoadingModes::FULL font.lazy_load_enabled = false font.read_table_data(sfnt_io) fonts << font end fonts end |
#font(index, io, mode: LoadingModes::FULL) ⇒ TrueTypeFont, OpenTypeFont
Get specific font from collection
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/fontisan/dfont_collection.rb', line 151 def font(index, io, mode: LoadingModes::FULL) if index >= @num_fonts raise InvalidFontError, "Font index #{index} out of range (collection has #{@num_fonts} fonts)" end io.rewind sfnt_data = Parsers::DfontParser.extract_sfnt(io, index: index) # Load font from SFNT binary require "stringio" sfnt_io = StringIO.new(sfnt_data) signature = sfnt_io.read(4) sfnt_io.rewind # Create font based on signature font = case signature when [Constants::SFNT_VERSION_TRUETYPE].pack("N"), "true" TrueTypeFont.read(sfnt_io) when "OTTO" OpenTypeFont.read(sfnt_io) else raise InvalidFontError, "Invalid SFNT signature: #{signature.inspect}" end font.initialize_storage font.loading_mode = mode font.lazy_load_enabled = false font.read_table_data(sfnt_io) font end |
#list_fonts(io) ⇒ Models::CollectionListInfo
List fonts in collection (brief info)
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/fontisan/dfont_collection.rb', line 112 def list_fonts(io) require_relative "models/collection_list_info" require_relative "models/collection_font_summary" fonts = extract_fonts(io) summaries = fonts.map.with_index do |font, index| name_table = font.table("name") family = name_table.english_name(Models::Tables::Name::FAMILY) || "Unknown" subfamily = name_table.english_name(Models::Tables::Name::SUBFAMILY) || "Regular" # Detect font format format = if font.has_table?("CFF ") || font.has_table?("CFF2") "OpenType" else "TrueType" end Models::CollectionFontSummary.new( index: index, family_name: family, subfamily_name: subfamily, font_format: format, ) end Models::CollectionListInfo.new( num_fonts: @num_fonts, fonts: summaries, ) end |
#valid? ⇒ Boolean
Check if collection is valid
64 65 66 |
# File 'lib/fontisan/dfont_collection.rb', line 64 def valid? File.exist?(@path) && @num_fonts.positive? end |