freetype: text_size() so that users can retrieve the vertical size of a text too

pull/3497/head
Delyan Angelov 2020-01-18 21:08:11 +02:00 committed by Alexander Medvednikov
parent 09e390eac5
commit 8c1b03c731
3 changed files with 80 additions and 20 deletions

View File

@ -46,10 +46,16 @@ pub const (
)
struct Character {
code i64
texture_id u32
size gg.Vec2
bearing gg.Vec2
advance u32
horizontal_bearing_px gg.Vec2
horizontal_advance_px u32
vertical_bearing_px gg.Vec2
vertical_advance_px u32
}
[typedef]
@ -84,6 +90,19 @@ struct C.Bitmap {
struct C.Advance {
x int
y int
}
[typedef]
struct C.FT_Glyph_Metrics {
width int
height int
horiBearingX int
horiBearingY int
horiAdvance int
vertBearingX int
vertBearingY int
vertAdvance int
}
struct C.Glyph {
@ -91,11 +110,14 @@ struct C.Glyph {
bitmap_left int
bitmap_top int
advance Advance
metrics FT_Glyph_Metrics
}
[typedef]
struct C.FT_Face {
glyph &Glyph
family_name charptr
style_name charptr
}
fn C.FT_Load_Char(voidptr, i64, int) int
@ -104,12 +126,12 @@ fn ft_load_char(face C.FT_Face, code i64) Character {
//println('\nftload_char( code=$code)')
//C.printf('face=%p\n', face)
//C.printf('cobj=%p\n', _face.cobj)
ret := C.FT_Load_Char(face, code, C.FT_LOAD_RENDER)
ret := C.FT_Load_Char(face, code, C.FT_LOAD_RENDER|C.FT_LOAD_FORCE_AUTOHINT)
//println('ret=$ret')
if ret != 0 {
println('freetype: failed to load glyph (utf32 code=$code, ' +
'error code=$ret)')
return Character{}
return Character{code: code}
}
// Generate texture
mut texture := 0
@ -124,14 +146,19 @@ fn ft_load_char(face C.FT_Face, code i64) Character {
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_WRAP_T, C.GL_CLAMP_TO_EDGE)
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_LINEAR)
fgleft := face.glyph.bitmap_left
fgtop := face.glyph.bitmap_top
// Create the character
return Character {
code: code
texture_id: u32(texture)
size: gg.vec2(int(u32(fgwidth)), int(u32(fgrows)))
bearing: gg.vec2(int(u32(fgleft)), int(u32(fgtop)))
advance: (u32(face.glyph.advance.x))
size: gg.vec2(fgwidth, fgrows)
// Note: advance is number of 1/64 pixels
// Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
horizontal_bearing_px: gg.vec2(face.glyph.metrics.horiBearingX >> 6, face.glyph.metrics.horiBearingY >> 6)
vertical_bearing_px: gg.vec2(face.glyph.metrics.vertBearingX >> 6, face.glyph.metrics.vertBearingY >> 6) // not used for now
horizontal_advance_px: face.glyph.metrics.horiAdvance >> 6
vertical_advance_px: face.glyph.metrics.vertAdvance >> 6
}
}
@ -316,8 +343,8 @@ fn (ctx mut FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCf
//exit(1)
// continue
}
xpos := x + f32(ch.bearing.x) * 1
ypos := y - f32(ch.size.y - ch.bearing.y) * 1
xpos := x + f32(ch.horizontal_bearing_px.x) * 1
ypos := y - f32(ch.size.y - ch.horizontal_bearing_px.y) * 1
w := f32(ch.size.x) * 1
h := f32(ch.size.y) * 1
// Update VBO for each character
@ -337,9 +364,7 @@ fn (ctx mut FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCf
C.glBufferData(C.GL_ARRAY_BUFFER, 96, vertices.data, C.GL_DYNAMIC_DRAW)
// Render quad
gl.draw_arrays(C.GL_TRIANGLES, 0, 6)
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
// Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
x += ch.advance >> u32(6)
x += f32(ch.horizontal_advance_px)
}
gl.bind_vao(u32(0))
C.glBindTexture(C.GL_TEXTURE_2D, 0)
@ -355,12 +380,25 @@ pub fn (ctx mut FreeType) draw_text_def(x, y int, text string) {
}
pub fn (ctx mut FreeType) text_width(s string) int {
x, _ := ctx.text_size(s)
return x
}
pub fn (ctx mut FreeType) text_height(s string) int {
_, y := ctx.text_size(s)
return y
}
pub fn (ctx mut FreeType) text_size(s string) (int, int) {
//t := time.ticks()
utext := s.ustring()
mut x := f64(0)
mut x := u32(0)
mut maxy := u32(0)
mut _rune := ''
mut ch := Character{}
for i := 0; i < utext.len; i++ {
_rune := utext.at(i)
mut ch := Character{}
_rune = utext.at(i)
ch = Character{}
mut found := false
if _rune.len == 1 {
idx := _rune[0]
@ -387,10 +425,25 @@ pub fn (ctx mut FreeType) text_width(s string) int {
ctx.utf_runes << _rune
ctx.utf_chars << ch
}
x += ch.advance >> u32(6)
x += ch.horizontal_advance_px
if maxy < ch.vertical_advance_px {
maxy = ch.vertical_advance_px
}
}
//println('text width "$s" = ${time.ticks() - t} ms')
return int(x) / ctx.scale
scaled_x := int(f64(x) / ctx.scale)
scaled_y := int(f64(maxy) / ctx.scale)
//println('text_size of "${s}" | x,y: $x,$maxy | scaled_x: ${scaled_x:3d} | scaled_y: ${scaled_y:3d} ')
return scaled_x, scaled_y
}
pub fn (f FT_Face) str() string {
return 'FT_Face{ style_name: ${ptr_str(f.style_name)} family_name: ${ptr_str(f.family_name)} }'
}
pub fn (ac []Character) str() string {
mut res := []string
for c in ac {
res << ' Character{ code: $c.code , texture_id: $c.texture_id }'
}
return '[\n' + res.join(',\n') + ']'
}

View File

@ -17,6 +17,10 @@ pub:
y int
}
pub fn (v Vec2) str() string {
return 'Vec2{ x: $v.x y: $v.y }'
}
pub fn vec2(x, y int) Vec2 {
res := Vec2 {
x: x

View File

@ -13,6 +13,9 @@ import glm
pub struct Shader {
program_id int
}
pub fn (s Shader) str() string {
return 'Shader{ program_id: s.program_id }'
}
pub const (
TEXT_VERT = '#version 330 core