### Install TTFunk Gem Source: https://github.com/prawnpdf/ttfunk/blob/master/README.md This command installs the TTFunk library using RubyGems, the standard package manager for Ruby. Ensure you have Ruby and RubyGems installed. ```shell gem install ttfunk ``` -------------------------------- ### Basic TTFunk Font Parsing in Ruby Source: https://github.com/prawnpdf/ttfunk/blob/master/README.md Demonstrates basic usage of the TTFunk library to open a font file and extract font metadata such as name, ascent, and descent. This requires the TTFunk library to be installed. ```ruby require 'ttfunk' file = TTFunk::File.open("some/path/myfont.ttf") puts "name : #{file.name.font_name.join(', ')}" puts "ascent : #{file.ascent}" puts "descent : #{file.descent}" ``` -------------------------------- ### Encode Subset Fonts with Options Source: https://context7.com/prawnpdf/ttfunk/llms.txt Shows how to create a font subset, add characters, and encode the subset into binary format with specific options like kerning. ```ruby require 'ttfunk' require 'ttfunk/subset' font = TTFunk::File.open("/path/to/font.ttf") subset = TTFunk::Subset.for(font, :unicode) "ABCabc123".each_char { |c| subset.use(c.unpack1('U*')) } data_no_kern = subset.encode puts "Without kerning: #{data_no_kern.length} bytes" data_with_kern = subset.encode(kerning: true) puts "With kerning: #{data_with_kern.length} bytes" encoder_class = subset.encoder_klass puts "Encoder: #{encoder_class.name}" unicode_map = subset.to_unicode_map puts "Unicode map entries: #{unicode_map.length}" ``` -------------------------------- ### Opening and Reading Font Files in Ruby Source: https://context7.com/prawnpdf/ttfunk/llms.txt Demonstrates how to load TrueType or OpenType fonts from file paths or IO objects and access core metadata like font names, copyright, and metrics such as ascent, descent, and bounding boxes. ```ruby require 'ttfunk' # Open a TrueType or OpenType font file from path font = TTFunk::File.open("/path/to/font.ttf") # Open from an IO object File.open("/path/to/font.ttf", "rb") do |io| font = TTFunk::File.open(io) end # Access basic font information puts font.name.font_name.join(', ') # Full font name puts font.name.font_family.join(', ') # Font family puts font.name.font_subfamily.join(', ') # Font subfamily (Regular, Bold, etc.) puts font.name.postscript_name # PostScript name puts font.name.copyright.first # Copyright notice puts font.name.version.first # Version string # Access font metrics puts font.ascent # Ascent (positive value) puts font.descent # Descent (negative value) puts font.line_gap # Line gap puts font.bbox # Bounding box [x_min, y_min, x_max, y_max] puts font.header.units_per_em # Units per em (typically 1000 or 2048) ``` -------------------------------- ### Analyze Font Metadata and Metrics with TTFunk Source: https://context7.com/prawnpdf/ttfunk/llms.txt This script demonstrates how to open a font file using TTFunk and extract key information including font identification, metrics, table structures, and character widths. It requires a valid path to a TrueType or OpenType font file as input. ```ruby require 'ttfunk' def analyze_font(path) font = TTFunk::File.open(path) puts "=" * 60 puts "FONT ANALYSIS: #{File.basename(path)}" puts "=" * 60 puts "\n-- IDENTIFICATION --" puts "Name: #{font.name.font_name.first}" puts "Family: #{font.name.font_family.first}" puts "Subfamily: #{font.name.font_subfamily.first}" puts "PostScript: #{font.name.postscript_name}" puts "Version: #{font.name.version.first}" puts "\n-- FONT TYPE --" if font.cff.exists? puts "Type: OpenType with CFF outlines" else puts "Type: TrueType with glyf outlines" end puts "\n-- METRICS --" puts "Units per em: #{font.header.units_per_em}" puts "Ascent: #{font.ascent}" puts "Descent: #{font.descent}" puts "Line gap: #{font.line_gap}" puts "Bounding box: #{font.bbox.inspect}" puts "\n-- GLYPHS --" puts "Total glyphs: #{font.maximum_profile.num_glyphs}" puts "\n-- TABLES --" tables = font.directory.tables.keys.sort puts "Tables (#{tables.length}): #{tables.join(', ')}" puts "\n-- CHARACTER WIDTHS (in em) --" unicode_cmap = font.cmap.unicode.first units = font.header.units_per_em %w[A M W i l].each do |char| glyph_id = unicode_cmap[char.ord] if glyph_id && glyph_id > 0 width = font.horizontal_metrics.for(glyph_id).advance_width puts " '#{char}': #{(width.to_f / units).round(3)} em" end end font end font = analyze_font("/path/to/font.ttf") ``` -------------------------------- ### Calculate Font Metrics and String Widths Source: https://context7.com/prawnpdf/ttfunk/llms.txt Demonstrates how to retrieve glyph metrics and calculate the visual width of strings in font units, points, or em fractions. It uses the font's cmap and horizontal metrics tables to perform these calculations. ```ruby glyph_id = font.cmap.unicode.first["A".unpack1('U*')] metric = font.horizontal_metrics.for(glyph_id) puts "Advance width: #{metric.advance_width}" def string_width_in_units(font, text) unicode_cmap = font.cmap.unicode.first text.chars.sum do |char| glyph_id = unicode_cmap[char.unpack1('U*')] font.horizontal_metrics.for(glyph_id).advance_width end end units_per_em = font.header.units_per_em font_size = 12.0 width_in_points = (width.to_f / units_per_em) * font_size ``` -------------------------------- ### Manage Multi-Encoding with SubsetCollection Source: https://context7.com/prawnpdf/ttfunk/llms.txt Demonstrates how to use SubsetCollection to handle text with mixed scripts by automatically managing multiple font subsets. ```ruby require 'ttfunk' require 'ttfunk/subset_collection' font = TTFunk::File.open("/path/to/font.ttf") collection = TTFunk::SubsetCollection.new(font) text = "Hello World! \u4e2d\u6587 \u0410\u0411\u0412" characters = text.unpack('U*') encoded_chunks = collection.encode(characters) encoded_chunks.each do |subset_index, encoded_string| puts "Subset #{subset_index}: #{encoded_string.bytes.inspect}" subset = collection[subset_index] subset_font_data = subset.encode puts " Font size: #{subset_font_data.length} bytes" puts " Unicode?: #{subset.unicode?}" end ``` -------------------------------- ### Loading Fonts from DFont Resources Source: https://context7.com/prawnpdf/ttfunk/llms.txt Explains how to load fonts from Mac OS X data-fork suitcases (DFont) by index or name, and how to list available resources. ```ruby require 'ttfunk' # Load font from DFont by index font = TTFunk::File.from_dfont("/path/to/font.dfont", 0) # Load font from DFont by name font = TTFunk::File.from_dfont("/path/to/font.dfont", "FontName") # List available font resources in a DFont TTFunk::ResourceFile.open("/path/to/font.dfont") do |dfont| font_names = dfont.resources_for("sfnt") puts "Available fonts: #{font_names.join(', ')}" end ``` -------------------------------- ### Create Font Subsets for Embedding Source: https://context7.com/prawnpdf/ttfunk/llms.txt Provides instructions on how to create a subset of a font containing only the necessary glyphs for a specific text string. This is useful for reducing file size in PDF generation. ```ruby require 'ttfunk/subset' font = TTFunk::File.open("/path/to/font.ttf") subset = TTFunk::Subset.for(font, :unicode) text.each_char { |char| subset.use(char.unpack1('U*')) } subset_data = subset.encode File.binwrite("/path/to/subset.ttf", subset_data) ``` -------------------------------- ### TTFunk for PDF Generation with Prawn Source: https://context7.com/prawnpdf/ttfunk/llms.txt Explains the primary use case of TTFunk: server-side font processing for Prawn PDF generation. It highlights how TTFunk enables efficient font subsetting to reduce PDF file sizes while maintaining text fidelity. ```APIDOC ## TTFunk for PDF Generation TTFunk is primarily designed for server-side font processing in Ruby applications, particularly as a dependency for the Prawn PDF generation library. It enables efficient font embedding by creating minimal subsets containing only the characters used in a document, significantly reducing PDF file sizes while maintaining full text rendering fidelity. The library handles the complex details of font table parsing and encoding according to OpenType and TrueType specifications. It supports both traditional TrueType fonts with glyf outlines and modern CFF-based OpenType fonts, making it suitable for processing virtually any contemporary font format. For PDF workflows, TTFunk works seamlessly with Prawn to provide automatic font subsetting, Unicode mapping for searchable text, and proper metric calculations for text positioning. ``` -------------------------------- ### Inspect Glyph Outlines and Structures Source: https://context7.com/prawnpdf/ttfunk/llms.txt Shows how to access raw glyph outline data for TrueType and CFF fonts. It includes logic to identify simple versus compound glyphs and retrieve bounding box information. ```ruby glyph_id = font.cmap.unicode.first["A".unpack1('U*')] glyph = font.find_glyph(glyph_id) if glyph.compound? puts "Compound glyph with components: #{glyph.glyph_ids.inspect}" end if font.cff.exists? charstring = font.cff.top_index[0].charstrings_index[glyph_id] glyph = charstring.glyph end ``` -------------------------------- ### Font Analysis Script Source: https://context7.com/prawnpdf/ttfunk/llms.txt A Ruby script demonstrating how to use TTFunk to open a font file, analyze its properties, and extract key information such as identification, metrics, glyph count, and table presence. ```APIDOC ## Complete Example: Font Analysis Script A comprehensive example showing how to analyze a font file and extract useful information. ```ruby require 'ttfunk' def analyze_font(path) font = TTFunk::File.open(path) puts "=" * 60 puts "FONT ANALYSIS: #{File.basename(path)}" puts "=" * 60 # Basic identification puts "\n-- IDENTIFICATION --" puts "Name: #{font.name.font_name.first}" puts "Family: #{font.name.font_family.first}" puts "Subfamily: #{font.name.font_subfamily.first}" puts "PostScript: #{font.name.postscript_name}" puts "Version: #{font.name.version.first}" # Font type puts "\n-- FONT TYPE --" if font.cff.exists? puts "Type: OpenType with CFF outlines" else puts "Type: TrueType with glyf outlines" end # Metrics puts "\n-- METRICS --" puts "Units per em: #{font.header.units_per_em}" puts "Ascent: #{font.ascent}" puts "Descent: #{font.descent}" puts "Line gap: #{font.line_gap}" puts "Bounding box: #{font.bbox.inspect}" # Glyph count puts "\n-- GLYPHS --" puts "Total glyphs: #{font.maximum_profile.num_glyphs}" # Tables present puts "\n-- TABLES --" tables = font.directory.tables.keys.sort puts "Tables (#{tables.length}): #{tables.join(', ')}" # Sample character widths puts "\n-- CHARACTER WIDTHS (in em) --" unicode_cmap = font.cmap.unicode.first units = font.header.units_per_em %w[A M W i l].each do |char| glyph_id = unicode_cmap[char.ord] if glyph_id && glyph_id > 0 width = font.horizontal_metrics.for(glyph_id).advance_width puts " '#{char}': #{(width.to_f / units).round(3)} em" end end font end # Usage font = analyze_font("/path/to/font.ttf") ``` ``` -------------------------------- ### Mapping Characters to Glyphs (cmap) Source: https://context7.com/prawnpdf/ttfunk/llms.txt Demonstrates how to use the cmap table to look up glyph IDs for specific characters and verify if a font supports a particular Unicode character. ```ruby require 'ttfunk' font = TTFunk::File.open("/path/to/font.ttf") # Get the Unicode cmap subtable (most commonly used) unicode_cmap = font.cmap.unicode.first # Look up glyph ID for a character character = "A" character_code = character.unpack1('U*') # Get Unicode code point glyph_id = unicode_cmap[character_code] puts "Character '#{character}' (U+#{character_code.to_s(16).upcase}) -> Glyph ID #{glyph_id}" # Look up multiple characters "Hello".each_char do |char| code = char.unpack1('U*') glyph = unicode_cmap[code] puts "#{char} (U+#{code.to_s(16).upcase.rjust(4, '0')}) -> Glyph #{glyph}" end # Check if font supports a character def supports_character?(font, char) code = char.unpack1('U*') glyph_id = font.cmap.unicode.first[code] glyph_id && glyph_id != 0 end puts supports_character?(font, "\u2603") # Snowman character ``` -------------------------------- ### Access Kerning Data and Calculate Kerned Width Source: https://context7.com/prawnpdf/ttfunk/llms.txt Explains how to check for kerning tables in a font, retrieve specific kerning pair adjustments, and calculate the total width of a string while accounting for kerning between adjacent glyphs. ```ruby if font.kerning.exists? && font.kerning.tables.any? kern_table = font.kerning.tables.first kern_value = kern_table.pairs[[left_glyph, right_glyph]] || 0 def kerned_string_width(font, text) # ... implementation iterating through glyphs and adding kern.pairs[pair] ... end end ``` -------------------------------- ### Loading Fonts from TrueType Collections (TTC) Source: https://context7.com/prawnpdf/ttfunk/llms.txt Shows how to extract specific fonts from a TrueType Collection file using indices or by iterating through the entire collection. ```ruby require 'ttfunk' # Load a specific font from a TTC collection by index font = TTFunk::File.from_ttc("/path/to/fonts.ttc", 0) # First font font = TTFunk::File.from_ttc("/path/to/fonts.ttc", 1) # Second font # Iterate over all fonts in a collection TTFunk::Collection.open("/path/to/fonts.ttc") do |collection| puts "Collection contains #{collection.count} fonts" collection.each do |font| puts "Font: #{font.name.font_name.first}" puts " Family: #{font.name.font_family.first}" end end # Access a specific font by index within the block TTFunk::Collection.open("/path/to/fonts.ttc") do |collection| font = collection[2] # Get third font puts font.name.postscript_name end ``` -------------------------------- ### Inspect Glyph Mapping Source: https://context7.com/prawnpdf/ttfunk/llms.txt Displays the original glyph IDs and the mapping between old and new glyph IDs for a subset. ```ruby puts "Original glyph IDs used: #{subset.original_glyph_ids}" puts "Glyph ID mapping (old => new): #{subset.old_to_new_glyph}" ``` -------------------------------- ### Access Font Table Information Source: https://context7.com/prawnpdf/ttfunk/llms.txt Retrieves and displays detailed metrics and metadata from various font tables including head, hhea, maxp, OS/2, and post tables. ```ruby require 'ttfunk' font = TTFunk::File.open("/path/to/font.ttf") head = font.header puts "Units per em: #{head.units_per_em}" hhea = font.horizontal_header puts "Ascent: #{hhea.ascent}" maxp = font.maximum_profile puts "Number of glyphs: #{maxp.num_glyphs}" if font.os2.exists? os2 = font.os2 puts "Weight class: #{os2.weight_class}" end post = font.postscript puts "Italic angle: #{post.italic_angle}" puts "Has CFF (OpenType): #{font.cff.exists?}" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.