Class: Fontisan::Models::GlyphOutline

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/models/glyph_outline.rb

Overview

Represents a glyph's outline data with conversion capabilities

GlyphOutline is a pure data model that stores glyph outline information extracted from font tables. It provides methods to convert the outline data to various formats (SVG paths, drawing commands) for rendering and manipulation.

The outline consists of:

  • Contours: Array of closed paths, each containing points
  • Points: All points from all contours (flattened for easy access)
  • Bounding box: The glyph's bounding rectangle
  • Glyph ID: The identifier of this glyph

This class is immutable after construction to ensure data integrity.

Reference: docs/GETTING_STARTED.md:66-121

Examples:

Creating an outline

outline = Fontisan::Models::GlyphOutline.new(
  glyph_id: 65,
  contours: [
    [
      { x: 100, y: 0, on_curve: true },
      { x: 200, y: 700, on_curve: true },
      { x: 300, y: 0, on_curve: true }
    ]
  ],
  bbox: { x_min: 100, y_min: 0, x_max: 300, y_max: 700 }
)

Converting to SVG

svg_path = outline.to_svg_path
# => "M 100 0 L 200 700 L 300 0 Z"

Getting drawing commands

commands = outline.to_commands
# => [[:move_to, 100, 0], [:line_to, 200, 700], [:line_to, 300, 0], [:close_path]]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(glyph_id:, contours:, bbox:) ⇒ GlyphOutline

Initialize a new glyph outline

Parameters:

  • glyph_id (Integer)

    The glyph identifier

  • contours (Array<Array<Hash>>)

    Array of contours, each containing points Each point must have :x, :y, and :on_curve keys

  • bbox (Hash)

    Bounding box with :x_min, :y_min, :x_max, :y_max keys

Raises:

  • (ArgumentError)

    If required parameters are missing or invalid



63
64
65
66
67
68
69
70
# File 'lib/fontisan/models/glyph_outline.rb', line 63

def initialize(glyph_id:, contours:, bbox:)
  validate_parameters!(glyph_id, contours, bbox)

  @glyph_id = glyph_id.freeze
  @contours = deep_freeze(contours)
  @points = extract_all_points(contours).freeze
  @bbox = bbox.freeze
end

Instance Attribute Details

#bboxHash (readonly)

Returns Bounding box with keys: :x_min, :y_min, :x_max, :y_max.

Returns:

  • (Hash)

    Bounding box with keys: :x_min, :y_min, :x_max, :y_max



54
55
56
# File 'lib/fontisan/models/glyph_outline.rb', line 54

def bbox
  @bbox
end

#contoursArray<Array<Hash>> (readonly)

Returns Array of contours, each containing points Each point hash has keys: :x, :y, :on_curve.

Returns:

  • (Array<Array<Hash>>)

    Array of contours, each containing points Each point hash has keys: :x, :y, :on_curve



48
49
50
# File 'lib/fontisan/models/glyph_outline.rb', line 48

def contours
  @contours
end

#glyph_idInteger (readonly)

Returns The glyph identifier.

Returns:

  • (Integer)

    The glyph identifier



44
45
46
# File 'lib/fontisan/models/glyph_outline.rb', line 44

def glyph_id
  @glyph_id
end

#pointsArray<Hash> (readonly)

Returns All points from all contours (flattened).

Returns:

  • (Array<Hash>)

    All points from all contours (flattened)



51
52
53
# File 'lib/fontisan/models/glyph_outline.rb', line 51

def points
  @points
end

Instance Method Details

#contour_countInteger

Number of contours in outline

Returns:

  • (Integer)

    Number of contours



138
139
140
# File 'lib/fontisan/models/glyph_outline.rb', line 138

def contour_count
  contours.length
end

#empty?Boolean

Check if outline is empty (e.g., space glyph)

Returns:

  • (Boolean)

    True if the glyph has no contours



124
125
126
# File 'lib/fontisan/models/glyph_outline.rb', line 124

def empty?
  contours.empty?
end

#point_countInteger

Number of points in outline

Returns:

  • (Integer)

    Total number of points across all contours



131
132
133
# File 'lib/fontisan/models/glyph_outline.rb', line 131

def point_count
  points.length
end

#to_commandsArray<Array>

Convert to drawing commands

Returns an array of drawing command arrays that can be used to render the glyph. Each command is an array with the command type as the first element and coordinates as subsequent elements.

Command types:

  • :move_to - Move to a point without drawing
  • :line_to - Draw a straight line to a point
  • :curve_to - Draw a quadratic Bézier curve (TrueType) or cubic curve (CFF)
  • :close_path - Close the current path

Examples:

commands = outline.to_commands
# => [
#   [:move_to, 100, 0],
#   [:line_to, 200, 700],
#   [:line_to, 300, 0],
#   [:close_path]
# ]

Returns:

  • (Array<Array>)

    Array of [command, *args] arrays



111
112
113
114
115
116
117
118
119
# File 'lib/fontisan/models/glyph_outline.rb', line 111

def to_commands
  return [] if empty?

  commands = []
  contours.each do |contour|
    commands.concat(build_contour_commands(contour))
  end
  commands
end

#to_sString Also known as: inspect

String representation for debugging

Returns:

  • (String)

    Human-readable representation



145
146
147
148
149
# File 'lib/fontisan/models/glyph_outline.rb', line 145

def to_s
  "#<#{self.class.name} glyph_id=#{glyph_id} " \
    "contours=#{contour_count} points=#{point_count} " \
    "bbox=#{bbox.inspect}>"
end

#to_svg_pathString

Convert outline to SVG path data

Generates SVG path commands from the outline contours. Each contour becomes a closed path, with move_to for the first point, line_to or curve_to for subsequent points, and an explicit close path.

Returns:

  • (String)

    SVG path commands (e.g., "M 100 0 L 200 700 Z")



79
80
81
82
83
84
85
86
87
# File 'lib/fontisan/models/glyph_outline.rb', line 79

def to_svg_path
  return "" if empty?

  path_parts = contours.map do |contour|
    build_contour_path(contour)
  end

  path_parts.join(" ")
end