gamnit :: Font :: write_into
TextSprites.text=
# Backend writing service, clients should use `TextSprites.text=`
protected fun write_into(text_sprites: TextSprites, text: Text) is abstract
lib/gamnit/font.nit:29,2--30,76
redef fun write_into(text_sprites, text)
do
var dx = 0.0
var dy = 0.0
var text_width = 0.0
var line_sprites = new Array[Sprite]
var height = 0.0
# Has the current line height been added to `height`?
var line_height_counted = false
# TextSprite customization
var max_width = text_sprites.max_width
var max_height = text_sprites.max_height
var scale = text_sprites.scale
# Font customization
var line_height = desc.line_height * scale
var partial_line_skip = line_height * partial_line_mod.to_f
# Links data
text_sprites.links.clear
var in_link = false
var link_sprites = new Array[Sprite]
var link_name = ""
# Loop over all characters
var prev_char = null
var i = -1
while i < text.length - 1 do
i += 1
var c = text[i]
# Special characters
var word_break = false
if c == '\n' then
justify(line_sprites, text_sprites.align, dx)
dy -= line_height
if max_height != null and max_height < -dy + line_height then break
dx = 0.0
if not line_height_counted then
# Force to account for empty lines
height += line_height
end
line_height_counted = false
prev_char = null
continue
else if c == pld then
dy -= partial_line_skip
height += partial_line_skip
word_break = true
continue
else if c == plu then
dy += partial_line_skip
height -= partial_line_skip # We could keep two heights and return the max
word_break = true
continue
else if c.is_whitespace then
var space_advance = if desc.chars.keys.has(' ') then
desc.chars[' '].xadvance
else if desc.chars.keys.has('f') then
desc.chars['f'].xadvance
else 16.0
dx += space_advance * scale
word_break = true
else if c == '[' then
# Open link?
if i + 1 < text.length and text[i+1] == '[' then
# Escape if duplicated
i += 1
else
in_link = true
continue
end
else if c == ']' then
# Close link?
if i + 1 < text.length and text[i+1] == ']' then
# Escape if duplicated
i += 1
else
# If there's a () use it as link_name
var j = i + 1
if j < text.length and text[j] == '(' then
var new_name
new_name = ""
loop
j += 1
if j > text.length then
# No closing ), abort
new_name = null
break
end
var l = text[j]
if l == ')' then break
new_name += l.to_s
end
if new_name != null then
link_name = new_name
i = j
end
end
# Register the link for the clients
text_sprites.links[link_name] = link_sprites
# Prepare next link
in_link = false
link_sprites = new Array[Sprite]
link_name = ""
continue
end
end
if in_link then link_name += c.to_s
# End of a word?
if word_break then
# If we care about line width, check for overflow
if max_width != null then
# Calculate the length of the next word
var prev_w = null
var word_len = 0.0
for wi in [i+1..text.length[ do
var w = text[wi]
if w == '\n' or w == pld or w == plu or w.is_whitespace or (in_link and w == ']') then break
if not desc.chars.keys.has(w) then
var rc = replacement_char
if rc == null then continue
w = rc
end
word_len += advance(prev_w, w) * scale
prev_w = w
end
# Would the line be too long?
if dx + word_len > max_width then
justify(line_sprites, text_sprites.align, dx)
dy -= line_height
if max_height != null and max_height < -dy + line_height then break
dx = 0.0
line_height_counted = false
if not text_sprites.wrap then
# Cut short, skip everything until the next new line
while c != '\n' and i < text.length - 1 do
i += 1
c = text[i]
end
end
end
end
prev_char = null
continue
end
# Replace or skip unknown characters
if not desc.chars.keys.has(c) then
var rc = replacement_char
if rc == null then continue
c = rc
end
var char_info = desc.chars[c]
var advance = char_info.xadvance
var kerning = desc.kerning(prev_char, c)
var x = dx + (char_info.width/2.0 + char_info.xoffset + kerning) * scale
var y = dy - (char_info.height/2.0 + char_info.yoffset) * scale
var pos = text_sprites.anchor.offset(x, y, 0.0)
var s = new Sprite(char_info.subtexture, pos)
s.scale = scale * char_info.scale
text_sprites.sprites.add s
line_sprites.add s
if in_link then link_sprites.add s
dx += (advance + kerning) * scale
prev_char = c
text_width = text_width.max(dx)
if not line_height_counted then
# Increase `height` only once per line iff there's a caracter
line_height_counted = true
height += line_height
end
end
justify(line_sprites, text_sprites.align, dx)
# valign
if text_sprites.valign != 0.0 then
var d = (-dy+line_height) * text_sprites.valign
for s in text_sprites.sprites do s.center.y += d
end
text_sprites.width = text_width.max(dx)
text_sprites.height = height
end
lib/gamnit/bmfont.nit:364,2--566,4
redef fun write_into(text_sprites, text)
do
# Build new sprites
var dx = advance/2.0
var dy = hspace.to_f/2.0
for c in text do
if c == '\n' then
dy -= height.to_f + vspace.to_f
dx = advance/2.0
continue
else if c == pld then
dy -= (height.to_f + vspace.to_f) * partial_line_mod.to_f
continue
else if c == plu then
dy += (height.to_f + vspace.to_f) * partial_line_mod.to_f
continue
else if c.is_whitespace then
dx += advance
continue
end
var tex = char(c)
if tex == null then
# Try to fallback to '?'
tex = char('?')
if tex == null then continue
end
text_sprites.sprites.add new Sprite(tex, text_sprites.anchor.offset(dx, dy, 0))
dx += advance
end
end
lib/gamnit/tileset.nit:123,2--154,4