Class: Fontisan::Type1Font
- Inherits:
-
Object
- Object
- Fontisan::Type1Font
- Defined in:
- lib/fontisan/type1_font.rb
Overview
Adobe Type 1 Font handler
[‘Type1Font`](lib/fontisan/type1_font.rb) provides parsing and conversion capabilities for Adobe Type 1 fonts in PFB (Printer Font Binary) and PFA (Printer Font ASCII) formats.
Type 1 fonts were the standard for digital typography in the 1980s-1990s and consist of:
-
Font dictionary with metadata (FontInfo, FontName, Encoding, etc.)
-
Private dictionary with hinting and spacing information
-
CharStrings (glyph outline descriptions)
-
eexec encryption for protection
Instance Attribute Summary collapse
-
#decrypted_data ⇒ String?
readonly
Decrypted font data.
-
#file_path ⇒ String?
readonly
File path if loaded from file.
-
#format ⇒ Symbol
readonly
Format type (:pfb or :pfa).
-
#loading_mode ⇒ Symbol
readonly
Loading mode (:metadata or :full).
Class Method Summary collapse
-
.from_file(file_path, mode: :full) ⇒ Type1Font
Load Type 1 font from file.
Instance Method Summary collapse
-
#charstrings ⇒ CharStrings?
CharStrings dictionary.
-
#clear_text ⇒ String
Get clear text portion (before eexec).
-
#decrypt! ⇒ String
Decrypt the font if not already decrypted.
-
#decrypted? ⇒ Boolean
Check if font has been decrypted.
-
#encrypted? ⇒ Boolean
Check if font is encrypted.
-
#encrypted_portion ⇒ String
Get encrypted portion (as hex string for PFA).
-
#family_name ⇒ String?
Get family name from FontInfo.
-
#font_dictionary ⇒ FontDictionary?
Font dictionary.
-
#font_name ⇒ String?
Get font name from font dictionary.
-
#full_name ⇒ String?
Get full name from FontInfo.
-
#glyph_names ⇒ Array<String>
Get list of glyph names.
-
#initialize(data, format: nil, file_path: nil, mode: :full) ⇒ Type1Font
constructor
Initialize a new Type1Font instance.
-
#parse_dictionaries! ⇒ void
Parse font dictionaries from decrypted data.
-
#parsed_dictionaries? ⇒ Boolean
Check if dictionaries have been parsed.
-
#private_dict ⇒ PrivateDict?
Private dictionary.
-
#version ⇒ String?
Get version from FontInfo.
Constructor Details
#initialize(data, format: nil, file_path: nil, mode: :full) ⇒ Type1Font
Initialize a new Type1Font instance
70 71 72 73 74 75 76 77 |
# File 'lib/fontisan/type1_font.rb', line 70 def initialize(data, format: nil, file_path: nil, mode: :full) @file_path = file_path @format = format || detect_format(data) @data = data @loading_mode = mode parse_font_data end |
Instance Attribute Details
#decrypted_data ⇒ String? (readonly)
Returns Decrypted font data.
44 45 46 |
# File 'lib/fontisan/type1_font.rb', line 44 def decrypted_data @decrypted_data end |
#file_path ⇒ String? (readonly)
Returns File path if loaded from file.
35 36 37 |
# File 'lib/fontisan/type1_font.rb', line 35 def file_path @file_path end |
#format ⇒ Symbol (readonly)
Returns Format type (:pfb or :pfa).
38 39 40 |
# File 'lib/fontisan/type1_font.rb', line 38 def format @format end |
#loading_mode ⇒ Symbol (readonly)
Returns Loading mode (:metadata or :full).
41 42 43 |
# File 'lib/fontisan/type1_font.rb', line 41 def loading_mode @loading_mode end |
Class Method Details
.from_file(file_path, mode: :full) ⇒ Type1Font
Load Type 1 font from file
92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/fontisan/type1_font.rb', line 92 def self.from_file(file_path, mode: :full) raise ArgumentError, "File path cannot be nil" if file_path.nil? unless File.exist?(file_path) raise Fontisan::Error, "File not found: #{file_path}" end # Read file data = File.binread(file_path) new(data, file_path: file_path, mode: mode) end |
Instance Method Details
#charstrings ⇒ CharStrings?
Returns CharStrings dictionary.
59 60 61 62 |
# File 'lib/fontisan/type1_font.rb', line 59 def charstrings parse_dictionaries! unless @charstrings @charstrings end |
#clear_text ⇒ String
Get clear text portion (before eexec)
108 109 110 |
# File 'lib/fontisan/type1_font.rb', line 108 def clear_text @clear_text ||= "" end |
#decrypt! ⇒ String
Decrypt the font if not already decrypted
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/fontisan/type1_font.rb', line 136 def decrypt! return @decrypted_data if decrypted? if @encrypted_portion.nil? || @encrypted_portion.empty? @decrypted_data = @clear_text else encrypted_binary = if @format == :pfa # Convert hex string to binary [@encrypted_portion.gsub(/\s/, "")].pack("H*") else @encrypted_portion end @decrypted_data = @clear_text + Type1::Decryptor.eexec_decrypt(encrypted_binary) end @decrypted_data end |
#decrypted? ⇒ Boolean
Check if font has been decrypted
122 123 124 |
# File 'lib/fontisan/type1_font.rb', line 122 def decrypted? !@decrypted_data.nil? end |
#encrypted? ⇒ Boolean
Check if font is encrypted
129 130 131 |
# File 'lib/fontisan/type1_font.rb', line 129 def encrypted? !@encrypted_portion.nil? && !@encrypted_portion.empty? end |
#encrypted_portion ⇒ String
Get encrypted portion (as hex string for PFA)
115 116 117 |
# File 'lib/fontisan/type1_font.rb', line 115 def encrypted_portion @encrypted_portion ||= "" end |
#family_name ⇒ String?
Get family name from FontInfo
196 197 198 199 200 |
# File 'lib/fontisan/type1_font.rb', line 196 def family_name return @font_dictionary&.font_info&.family_name if @font_dictionary extract_fontinfo_value("FamilyName") end |
#font_dictionary ⇒ FontDictionary?
Returns Font dictionary.
47 48 49 50 |
# File 'lib/fontisan/type1_font.rb', line 47 def font_dictionary parse_dictionaries! unless @font_dictionary @font_dictionary end |
#font_name ⇒ String?
Get font name from font dictionary
178 179 180 181 182 |
# File 'lib/fontisan/type1_font.rb', line 178 def font_name return @font_dictionary&.font_name if @font_dictionary extract_dictionary_value("/FontName") end |
#full_name ⇒ String?
Get full name from FontInfo
187 188 189 190 191 |
# File 'lib/fontisan/type1_font.rb', line 187 def full_name return @font_dictionary&.font_info&.full_name if @font_dictionary extract_fontinfo_value("FullName") end |
#glyph_names ⇒ Array<String>
Get list of glyph names
214 215 216 217 218 |
# File 'lib/fontisan/type1_font.rb', line 214 def glyph_names return [] unless @charstrings @charstrings.glyph_names end |
#parse_dictionaries! ⇒ void
This method returns an undefined value.
Parse font dictionaries from decrypted data
Parses the font dictionary, private dictionary, and CharStrings from the decrypted font data.
162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/fontisan/type1_font.rb', line 162 def parse_dictionaries! decrypt! unless decrypted? # Parse font dictionary @font_dictionary = Type1::FontDictionary.parse(@decrypted_data) # Parse private dictionary @private_dict = Type1::PrivateDict.parse(@decrypted_data) # Parse CharStrings @charstrings = Type1::CharStrings.parse(@decrypted_data, @private_dict) end |
#parsed_dictionaries? ⇒ Boolean
Check if dictionaries have been parsed
223 224 225 |
# File 'lib/fontisan/type1_font.rb', line 223 def parsed_dictionaries? !@font_dictionary.nil? end |
#private_dict ⇒ PrivateDict?
Returns Private dictionary.
53 54 55 56 |
# File 'lib/fontisan/type1_font.rb', line 53 def private_dict parse_dictionaries! unless @private_dict @private_dict end |
#version ⇒ String?
Get version from FontInfo
205 206 207 208 209 |
# File 'lib/fontisan/type1_font.rb', line 205 def version return @font_dictionary&.font_info&.version if @font_dictionary extract_fontinfo_value("version") end |