Class: Fontisan::Tables::Cff::DictBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/tables/cff/dict_builder.rb

Overview

CFF DICT (Dictionary) structure builder

[‘DictBuilder`](lib/fontisan/tables/cff/dict_builder.rb) constructs binary DICT structures from hash representations. DICTs in CFF use a compact operand-operator format similar to PostScript.

The builder encodes operands in various compact formats and writes operators according to the CFF specification.

Operand Encoding:

  • Small integers (-107 to +107): Single byte (32-246)

  • Medium integers (108 to 1131): Two bytes (247-250 + byte)

  • Medium integers (-1131 to -108): Two bytes (251-254 + byte)

  • Larger integers: Three bytes (28 + 2 bytes) or five bytes (29 + 4 bytes)

  • Real numbers: Nibble-encoded (30 + nibbles + 0xF terminator)

Operators:

  • Single-byte: 0-21

  • Two-byte: 12 followed by second byte

Reference: CFF specification section 4 “DICT Data” adobe-type-tools.github.io/font-tech-notes/pdfs/5176.CFF.pdf

Examples:

Building a DICT

dict_hash = { version: 391, notice: 392, charset: 0 }
dict_data = Fontisan::Tables::Cff::DictBuilder.build(dict_hash)

Constant Summary collapse

OPERATORS =

Operator mapping (name => byte(s))

{
  version: 0,
  notice: 1,
  full_name: 2,
  family_name: 3,
  weight: 4,
  charset: 15,
  encoding: 16,
  charstrings: 17,
  private: 18,
  copyright: [12, 0],
  is_fixed_pitch: [12, 1],
  italic_angle: [12, 2],
  underline_position: [12, 3],
  underline_thickness: [12, 4],
  paint_type: [12, 5],
  charstring_type: [12, 6],
  font_matrix: [12, 7],
  stroke_width: [12, 8],
  synthetic_base: [12, 20],
  postscript: [12, 21],
  base_font_name: [12, 22],
  base_font_blend: [12, 23],
  # Private DICT operators
  subrs: 19,
  default_width_x: 20,
  nominal_width_x: 21,
}.freeze

Class Method Summary collapse

Class Method Details

.build(dict_hash) ⇒ String

Build DICT structure from hash

Parameters:

  • dict_hash (Hash)

    Hash of operator => value pairs

Returns:

  • (String)

    Binary DICT data

Raises:

  • (ArgumentError)

    If dict_hash is invalid



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/fontisan/tables/cff/dict_builder.rb', line 70

def self.build(dict_hash)
  validate_dict!(dict_hash)

  return "".b if dict_hash.empty?

  output = StringIO.new("".b)

  # Encode each operator with its operands
  dict_hash.each do |operator_name, value|
    # Get operator bytes
    operator_bytes = operator_for_name(operator_name)
    raise ArgumentError, "Unknown operator: #{operator_name}" unless operator_bytes

    # Write operands (value can be single value or array)
    if value.is_a?(Array)
      value.each { |v| write_operand(output, v) }
    else
      write_operand(output, value)
    end

    # Write operator
    write_operator(output, operator_bytes)
  end

  output.string
end