Class: SFML::Font

Inherits:
Object
  • Object
show all
Defined in:
lib/sfml/graphics/font.rb

Overview

A typeface loaded from a TTF/OTF file.

font = SFML::Font.default                                                # bundled DejaVu Sans
font = SFML::Font.load("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf")
font = SFML::Font.find("DejaVuSans")                                     # search common locations

Constant Summary collapse

SEARCH_PATHS =
[
  "/usr/share/fonts",
  "/usr/local/share/fonts",
  "/Library/Fonts",
  "/System/Library/Fonts",
  File.expand_path("~/Library/Fonts"),
  "C:/Windows/Fonts",
].freeze
DEFAULT_PATH =

Path to the font ruby-sfml ships with: DejaVu Sans (Bitstream Vera license, redistributable). See lib/sfml/assets/fonts/DejaVuSans.LICENSE.txt.

File.expand_path("../assets/fonts/DejaVuSans.ttf", __dir__).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#handle ⇒ Object (readonly)

:nodoc:



161
162
163
# File 'lib/sfml/graphics/font.rb', line 161

def handle
  @handle
end

Class Method Details

.default ⇒ Object

The default font bundled with ruby-sfml. Use this when you don't care which typeface as long as you can render text — examples, debug HUDs, prototypes. Memoized so subsequent calls return the same Font instance.



71
72
73
# File 'lib/sfml/graphics/font.rb', line 71

def self.default
  @default ||= load(DEFAULT_PATH)
end

.find(name) ⇒ Object

Look up a font on disk by basename (with or without extension). Useful for examples that should "just run" — production code should ship its own font files. Returns nil if nothing is found.



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/sfml/graphics/font.rb', line 78

def self.find(name)
  target = name.to_s.downcase.sub(/\.(ttf|otf)\z/, "")
  SEARCH_PATHS.each do |dir|
    next unless File.directory?(dir)
    match = Dir.glob(File.join(dir, "**", "*.{ttf,otf}")).find do |path|
      File.basename(path).downcase.sub(/\.(ttf|otf)\z/, "") == target
    end
    return load(match) if match
  end
  nil
end

.from_memory(bytes) ⇒ Object

Load a font from a Ruby String of bytes — useful when the font lives inside a data: URL, an embedded asset, or a network response. The bytes are copied by SFML before this call returns; the caller's String can be GC'd safely.

Raises:

  • (ArgumentError)


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/sfml/graphics/font.rb', line 35

def self.from_memory(bytes)
  raise ArgumentError, "expected a String, got #{bytes.class}" unless bytes.is_a?(String)

  buf = FFI::MemoryPointer.new(:uint8, bytes.bytesize)
  buf.write_bytes(bytes)
  ptr = C::Graphics.sfFont_createFromMemory(buf, bytes.bytesize)
  raise LoadError, "sfFont_createFromMemory returned NULL" if ptr.null?

  font = allocate
  font.send(:_take_ownership, ptr)
  # CSFML doesn't copy the font bytes — keep them pinned so the
  # GC doesn't free them while CSFML still references the buffer.
  font.instance_variable_set(:@_memory_pin, buf)
  font
end

.from_stream(io) ⇒ Object

Load a TTF/OTF from any Ruby IO-like object — file, in-memory, network-backed reader. Keep the IO open until the Font is no longer in use; CSFML reads glyphs lazily.

Raises:



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/sfml/graphics/font.rb', line 54

def self.from_stream(io)
  stream = SFML::InputStream.new(io)
  ptr = C::Graphics.sfFont_createFromStream(stream.to_ptr)
  raise LoadError, "sfFont_createFromStream returned NULL" if ptr.null?

  font = allocate
  font.send(:_take_ownership, ptr)
  # CSFML reads the font lazily from this stream — keep it pinned.
  font.instance_variable_set(:@_stream_pin, stream)
  font.instance_variable_set(:@_io_pin, io)
  font
end

.load(path) ⇒ Object

Returns the self.

Raises:



22
23
24
25
26
27
28
29
# File 'lib/sfml/graphics/font.rb', line 22

def self.load(path)
  ptr = C::Graphics.sfFont_createFromFile(path.to_s)
  raise LoadError, "Could not load font from #{path.inspect}" if ptr.null?

  font = allocate
  font.send(:_take_ownership, ptr)
  font
end

Instance Method Details

#dup ⇒ Object Also known as: clone

Deep copy. The returned font has its own atlas state; mutate one without affecting the other.

Raises:



151
152
153
154
155
156
157
158
# File 'lib/sfml/graphics/font.rb', line 151

def dup
  ptr = C::Graphics.sfFont_copy(@handle)
  raise GraphicsError, "sfFont_copy returned NULL" if ptr.null?

  font = self.class.allocate
  font.send(:_take_ownership, ptr)
  font
end

#family ⇒ Object

Human-readable family name (e.g. "DejaVu Sans"). Read once via sfFont_getInfo — CSFML returns a static C string from FreeType so we copy out into a Ruby String.



101
102
103
104
# File 'lib/sfml/graphics/font.rb', line 101

def family
  info = C::Graphics.sfFont_getInfo(@handle)
  info[:family].null? ? nil : info[:family].read_string
end

#has_glyph?(codepoint) ⇒ Boolean

true if the font has a glyph for the given Unicode codepoint (Integer) or single-character String.

Returns:

  • (Boolean)


108
109
110
111
# File 'lib/sfml/graphics/font.rb', line 108

def has_glyph?(codepoint)
  cp = codepoint.is_a?(String) ? codepoint.codepoints.first : Integer(codepoint)
  C::Graphics.sfFont_hasGlyph(@handle, cp || 0)
end

#kerning(first, second, character_size:, bold: false) ⇒ Object

Horizontal kerning offset between two adjacent glyphs at the given character size. Float, in pixels (often negative — the kern pulls the second glyph leftward).



116
117
118
119
120
121
# File 'lib/sfml/graphics/font.rb', line 116

def kerning(first, second, character_size:, bold: false)
  a = first.is_a?(String)  ? first.codepoints.first  : Integer(first)
  b = second.is_a?(String) ? second.codepoints.first : Integer(second)
  fn = bold ? :sfFont_getBoldKerning : :sfFont_getKerning
  C::Graphics.send(fn, @handle, a || 0, b || 0, Integer(character_size))
end

#line_spacing(character_size) ⇒ Object

Distance between two consecutive baselines for the given character size. Float, in pixels.



125
126
127
# File 'lib/sfml/graphics/font.rb', line 125

def line_spacing(character_size)
  C::Graphics.sfFont_getLineSpacing(@handle, Integer(character_size))
end

#smooth=(value) ⇒ Object

Set the smooth.



94
95
96
# File 'lib/sfml/graphics/font.rb', line 94

def smooth=(value)
  C::Graphics.sfFont_setSmooth(@handle, !!value)
end

#smooth? ⇒ Boolean

true if smooth.

Returns:

  • (Boolean)


91
# File 'lib/sfml/graphics/font.rb', line 91

def smooth?       = C::Graphics.sfFont_isSmooth(@handle)

#texture(character_size) ⇒ Object

The internal glyph atlas as a SFML::Texture (read-only — we don't own the pointer; CSFML keeps it alive as long as the font does).



143
144
145
146
147
# File 'lib/sfml/graphics/font.rb', line 143

def texture(character_size)
  ptr = C::Graphics.sfFont_getTexture(@handle, Integer(character_size))
  return nil if ptr.null?
  Texture.send(:_borrow, ptr)
end

#underline_position(character_size) ⇒ Object

Vertical offset of the underline from the baseline (positive values point downward). Float, in pixels.



131
132
133
# File 'lib/sfml/graphics/font.rb', line 131

def underline_position(character_size)
  C::Graphics.sfFont_getUnderlinePosition(@handle, Integer(character_size))
end

#underline_thickness(character_size) ⇒ Object

Thickness of the underline stroke. Float, in pixels.



136
137
138
# File 'lib/sfml/graphics/font.rb', line 136

def underline_thickness(character_size)
  C::Graphics.sfFont_getUnderlineThickness(@handle, Integer(character_size))
end