2019-07-10 13:27:35 +02:00
|
|
|
|
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
module freetype
|
2019-07-10 13:27:35 +02:00
|
|
|
|
|
2019-08-05 10:42:58 +02:00
|
|
|
|
import (
|
2019-08-20 13:34:29 +02:00
|
|
|
|
os
|
|
|
|
|
gx
|
|
|
|
|
gg
|
2019-08-08 10:08:39 +02:00
|
|
|
|
glm
|
|
|
|
|
gl
|
2019-08-20 13:34:29 +02:00
|
|
|
|
)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
|
2019-08-26 12:51:48 +02:00
|
|
|
|
#flag windows -I @VROOT/thirdparty/freetype/include
|
|
|
|
|
#flag windows -L @VROOT/thirdparty/freetype/win64
|
|
|
|
|
|
2019-08-09 15:06:03 +02:00
|
|
|
|
#flag darwin -I/usr/local/include/freetype2
|
|
|
|
|
#flag darwin -I/opt/local/include/freetype2
|
2019-08-20 13:34:29 +02:00
|
|
|
|
#flag -lfreetype
|
2019-07-10 13:27:35 +02:00
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
//#flag -I @VROOT/thirdparty/freetype
|
2019-08-05 10:42:58 +02:00
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
//#flag @VROOT/thirdparty/freetype/libfreetype.a
|
|
|
|
|
#flag darwin -lpng -lbz2 -lz
|
2019-07-10 13:27:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#flag linux -I/usr/include/freetype2
|
|
|
|
|
#flag linux -I.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "ft2build.h"
|
|
|
|
|
#include FT_FREETYPE_H
|
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
|
|
|
|
|
|
2019-08-05 10:42:58 +02:00
|
|
|
|
const (
|
|
|
|
|
DEFAULT_FONT_SIZE = 12
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
struct Character {
|
|
|
|
|
texture_id u32
|
|
|
|
|
size gg.Vec2
|
|
|
|
|
bearing gg.Vec2
|
|
|
|
|
advance u32
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
[typedef]
|
|
|
|
|
struct C.FT_Library {
|
2019-09-22 16:24:15 +02:00
|
|
|
|
_z int
|
2019-08-20 13:34:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-08 16:43:11 +02:00
|
|
|
|
struct Context {
|
2019-07-10 13:27:35 +02:00
|
|
|
|
shader gl.Shader
|
|
|
|
|
// use_ortho bool
|
|
|
|
|
width int
|
|
|
|
|
height int
|
2019-08-05 10:42:58 +02:00
|
|
|
|
vao u32
|
2019-07-10 13:27:35 +02:00
|
|
|
|
rect_vao u32
|
|
|
|
|
rect_vbo u32
|
|
|
|
|
line_vao u32
|
|
|
|
|
line_vbo u32
|
2019-08-05 10:42:58 +02:00
|
|
|
|
vbo u32
|
|
|
|
|
chars []Character
|
2019-08-26 21:40:07 +02:00
|
|
|
|
face C.FT_Face
|
2019-07-10 13:27:35 +02:00
|
|
|
|
scale int // retina = 2 , normal = 1
|
2019-08-30 19:19:06 +02:00
|
|
|
|
mut:
|
|
|
|
|
utf_runes []string
|
|
|
|
|
utf_chars []Character
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
struct C.Bitmap {
|
|
|
|
|
width int
|
|
|
|
|
rows int
|
|
|
|
|
buffer int
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
struct C.Advance {
|
|
|
|
|
x int
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct C.Glyph {
|
|
|
|
|
bitmap Bitmap
|
|
|
|
|
bitmap_left int
|
|
|
|
|
bitmap_top int
|
|
|
|
|
advance Advance
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[typedef]
|
|
|
|
|
struct C.FT_Face {
|
2019-09-03 08:04:11 +02:00
|
|
|
|
glyph &Glyph
|
2019-08-20 13:34:29 +02:00
|
|
|
|
}
|
2019-08-05 10:42:58 +02:00
|
|
|
|
|
2019-08-26 21:40:07 +02:00
|
|
|
|
fn C.FT_Load_Char(voidptr, i64, int) int
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
//println('ret=$ret')
|
2019-08-20 13:34:29 +02:00
|
|
|
|
if ret != 0 {
|
|
|
|
|
println('freetype: failed to load glyph (utf32 code=$code, ' +
|
|
|
|
|
'error code=$ret)')
|
|
|
|
|
return Character{}
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
// Generate texture
|
2019-08-20 13:34:29 +02:00
|
|
|
|
mut texture := 0
|
|
|
|
|
C.glGenTextures(1, &texture)
|
|
|
|
|
C.glBindTexture(C.GL_TEXTURE_2D, texture)
|
|
|
|
|
fgwidth := face.glyph.bitmap.width
|
|
|
|
|
fgrows := face.glyph.bitmap.rows
|
|
|
|
|
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RED, fgwidth, fgrows,
|
|
|
|
|
0, C.GL_RED, C.GL_UNSIGNED_BYTE, face.glyph.bitmap.buffer)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// Set texture options
|
2019-08-22 23:00:31 +02:00
|
|
|
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_WRAP_S, C.GL_CLAMP_TO_EDGE)
|
|
|
|
|
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)
|
2019-08-20 13:34:29 +02:00
|
|
|
|
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 {
|
|
|
|
|
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))
|
|
|
|
|
}
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-03 08:04:11 +02:00
|
|
|
|
pub fn new_context(cfg gg.Cfg) &Context {
|
2019-08-20 13:34:29 +02:00
|
|
|
|
scale := cfg.scale
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// Can only have text in ortho mode
|
|
|
|
|
if !cfg.use_ortho {
|
2019-08-20 13:34:29 +02:00
|
|
|
|
return &Context{}
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
mut width := cfg.width * scale
|
|
|
|
|
mut height := cfg.height * scale
|
|
|
|
|
font_size := cfg.font_size * scale
|
|
|
|
|
// exit('fs=$font_size')
|
|
|
|
|
// if false {
|
|
|
|
|
// retina
|
|
|
|
|
// width = width * 2// scale// 2
|
|
|
|
|
// height = height * 2// scale// 2
|
|
|
|
|
// font_size *= scale// 2
|
|
|
|
|
// }
|
2019-08-20 13:34:29 +02:00
|
|
|
|
/*
|
2019-07-10 13:27:35 +02:00
|
|
|
|
gl.viewport(0, 0, width, height)
|
|
|
|
|
*/
|
2019-08-20 13:34:29 +02:00
|
|
|
|
// gl.enable(GL_CULL_FACE) // TODO NEED CULL?
|
2019-08-22 23:00:31 +02:00
|
|
|
|
gl.enable(C.GL_BLEND)
|
2019-08-20 13:34:29 +02:00
|
|
|
|
C.glBlendFunc(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
shader := gl.new_shader('text')
|
|
|
|
|
shader.use()
|
|
|
|
|
projection := glm.ortho(0, width, 0, height)// 0 at BOT
|
|
|
|
|
shader.set_mat4('projection', projection)
|
|
|
|
|
// FREETYPE
|
2019-09-22 16:24:15 +02:00
|
|
|
|
ft := FT_Library{0}
|
2019-08-20 13:34:29 +02:00
|
|
|
|
// All functions return a value different than 0 whenever
|
|
|
|
|
// an error occurred
|
|
|
|
|
mut ret := C.FT_Init_FreeType(&ft)
|
|
|
|
|
if ret != 0 {
|
|
|
|
|
panic('freetype: Could not init FreeType Library')
|
|
|
|
|
}
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// Load font as face
|
2019-08-09 16:48:19 +02:00
|
|
|
|
mut font_path := cfg.font_path
|
|
|
|
|
if font_path == '' {
|
|
|
|
|
font_path = 'RobotoMono-Regular.ttf'
|
|
|
|
|
}
|
2019-07-10 13:27:35 +02:00
|
|
|
|
if !os.file_exists(font_path) {
|
2019-08-05 10:42:58 +02:00
|
|
|
|
exe_path := os.executable()
|
|
|
|
|
exe_dir := os.basedir(exe_path)
|
2019-08-09 16:48:19 +02:00
|
|
|
|
font_path = '$exe_dir/$font_path'
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
if !os.file_exists(font_path) {
|
2019-08-09 16:48:19 +02:00
|
|
|
|
println('failed to load $font_path')
|
2019-08-09 07:28:37 +02:00
|
|
|
|
return 0
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
2019-08-09 16:48:19 +02:00
|
|
|
|
println('Trying to load font from $font_path')
|
2019-08-20 13:34:29 +02:00
|
|
|
|
face := C.FT_Face{}
|
|
|
|
|
ret = int(C.FT_New_Face(ft, font_path.str, 0, &face))
|
|
|
|
|
if ret != 0 {
|
|
|
|
|
println('freetype: failed to load the font (error=$ret)')
|
2019-07-10 13:27:35 +02:00
|
|
|
|
exit(1)
|
|
|
|
|
}
|
|
|
|
|
// Set size to load glyphs as
|
2019-08-20 13:34:29 +02:00
|
|
|
|
C.FT_Set_Pixel_Sizes(face, 0, font_size)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// Disable byte-alignment restriction
|
2019-08-20 13:34:29 +02:00
|
|
|
|
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 1)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// Gen texture
|
|
|
|
|
// Load first 128 characters of ASCII set
|
2019-08-05 10:42:58 +02:00
|
|
|
|
mut chars := []Character{}
|
2019-07-10 13:27:35 +02:00
|
|
|
|
for c := 0; c < 128; c++ {
|
2019-08-26 21:40:07 +02:00
|
|
|
|
mut ch := ft_load_char(face, i64(c))
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// s := utf32_to_str(uint(0x043f))
|
|
|
|
|
// s := 'п'
|
|
|
|
|
// ch = ft_load_char(f, s.utf32_code())
|
|
|
|
|
// # unsigned long c = FT_Get_Char_Index(face, 0x043f );
|
|
|
|
|
// # printf("!!!!!!!!! %lu\n", c);
|
|
|
|
|
// # c = FT_Get_Char_Index(face, 0xd0bf );
|
|
|
|
|
// # printf("!!!!!!!!! %lu\n", c);
|
|
|
|
|
// # ch = gg__ft_load_char(f, 0xd0bf) ; // UTF 8
|
|
|
|
|
chars << ch
|
|
|
|
|
}
|
|
|
|
|
ch := Character{}
|
|
|
|
|
// Configure VAO
|
2019-08-05 10:42:58 +02:00
|
|
|
|
vao := gl.gen_vertex_array()
|
|
|
|
|
println('new gg text context vao=$vao')
|
|
|
|
|
vbo := gl.gen_buffer()
|
|
|
|
|
gl.bind_vao(vao)
|
2019-08-22 23:00:31 +02:00
|
|
|
|
gl.bind_buffer(C.GL_ARRAY_BUFFER, vbo)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// # glBufferData(GL_ARRAY_BUFFER, sizeof(GLf32) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
|
|
|
|
gl.enable_vertex_attrib_array(0)
|
2019-08-22 23:00:31 +02:00
|
|
|
|
gl.vertex_attrib_pointer(0, 4, C.GL_FLOAT, false, 4, 0)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// # glVertexAttribPointer(0, 4, GL_FLOAT,false, 4 * sizeof(GLf32), 0);
|
|
|
|
|
// gl.bind_buffer(GL_ARRAY_BUFFER, uint(0))
|
|
|
|
|
// # glBindVertexArray(0);
|
2019-08-08 16:43:11 +02:00
|
|
|
|
mut ctx := &Context {
|
2019-08-20 13:34:29 +02:00
|
|
|
|
shader: shader
|
|
|
|
|
width: width
|
|
|
|
|
height: height
|
2019-07-10 13:27:35 +02:00
|
|
|
|
scale: scale
|
2019-08-20 13:34:29 +02:00
|
|
|
|
vao: vao
|
|
|
|
|
vbo: vbo
|
|
|
|
|
chars: chars
|
2019-08-26 21:40:07 +02:00
|
|
|
|
face: face
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
2019-08-26 21:40:07 +02:00
|
|
|
|
//ctx.init_utf8_runes()
|
2019-07-10 13:27:35 +02:00
|
|
|
|
return ctx
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-26 21:40:07 +02:00
|
|
|
|
/*
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// A dirty hack to implement rendering of cyrillic letters.
|
2019-08-26 21:40:07 +02:00
|
|
|
|
// All UTF-8 must be supported. update: no longer needed
|
2019-08-08 16:43:11 +02:00
|
|
|
|
fn (ctx mut Context) init_utf8_runes() {
|
2019-08-18 14:02:30 +02:00
|
|
|
|
s := '≈≠⩽⩾йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ'
|
2019-08-20 13:34:29 +02:00
|
|
|
|
print('init utf8 runes: ')
|
|
|
|
|
//println(s)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
us := s.ustring()
|
|
|
|
|
for i := 0; i < us.len; i++ {
|
|
|
|
|
_rune := us.at(i)
|
|
|
|
|
ch := ft_load_char(ctx.face, _rune.utf32_code())
|
|
|
|
|
// ctx.utf_rune_map.set(rune, ch)
|
|
|
|
|
ctx.utf_runes << _rune
|
|
|
|
|
ctx.utf_chars << ch
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-08-26 21:40:07 +02:00
|
|
|
|
*/
|
2019-07-10 13:27:35 +02:00
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
pub fn (ctx mut Context) draw_text(_x, _y int, text string, cfg gx.TextCfg) {
|
2019-08-18 17:11:17 +02:00
|
|
|
|
//utext := text.ustring_tmp()
|
|
|
|
|
utext := text.ustring()
|
2019-08-07 13:00:19 +02:00
|
|
|
|
ctx._draw_text(_x, _y, utext, cfg)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
fn (ctx mut Context) draw_text_fast(_x, _y int, text ustring, cfg gx.TextCfg) {
|
2019-08-08 16:43:11 +02:00
|
|
|
|
ctx._draw_text(_x, _y, text, cfg)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
fn (ctx mut Context) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
|
|
|
|
|
/*
|
2019-07-10 13:27:35 +02:00
|
|
|
|
if utext.s.contains('on_seg') {
|
|
|
|
|
println('\nat(0)')
|
|
|
|
|
println(utext.runes)
|
|
|
|
|
firstc := utext.at(0)
|
|
|
|
|
println('drawtext "$utext.s" len=$utext.s.len ulen=$utext.len x=$_x firstc=$firstc')
|
|
|
|
|
if firstc != ' ' {
|
|
|
|
|
exit(1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
2019-08-20 13:34:29 +02:00
|
|
|
|
mut x := f32(_x)
|
|
|
|
|
mut y := f32(_y)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// println('scale=$ctx.scale size=$cfg.size')
|
|
|
|
|
if cfg.align == gx.ALIGN_RIGHT {
|
|
|
|
|
width := utext.len * 7
|
2019-08-07 13:00:19 +02:00
|
|
|
|
x -= width + 10
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
2019-08-07 13:00:19 +02:00
|
|
|
|
x *= ctx.scale// f32(2)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// println('y=$_y height=$ctx.height')
|
|
|
|
|
// _y = _y * int(ctx.scale) //+ 26
|
2019-08-07 13:00:19 +02:00
|
|
|
|
y = y * int(ctx.scale) + ((cfg.size * ctx.scale) / 2) + 5 * ctx.scale
|
2019-08-20 13:34:29 +02:00
|
|
|
|
y = f32(ctx.height) - y
|
2019-07-10 13:27:35 +02:00
|
|
|
|
color := cfg.color
|
|
|
|
|
// Activate corresponding render state
|
|
|
|
|
ctx.shader.use()
|
|
|
|
|
ctx.shader.set_color('textColor', color)
|
2019-08-20 13:34:29 +02:00
|
|
|
|
C.glActiveTexture(C.GL_TEXTURE0)
|
2019-08-05 10:42:58 +02:00
|
|
|
|
gl.bind_vao(ctx.vao)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// Iterate through all characters
|
|
|
|
|
// utext := text.ustring()
|
|
|
|
|
for i := 0; i < utext.len; i++ {
|
|
|
|
|
_rune := utext.at(i)
|
|
|
|
|
// println('$i => $_rune')
|
|
|
|
|
mut ch := Character{}
|
2019-08-26 21:40:07 +02:00
|
|
|
|
mut found := false
|
2019-07-10 13:27:35 +02:00
|
|
|
|
if _rune.len == 1 {
|
|
|
|
|
idx := _rune[0]
|
|
|
|
|
if idx < 0 || idx >= ctx.chars.len {
|
|
|
|
|
println('BADE RUNE $_rune')
|
|
|
|
|
continue
|
|
|
|
|
}
|
2019-08-26 21:40:07 +02:00
|
|
|
|
found = true
|
2019-07-10 13:27:35 +02:00
|
|
|
|
ch = ctx.chars[_rune[0]]
|
|
|
|
|
}
|
|
|
|
|
else if _rune.len > 1 {
|
|
|
|
|
// TODO O(1) use map
|
|
|
|
|
for j := 0; j < ctx.utf_runes.len; j++ {
|
|
|
|
|
rune_j := ctx.utf_runes[j]
|
|
|
|
|
if rune_j==_rune {
|
|
|
|
|
ch = ctx.utf_chars[j]
|
2019-08-26 21:40:07 +02:00
|
|
|
|
found = true
|
2019-07-10 13:27:35 +02:00
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-08-26 21:40:07 +02:00
|
|
|
|
// A new Unicode character. Load it and cache it.
|
|
|
|
|
if !found && _rune.len > 0 && _rune[0] > 32 {
|
2019-08-20 13:34:29 +02:00
|
|
|
|
c := _rune[0]
|
2019-08-26 21:40:07 +02:00
|
|
|
|
//println('cant draw rune "$_rune" code=$c, loading')
|
|
|
|
|
//continue
|
2019-08-20 13:34:29 +02:00
|
|
|
|
ch = ft_load_char(ctx.face, _rune.utf32_code())
|
2019-08-26 21:40:07 +02:00
|
|
|
|
//println('done loading')
|
2019-08-20 13:34:29 +02:00
|
|
|
|
ctx.utf_runes << _rune
|
|
|
|
|
ctx.utf_chars << ch
|
2019-08-26 21:40:07 +02:00
|
|
|
|
//exit(1)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// continue
|
|
|
|
|
}
|
|
|
|
|
xpos := x + f32(ch.bearing.x) * 1
|
|
|
|
|
ypos := y - f32(ch.size.y - ch.bearing.y) * 1
|
|
|
|
|
w := f32(ch.size.x) * 1
|
|
|
|
|
h := f32(ch.size.y) * 1
|
|
|
|
|
// Update VBO for each character
|
2019-08-20 13:34:29 +02:00
|
|
|
|
vertices := [
|
|
|
|
|
xpos, ypos + h, 0.0, 0.0 ,
|
|
|
|
|
xpos, ypos, 0.0, 1.0 ,
|
|
|
|
|
xpos + w, ypos, 1.0, 1.0 ,
|
|
|
|
|
xpos, ypos + h, 0.0, 0.0 ,
|
|
|
|
|
xpos + w, ypos, 1.0, 1.0 ,
|
|
|
|
|
xpos + w, ypos + h, 1.0, 0.0
|
|
|
|
|
]
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// Render glyph texture over quad
|
2019-08-20 13:34:29 +02:00
|
|
|
|
C.glBindTexture(C.GL_TEXTURE_2D, ch.texture_id)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// Update content of VBO memory
|
2019-08-22 23:00:31 +02:00
|
|
|
|
gl.bind_buffer(C.GL_ARRAY_BUFFER, ctx.vbo)
|
2019-08-20 13:34:29 +02:00
|
|
|
|
// glBufferSubData(..)
|
2019-08-22 23:00:31 +02:00
|
|
|
|
C.glBufferData(C.GL_ARRAY_BUFFER, 96, vertices.data, C.GL_DYNAMIC_DRAW)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// Render quad
|
2019-08-22 23:00:31 +02:00
|
|
|
|
gl.draw_arrays(C.GL_TRIANGLES, 0, 6)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
// 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))
|
2019-08-20 13:34:29 +02:00
|
|
|
|
x += ch.advance >> u32(6)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
gl.bind_vao(u32(0))
|
2019-08-20 13:34:29 +02:00
|
|
|
|
C.glBindTexture(C.GL_TEXTURE_2D, 0)
|
2019-07-10 13:27:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-20 13:34:29 +02:00
|
|
|
|
pub fn (ctx mut Context) draw_text_def(x, y int, text string) {
|
2019-07-10 13:27:35 +02:00
|
|
|
|
cfg := gx.TextCfg {
|
|
|
|
|
color: gx.Black,
|
|
|
|
|
size: DEFAULT_FONT_SIZE,
|
|
|
|
|
align: gx.ALIGN_LEFT,
|
|
|
|
|
}
|
|
|
|
|
ctx.draw_text(x, y, text, cfg)
|
|
|
|
|
}
|