mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
table: TypeCategory; freetype: remove C code; [typedef] C structs;
Objective-C interfaces
This commit is contained in:
parent
c8da79d785
commit
eb5fcafa77
@ -13,7 +13,7 @@ CommonCHeaders = '
|
|||||||
|
|
||||||
#define STRUCT_DEFAULT_VALUE {}
|
#define STRUCT_DEFAULT_VALUE {}
|
||||||
#define EMPTY_STRUCT_DECLARATION
|
#define EMPTY_STRUCT_DECLARATION
|
||||||
#define EMPTY_STRUCT_INIT
|
#define EMPTY_STRUCT_INIT 0
|
||||||
#define OPTION_CAST(x) (x)
|
#define OPTION_CAST(x) (x)
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -105,4 +105,4 @@ void init_consts();
|
|||||||
|
|
||||||
'
|
'
|
||||||
|
|
||||||
)
|
)
|
||||||
|
@ -140,7 +140,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
}
|
}
|
||||||
receiver_typ = p.get_type()
|
receiver_typ = p.get_type()
|
||||||
T := p.table.find_type(receiver_typ)
|
T := p.table.find_type(receiver_typ)
|
||||||
if T.is_interface {
|
if T.cat == .interface_ {
|
||||||
p.error('invalid receiver type `$receiver_typ` (`$receiver_typ` is an interface)')
|
p.error('invalid receiver type `$receiver_typ` (`$receiver_typ` is an interface)')
|
||||||
}
|
}
|
||||||
// Don't allow modifying types from a different module
|
// Don't allow modifying types from a different module
|
||||||
|
@ -74,6 +74,8 @@ mut:
|
|||||||
returns bool
|
returns bool
|
||||||
vroot string
|
vroot string
|
||||||
is_c_struct_init bool
|
is_c_struct_init bool
|
||||||
|
is_empty_c_struct_init bool
|
||||||
|
is_c_fn_call bool
|
||||||
can_chash bool
|
can_chash bool
|
||||||
attr string
|
attr string
|
||||||
v_script bool // "V bash", import all os functions into global space
|
v_script bool // "V bash", import all os functions into global space
|
||||||
@ -177,7 +179,7 @@ fn (p mut Parser) parse() {
|
|||||||
}
|
}
|
||||||
p.fgenln('\n')
|
p.fgenln('\n')
|
||||||
p.builtin_mod = p.mod == 'builtin'
|
p.builtin_mod = p.mod == 'builtin'
|
||||||
p.can_chash = p.mod == 'freetype' || p.mod=='ui' // TODO tmp remove
|
p.can_chash = p.mod=='ui' || p.mod == 'darwin'// TODO tmp remove
|
||||||
// Import pass - the first and the smallest pass that only analyzes imports
|
// Import pass - the first and the smallest pass that only analyzes imports
|
||||||
// fully qualify the module name, eg base64 to encoding.base64
|
// fully qualify the module name, eg base64 to encoding.base64
|
||||||
fq_mod := p.table.qualify_module(p.mod, p.file_path)
|
fq_mod := p.table.qualify_module(p.mod, p.file_path)
|
||||||
@ -199,7 +201,7 @@ fn (p mut Parser) parse() {
|
|||||||
// Go through every top level token or throw a compilation error if a non-top level token is met
|
// Go through every top level token or throw a compilation error if a non-top level token is met
|
||||||
for {
|
for {
|
||||||
switch p.tok {
|
switch p.tok {
|
||||||
case Token.key_import:
|
case .key_import:
|
||||||
if p.peek() == .key_const {
|
if p.peek() == .key_const {
|
||||||
p.const_decl()
|
p.const_decl()
|
||||||
}
|
}
|
||||||
@ -483,26 +485,27 @@ fn (p mut Parser) interface_method(field_name, receiver string) &Fn {
|
|||||||
return method
|
return method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn key_to_type_cat(tok Token) TypeCategory {
|
||||||
|
switch tok {
|
||||||
|
case Token.key_interface: return TypeCategory.interface_
|
||||||
|
case Token.key_struct: return TypeCategory.struct_
|
||||||
|
case Token.key_union: return TypeCategory.union_
|
||||||
|
//Token.key_ => return .interface_
|
||||||
|
}
|
||||||
|
panic('')
|
||||||
|
}
|
||||||
|
|
||||||
// also unions and interfaces
|
// also unions and interfaces
|
||||||
fn (p mut Parser) struct_decl() {
|
fn (p mut Parser) struct_decl() {
|
||||||
// Attribute before type?
|
// V can generate Objective C for integration with Cocoa
|
||||||
mut objc_parent := ''
|
// `[interface:ParentInterface]`
|
||||||
mut is_objc := false// V can generate Objective C for integration with Cocoa
|
is_objc := p.attr.starts_with('interface')
|
||||||
// [attr]
|
objc_parent := if is_objc { p.attr.right(10) } else { '' }
|
||||||
if p.tok == .lsbr {
|
// interface, union, struct
|
||||||
p.check(.lsbr)
|
|
||||||
// `[interface:ParentInterface]`
|
|
||||||
is_objc = p.tok == .key_interface
|
|
||||||
p.next()
|
|
||||||
if is_objc {
|
|
||||||
p.check(.colon)
|
|
||||||
objc_parent = p.check_name()
|
|
||||||
}
|
|
||||||
p.check(.rsbr)
|
|
||||||
}
|
|
||||||
is_interface := p.tok == .key_interface
|
is_interface := p.tok == .key_interface
|
||||||
is_union := p.tok == .key_union
|
is_union := p.tok == .key_union
|
||||||
is_struct := p.tok == .key_struct
|
is_struct := p.tok == .key_struct
|
||||||
|
mut cat := key_to_type_cat(p.tok)
|
||||||
p.fgen(p.tok.str() + ' ')
|
p.fgen(p.tok.str() + ' ')
|
||||||
// Get type name
|
// Get type name
|
||||||
p.next()
|
p.next()
|
||||||
@ -517,6 +520,10 @@ fn (p mut Parser) struct_decl() {
|
|||||||
if is_c {
|
if is_c {
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
name = p.check_name()
|
name = p.check_name()
|
||||||
|
cat = .c_struct
|
||||||
|
if p.attr == 'typedef' {
|
||||||
|
cat = .c_typedef
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !is_c && !good_type_name(name) {
|
if !is_c && !good_type_name(name) {
|
||||||
p.error('bad struct name, e.g. use `HttpRequest` instead of `HTTPRequest`')
|
p.error('bad struct name, e.g. use `HttpRequest` instead of `HTTPRequest`')
|
||||||
@ -549,13 +556,14 @@ fn (p mut Parser) struct_decl() {
|
|||||||
typ.mod = p.mod
|
typ.mod = p.mod
|
||||||
typ.is_c = is_c
|
typ.is_c = is_c
|
||||||
typ.is_placeholder = false
|
typ.is_placeholder = false
|
||||||
|
typ.cat = cat
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
typ = &Type {
|
typ = &Type {
|
||||||
name: name
|
name: name
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
is_c: is_c
|
is_c: is_c
|
||||||
is_interface: is_interface
|
cat: cat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Struct `C.Foo` declaration, no body
|
// Struct `C.Foo` declaration, no body
|
||||||
@ -706,7 +714,7 @@ fn (p mut Parser) enum_decl(_enum_name string) {
|
|||||||
name: enum_name
|
name: enum_name
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
parent: 'int'
|
parent: 'int'
|
||||||
is_enum: true
|
cat: TypeCategory.enum_
|
||||||
enum_vals: fields
|
enum_vals: fields
|
||||||
})
|
})
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
@ -905,7 +913,8 @@ fn (p mut Parser) get_type() string {
|
|||||||
}
|
}
|
||||||
typ += p.lit
|
typ += p.lit
|
||||||
if !p.is_struct_init {
|
if !p.is_struct_init {
|
||||||
// Otherwise we get `foo := FooFoo{` because `Foo` was already generated in name_expr()
|
// Otherwise we get `foo := FooFoo{` because `Foo` was already
|
||||||
|
// generated in name_expr()
|
||||||
p.fgen(p.lit)
|
p.fgen(p.lit)
|
||||||
}
|
}
|
||||||
// C.Struct import
|
// C.Struct import
|
||||||
@ -1120,7 +1129,6 @@ fn (p mut Parser) statement(add_semi bool) string {
|
|||||||
}
|
}
|
||||||
// `a := 777`
|
// `a := 777`
|
||||||
else if p.peek() == .decl_assign {
|
else if p.peek() == .decl_assign {
|
||||||
p.log('var decl')
|
|
||||||
p.var_decl()
|
p.var_decl()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1128,7 +1136,7 @@ fn (p mut Parser) statement(add_semi bool) string {
|
|||||||
if p.lit == 'panic' || p.lit == 'exit' {
|
if p.lit == 'panic' || p.lit == 'exit' {
|
||||||
p.returns = true
|
p.returns = true
|
||||||
}
|
}
|
||||||
// `a + 3`, `a(7)` or maybe just `a`
|
// `a + 3`, `a(7)`, or just `a`
|
||||||
q = p.bool_expression()
|
q = p.bool_expression()
|
||||||
}
|
}
|
||||||
case Token.key_goto:
|
case Token.key_goto:
|
||||||
@ -1220,7 +1228,7 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) {
|
|||||||
is_str := v.typ == 'string'
|
is_str := v.typ == 'string'
|
||||||
switch tok {
|
switch tok {
|
||||||
case Token.assign:
|
case Token.assign:
|
||||||
if !is_map {
|
if !is_map && !p.is_empty_c_struct_init {
|
||||||
p.gen(' = ')
|
p.gen(' = ')
|
||||||
}
|
}
|
||||||
case Token.plus_assign:
|
case Token.plus_assign:
|
||||||
@ -1326,13 +1334,18 @@ fn (p mut Parser) var_decl() {
|
|||||||
})
|
})
|
||||||
if !or_else {
|
if !or_else {
|
||||||
gen_name := p.table.var_cgen_name(name)
|
gen_name := p.table.var_cgen_name(name)
|
||||||
mut nt_gen := p.table.cgen_name_type_pair(gen_name, typ) + '='
|
mut nt_gen := p.table.cgen_name_type_pair(gen_name, typ)
|
||||||
|
// `foo := C.Foo{}` => `Foo foo;`
|
||||||
|
if !p.is_empty_c_struct_init {
|
||||||
|
nt_gen += '='
|
||||||
|
}
|
||||||
if is_static {
|
if is_static {
|
||||||
nt_gen = 'static $nt_gen'
|
nt_gen = 'static $nt_gen'
|
||||||
}
|
}
|
||||||
p.cgen.set_placeholder(pos, nt_gen)
|
p.cgen.set_placeholder(pos, nt_gen)
|
||||||
}
|
}
|
||||||
p.var_decl_name = ''
|
p.var_decl_name = ''
|
||||||
|
p.is_empty_c_struct_init = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -1383,7 +1396,7 @@ fn (p mut Parser) bterm() string {
|
|||||||
is_str := typ=='string' && !p.is_sql
|
is_str := typ=='string' && !p.is_sql
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
// if tok in [ .eq, .gt, .lt, .le, .ge, .ne] {
|
// if tok in [ .eq, .gt, .lt, .le, .ge, .ne] {
|
||||||
if tok == .eq || (tok == .assign && p.is_sql) || tok == .gt || tok == .lt || tok == .le || tok == .ge || tok == .ne {
|
if tok == .eq || tok == .gt || tok == .lt || tok == .le || tok == .ge || tok == .ne {
|
||||||
p.fgen(' ${p.tok.str()} ')
|
p.fgen(' ${p.tok.str()} ')
|
||||||
if is_str {
|
if is_str {
|
||||||
p.gen(',')
|
p.gen(',')
|
||||||
@ -1466,7 +1479,7 @@ fn (p mut Parser) name_expr() string {
|
|||||||
if p.tok == .dot {
|
if p.tok == .dot {
|
||||||
//println('got enum dot val $p.left_type pass=$p.pass $p.scanner.line_nr left=$p.left_type')
|
//println('got enum dot val $p.left_type pass=$p.pass $p.scanner.line_nr left=$p.left_type')
|
||||||
T := p.find_type(p.expected_type)
|
T := p.find_type(p.expected_type)
|
||||||
if T.is_enum {
|
if T.cat == .enum_ {
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
val := p.check_name()
|
val := p.check_name()
|
||||||
// Make sure this enum value exists
|
// Make sure this enum value exists
|
||||||
@ -1552,7 +1565,7 @@ fn (p mut Parser) name_expr() string {
|
|||||||
// Color.green
|
// Color.green
|
||||||
else if p.peek() == .dot {
|
else if p.peek() == .dot {
|
||||||
enum_type := p.table.find_type(name)
|
enum_type := p.table.find_type(name)
|
||||||
if !enum_type.is_enum {
|
if enum_type.cat != .enum_ {
|
||||||
p.error('`$name` is not an enum')
|
p.error('`$name` is not an enum')
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
@ -1563,19 +1576,8 @@ fn (p mut Parser) name_expr() string {
|
|||||||
p.next()
|
p.next()
|
||||||
return enum_type.name
|
return enum_type.name
|
||||||
}
|
}
|
||||||
|
// struct initialization
|
||||||
else if p.peek() == .lcbr {
|
else if p.peek() == .lcbr {
|
||||||
// go back to name start (mod.name)
|
|
||||||
/*
|
|
||||||
p.scanner.pos = hack_pos
|
|
||||||
p.tok = hack_tok
|
|
||||||
p.lit = hack_lit
|
|
||||||
*/
|
|
||||||
// TODO hack. If it's a C type, we may need to add struct before declaration:
|
|
||||||
// a := &C.A{} ==> struct A* a = malloc(sizeof(struct A));
|
|
||||||
if is_c_struct_init {
|
|
||||||
p.is_c_struct_init = true
|
|
||||||
p.cgen.insert_before('struct /*c struct init*/')
|
|
||||||
}
|
|
||||||
if ptr {
|
if ptr {
|
||||||
name += '*' // `&User{}` => type `User*`
|
name += '*' // `&User{}` => type `User*`
|
||||||
}
|
}
|
||||||
@ -1597,12 +1599,15 @@ fn (p mut Parser) name_expr() string {
|
|||||||
name: name// .replace('c_', '')
|
name: name// .replace('c_', '')
|
||||||
is_c: true
|
is_c: true
|
||||||
}
|
}
|
||||||
|
p.is_c_fn_call = true
|
||||||
p.fn_call(f, 0, '', '')
|
p.fn_call(f, 0, '', '')
|
||||||
|
p.is_c_fn_call = false
|
||||||
// Try looking it up. Maybe its defined with "C.fn_name() fn_type",
|
// Try looking it up. Maybe its defined with "C.fn_name() fn_type",
|
||||||
// then we know what type it returns
|
// then we know what type it returns
|
||||||
cfn := p.table.find_fn(name)
|
cfn := p.table.find_fn(name)
|
||||||
// Not Found? Return 'void*'
|
// Not Found? Return 'void*'
|
||||||
if cfn.name == '' {
|
if cfn.name == '' {
|
||||||
|
//return 'cvoid' //'void*'
|
||||||
return 'void*'
|
return 'void*'
|
||||||
}
|
}
|
||||||
return cfn.typ
|
return cfn.typ
|
||||||
@ -1791,7 +1796,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
|||||||
p.gen_array_str(mut typ)
|
p.gen_array_str(mut typ)
|
||||||
has_method = true
|
has_method = true
|
||||||
}
|
}
|
||||||
if !typ.is_c && !has_field && !has_method && !p.first_pass() {
|
if !typ.is_c && !p.is_c_fn_call && !has_field && !has_method && !p.first_pass() {
|
||||||
if typ.name.starts_with('Option_') {
|
if typ.name.starts_with('Option_') {
|
||||||
opt_type := typ.name.right(7)
|
opt_type := typ.name.right(7)
|
||||||
p.error('unhandled option type: $opt_type?')
|
p.error('unhandled option type: $opt_type?')
|
||||||
@ -1809,7 +1814,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
|||||||
p.error('type `$typ.name` has no field or method `$field_name`')
|
p.error('type `$typ.name` has no field or method `$field_name`')
|
||||||
}
|
}
|
||||||
mut dot := '.'
|
mut dot := '.'
|
||||||
if str_typ.contains('*') {
|
if str_typ.ends_with('*') || str_typ == 'FT_Face' { // TODO fix C ptr typedefs
|
||||||
dot = '->'
|
dot = '->'
|
||||||
}
|
}
|
||||||
// field
|
// field
|
||||||
@ -2113,7 +2118,7 @@ fn (p mut Parser) expression() string {
|
|||||||
p.check_space(.left_shift)
|
p.check_space(.left_shift)
|
||||||
// Get the value we are pushing
|
// Get the value we are pushing
|
||||||
p.gen(', (')
|
p.gen(', (')
|
||||||
// Imkey_mut? Can we push?
|
// Immutable? Can we push?
|
||||||
if !p.expr_var.is_mut && !p.pref.translated {
|
if !p.expr_var.is_mut && !p.pref.translated {
|
||||||
p.error('`$p.expr_var.name` is immutable (can\'t <<)')
|
p.error('`$p.expr_var.name` is immutable (can\'t <<)')
|
||||||
}
|
}
|
||||||
@ -2130,7 +2135,7 @@ fn (p mut Parser) expression() string {
|
|||||||
p.check_types(expr_type, tmp_typ)
|
p.check_types(expr_type, tmp_typ)
|
||||||
// Pass tmp var info to the _PUSH macro
|
// Pass tmp var info to the _PUSH macro
|
||||||
// Prepend tmp initialisation and push call
|
// Prepend tmp initialisation and push call
|
||||||
// Don't dereference if it's already a key_mut array argument (`fn foo(mut []int)`)
|
// Don't dereference if it's already a mutable array argument (`fn foo(mut []int)`)
|
||||||
push_call := if typ.contains('*'){'_PUSH('} else { '_PUSH(&'}
|
push_call := if typ.contains('*'){'_PUSH('} else { '_PUSH(&'}
|
||||||
p.cgen.set_placeholder(ph, push_call)
|
p.cgen.set_placeholder(ph, push_call)
|
||||||
p.gen('), $tmp, $tmp_typ)')
|
p.gen('), $tmp, $tmp_typ)')
|
||||||
@ -2791,18 +2796,32 @@ fn (p mut Parser) array_init() string {
|
|||||||
|
|
||||||
fn (p mut Parser) struct_init(typ string, is_c_struct_init bool) string {
|
fn (p mut Parser) struct_init(typ string, is_c_struct_init bool) string {
|
||||||
p.is_struct_init = true
|
p.is_struct_init = true
|
||||||
|
t := p.table.find_type(typ)
|
||||||
|
// TODO hack. If it's a C type, we may need to add struct before declaration:
|
||||||
|
// a := &C.A{} ==> struct A* a = malloc(sizeof(struct A));
|
||||||
|
if is_c_struct_init { // && t.cat != .c_typedef {
|
||||||
|
p.is_c_struct_init = true
|
||||||
|
if t.cat != .c_typedef {
|
||||||
|
p.cgen.insert_before('struct /*c struct init*/')
|
||||||
|
}
|
||||||
|
}
|
||||||
p.next()
|
p.next()
|
||||||
p.scanner.fmt_out.cut(typ.len)
|
p.scanner.fmt_out.cut(typ.len)
|
||||||
ptr := typ.contains('*')
|
ptr := typ.contains('*')
|
||||||
// TODO tm struct struct bug
|
// TODO tm struct struct bug
|
||||||
if typ == 'tm' {
|
if typ == 'tm' {
|
||||||
p.cgen.lines[p.cgen.lines.len-1] = ''
|
p.cgen.lines[p.cgen.lines.len-1] = ''
|
||||||
p.cgen.lines[p.cgen.lines.len-2] = ''
|
|
||||||
}
|
}
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
// tmp := p.get_tmp()
|
// `user := User{foo:bar}` => `User user = (User){ .foo = bar}`
|
||||||
if !ptr {
|
if !ptr {
|
||||||
if p.is_c_struct_init {
|
if p.is_c_struct_init {
|
||||||
|
// `face := C.FT_Face{}` => `FT_Face face;`
|
||||||
|
if p.tok == .rcbr {
|
||||||
|
p.is_empty_c_struct_init = true
|
||||||
|
p.check(.rcbr)
|
||||||
|
return typ
|
||||||
|
}
|
||||||
p.gen('(struct $typ) {')
|
p.gen('(struct $typ) {')
|
||||||
p.is_c_struct_init = false
|
p.is_c_struct_init = false
|
||||||
}
|
}
|
||||||
@ -2829,7 +2848,6 @@ fn (p mut Parser) struct_init(typ string, is_c_struct_init bool) string {
|
|||||||
mut inited_fields := []string
|
mut inited_fields := []string
|
||||||
peek := p.peek()
|
peek := p.peek()
|
||||||
if peek == .colon || p.tok == .rcbr {
|
if peek == .colon || p.tok == .rcbr {
|
||||||
t := p.table.find_type(typ)
|
|
||||||
for p.tok != .rcbr {
|
for p.tok != .rcbr {
|
||||||
field := p.check_name()
|
field := p.check_name()
|
||||||
if !t.has_field(field) {
|
if !t.has_field(field) {
|
||||||
@ -2942,6 +2960,9 @@ fn (p mut Parser) cast(typ string) string {
|
|||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
p.expected_type = typ
|
p.expected_type = typ
|
||||||
expr_typ := p.bool_expression()
|
expr_typ := p.bool_expression()
|
||||||
|
// `face := FT_Face(cobj)` => `FT_Face face = *((FT_Face*)cobj);`
|
||||||
|
casting_voidptr_to_value := expr_typ == 'void*' && typ != 'int' &&
|
||||||
|
typ != 'byteptr' && !typ.ends_with('*')
|
||||||
p.expected_type = ''
|
p.expected_type = ''
|
||||||
// `string(buffer)` => `tos2(buffer)`
|
// `string(buffer)` => `tos2(buffer)`
|
||||||
// `string(buffer, len)` => `tos(buffer, len)`
|
// `string(buffer, len)` => `tos(buffer, len)`
|
||||||
@ -2976,6 +2997,9 @@ fn (p mut Parser) cast(typ string) string {
|
|||||||
else if typ == 'byte' && expr_typ == 'string' {
|
else if typ == 'byte' && expr_typ == 'string' {
|
||||||
p.error('cannot cast `$expr_typ` to `$typ`, use backquotes `` to create a `$typ` or access the value of an index of `$expr_typ` using []')
|
p.error('cannot cast `$expr_typ` to `$typ`, use backquotes `` to create a `$typ` or access the value of an index of `$expr_typ` using []')
|
||||||
}
|
}
|
||||||
|
else if casting_voidptr_to_value {
|
||||||
|
p.cgen.set_placeholder(pos, '*($typ*)(')
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
p.cgen.set_placeholder(pos, '($typ)(')
|
p.cgen.set_placeholder(pos, '($typ)(')
|
||||||
}
|
}
|
||||||
@ -3524,7 +3548,13 @@ fn (p &Parser) building_v() bool {
|
|||||||
|
|
||||||
fn (p mut Parser) attribute() {
|
fn (p mut Parser) attribute() {
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
p.attr = p.check_name()
|
if p.tok == .key_interface {
|
||||||
|
p.check(.key_interface)
|
||||||
|
p.check(.colon)
|
||||||
|
p.attr = 'interface:' + p.check_name()
|
||||||
|
} else {
|
||||||
|
p.attr = p.check_name()
|
||||||
|
}
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
if p.tok == .func {
|
if p.tok == .func {
|
||||||
p.fn_decl()
|
p.fn_decl()
|
||||||
|
@ -43,17 +43,26 @@ enum AccessMod {
|
|||||||
public_mut_mut // public and mutable both inside and outside (not recommended to use, that's why it's so verbose)
|
public_mut_mut // public and mutable both inside and outside (not recommended to use, that's why it's so verbose)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TypeCategory {
|
||||||
|
struct_
|
||||||
|
func
|
||||||
|
interface_ // 2
|
||||||
|
enum_
|
||||||
|
union_
|
||||||
|
c_struct // 5
|
||||||
|
c_typedef
|
||||||
|
}
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
mut:
|
mut:
|
||||||
mod string
|
mod string
|
||||||
name string
|
name string
|
||||||
|
cat TypeCategory
|
||||||
fields []Var
|
fields []Var
|
||||||
methods []Fn
|
methods []Fn
|
||||||
parent string
|
parent string
|
||||||
func Fn // For cat == FN (type myfn fn())
|
func Fn // For cat == FN (type myfn fn())
|
||||||
is_c bool // C.FI.le
|
is_c bool // `C.FILE`
|
||||||
is_interface bool
|
|
||||||
is_enum bool
|
|
||||||
enum_vals []string
|
enum_vals []string
|
||||||
gen_types []string
|
gen_types []string
|
||||||
// This field is used for types that are not defined yet but are known to exist.
|
// This field is used for types that are not defined yet but are known to exist.
|
||||||
@ -488,7 +497,7 @@ fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// Todo void* allows everything right now
|
// Todo void* allows everything right now
|
||||||
if got=='void*' || expected=='void*' {
|
if got=='void*' || expected=='void*' {// || got == 'cvoid' || expected == 'cvoid' {
|
||||||
// if !p.builtin_mod {
|
// if !p.builtin_mod {
|
||||||
if p.pref.is_play {
|
if p.pref.is_play {
|
||||||
return false
|
return false
|
||||||
@ -623,7 +632,7 @@ fn type_default(typ string) string {
|
|||||||
// TODO PERF O(n)
|
// TODO PERF O(n)
|
||||||
fn (t &Table) is_interface(name string) bool {
|
fn (t &Table) is_interface(name string) bool {
|
||||||
for typ in t.types {
|
for typ in t.types {
|
||||||
if typ.is_interface && typ.name == name {
|
if typ.cat == .interface_ && typ.name == name {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -757,7 +766,7 @@ fn (t mut Table) register_generic_fn_type(fn_name, typ string) {
|
|||||||
|
|
||||||
fn (p mut Parser) typ_to_fmt(typ string, level int) string {
|
fn (p mut Parser) typ_to_fmt(typ string, level int) string {
|
||||||
t := p.table.find_type(typ)
|
t := p.table.find_type(typ)
|
||||||
if t.is_enum {
|
if t.cat == .enum_ {
|
||||||
return '%d'
|
return '%d'
|
||||||
}
|
}
|
||||||
switch typ {
|
switch typ {
|
||||||
|
@ -195,7 +195,7 @@ pub fn (n int) hex() string {
|
|||||||
} else {
|
} else {
|
||||||
11
|
11
|
||||||
}
|
}
|
||||||
hex := malloc(len) // 0x + \n
|
hex := malloc(len) // 0x + \n
|
||||||
count := int(C.sprintf(hex, '0x%x', n))
|
count := int(C.sprintf(hex, '0x%x', n))
|
||||||
return tos(hex, count)
|
return tos(hex, count)
|
||||||
}
|
}
|
||||||
@ -245,14 +245,14 @@ pub fn (c byte) str() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c byte) is_capital() bool {
|
pub fn (c byte) is_capital() bool {
|
||||||
return c >= `A` && c <= `Z`
|
return c >= `A` && c <= `Z`
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b []byte) clone() []byte {
|
pub fn (b []byte) clone() []byte {
|
||||||
mut res := [byte(0); b.len]
|
mut res := [byte(0); b.len]
|
||||||
for i := 0; i < b.len; i++ {
|
for i := 0; i < b.len; i++ {
|
||||||
res[i] = b[i]
|
res[i] = b[i]
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
vlib/darwin/darwin.v
Normal file
22
vlib/darwin/darwin.v
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
module darwin
|
||||||
|
|
||||||
|
#include <Cocoa/Cocoa.h>
|
||||||
|
#flag -framework Cocoa
|
||||||
|
|
||||||
|
struct C.NSString { }
|
||||||
|
|
||||||
|
// macOS and iOS helpers
|
||||||
|
fn nsstring(s string) *NSString {
|
||||||
|
// #return @"" ;
|
||||||
|
// println('ns $s len=$s.len')
|
||||||
|
# return [ [ NSString alloc ] initWithBytesNoCopy:s.str length:s.len
|
||||||
|
# encoding:NSUTF8StringEncoding freeWhenDone: false];
|
||||||
|
return 0
|
||||||
|
|
||||||
|
//ns := C.alloc_NSString()
|
||||||
|
//return ns.initWithBytesNoCopy(s.str, length: s.len,
|
||||||
|
//encoding: NSUTF8StringEncoding, freeWhenDone: false)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,25 +2,25 @@
|
|||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
module freetype
|
module freetype
|
||||||
|
|
||||||
import (
|
import (
|
||||||
os
|
os
|
||||||
gx
|
gx
|
||||||
gg
|
gg
|
||||||
stbi
|
stbi
|
||||||
glm
|
glm
|
||||||
gl
|
gl
|
||||||
)
|
)
|
||||||
|
|
||||||
#flag darwin -I/usr/local/include/freetype2
|
#flag darwin -I/usr/local/include/freetype2
|
||||||
#flag darwin -I/opt/local/include/freetype2
|
#flag darwin -I/opt/local/include/freetype2
|
||||||
#flag -lfreetype
|
#flag -lfreetype
|
||||||
|
|
||||||
//#flag -I @VROOT/thirdparty/freetype
|
//#flag -I @VROOT/thirdparty/freetype
|
||||||
|
|
||||||
//#flag @VROOT/thirdparty/freetype/libfreetype.a
|
//#flag @VROOT/thirdparty/freetype/libfreetype.a
|
||||||
#flag darwin -lpng -lbz2 -lz
|
#flag darwin -lpng -lbz2 -lz
|
||||||
|
|
||||||
|
|
||||||
#flag linux -I/usr/include/freetype2
|
#flag linux -I/usr/include/freetype2
|
||||||
@ -30,6 +30,8 @@ import (
|
|||||||
#include "ft2build.h"
|
#include "ft2build.h"
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DEFAULT_FONT_SIZE = 12
|
DEFAULT_FONT_SIZE = 12
|
||||||
)
|
)
|
||||||
@ -45,6 +47,11 @@ struct Face {
|
|||||||
cobj voidptr
|
cobj voidptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[typedef]
|
||||||
|
struct C.FT_Library {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
shader gl.Shader
|
shader gl.Shader
|
||||||
// use_ortho bool
|
// use_ortho bool
|
||||||
@ -63,67 +70,67 @@ struct Context {
|
|||||||
scale int // retina = 2 , normal = 1
|
scale int // retina = 2 , normal = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
struct C.Bitmap {
|
||||||
struct Cfg {
|
width int
|
||||||
width int
|
rows int
|
||||||
height int
|
buffer int
|
||||||
use_ortho bool
|
|
||||||
retina bool
|
|
||||||
scale int
|
|
||||||
font_size int
|
|
||||||
create_window bool
|
|
||||||
window_user_ptr voidptr
|
|
||||||
window_title string
|
|
||||||
always_on_top bool
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
struct C.Advance {
|
||||||
|
x int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct C.Glyph {
|
||||||
|
bitmap Bitmap
|
||||||
|
bitmap_left int
|
||||||
|
bitmap_top int
|
||||||
|
advance Advance
|
||||||
|
}
|
||||||
|
|
||||||
|
[typedef]
|
||||||
|
struct C.FT_Face {
|
||||||
|
glyph *Glyph
|
||||||
|
}
|
||||||
|
|
||||||
// jfn ft_load_char(face FT_Face, code FT_ULong) Character {
|
|
||||||
// fn ft_load_char(_face voidptr, _code voidptr) Character {
|
|
||||||
fn ft_load_char(_face Face, code i64) Character {
|
fn ft_load_char(_face Face, code i64) Character {
|
||||||
// #FT_Face face = *(FT_Face*)(_face); FT_ULong code = *(FT_ULong*)(code);
|
//println('ftload_char( code=$code)')
|
||||||
# FT_Face face = *((FT_Face*)_face.cobj);
|
//C.printf('face=%p\n', _face)
|
||||||
# int condition = FT_Load_Char(face, code, FT_LOAD_RENDER);
|
face := FT_Face(_face.cobj)
|
||||||
if (C.condition != 0)
|
ret := int(C.FT_Load_Char(face, code, C.FT_LOAD_RENDER))
|
||||||
{
|
if ret != 0 {
|
||||||
println('freetype: Failed to load Glyph')
|
println('freetype: failed to load glyph (utf32 code=$code, ' +
|
||||||
exit(1)
|
'error code=$ret)')
|
||||||
|
return Character{}
|
||||||
}
|
}
|
||||||
// Generate texture
|
// Generate texture
|
||||||
# GLuint texture;
|
mut texture := 0
|
||||||
# glGenTextures(1, &texture);
|
C.glGenTextures(1, &texture)
|
||||||
# glBindTexture(GL_TEXTURE_2D, texture);
|
C.glBindTexture(C.GL_TEXTURE_2D, texture)
|
||||||
# glTexImage2D(
|
fgwidth := face.glyph.bitmap.width
|
||||||
# GL_TEXTURE_2D,
|
fgrows := face.glyph.bitmap.rows
|
||||||
# 0,
|
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RED, fgwidth, fgrows,
|
||||||
# GL_RED,
|
0, C.GL_RED, C.GL_UNSIGNED_BYTE, face.glyph.bitmap.buffer)
|
||||||
# face->glyph->bitmap.width,
|
|
||||||
# face->glyph->bitmap.rows,
|
|
||||||
# 0,
|
|
||||||
# GL_RED,
|
|
||||||
# GL_UNSIGNED_BYTE,
|
|
||||||
# face->glyph->bitmap.buffer
|
|
||||||
# );
|
|
||||||
// Set texture options
|
// Set texture options
|
||||||
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
C.glTexParameteri(GL_TEXTURE_2D, C.GL_TEXTURE_WRAP_S, C.GL_CLAMP_TO_EDGE)
|
||||||
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
C.glTexParameteri(GL_TEXTURE_2D, C.GL_TEXTURE_WRAP_T, C.GL_CLAMP_TO_EDGE)
|
||||||
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
C.glTexParameteri(GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
|
||||||
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_LINEAR)
|
||||||
// Now store character for later use
|
fgleft := face.glyph.bitmap_left
|
||||||
ch := Character{}
|
fgtop := face.glyph.bitmap_top
|
||||||
# ch.texture_id=texture ;
|
// Create the character
|
||||||
# ch.size = gg__vec2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
return Character {
|
||||||
# ch.bearing = gg__vec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
|
texture_id: u32(texture)
|
||||||
# ch.advance = face->glyph->advance.x;
|
size: gg.vec2(int(u32(fgwidth)), int(u32(fgrows)))
|
||||||
return ch
|
bearing: gg.vec2(int(u32(fgleft)), int(u32(fgtop)))
|
||||||
|
advance: (u32(face.glyph.advance.x))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_context(cfg gg.Cfg) *Context {
|
pub fn new_context(cfg gg.Cfg) *Context {
|
||||||
scale := cfg.scale
|
scale := cfg.scale
|
||||||
// Can only have text in ortho mode
|
// Can only have text in ortho mode
|
||||||
if !cfg.use_ortho {
|
if !cfg.use_ortho {
|
||||||
return &Context{}
|
return &Context{}
|
||||||
}
|
}
|
||||||
mut width := cfg.width * scale
|
mut width := cfg.width * scale
|
||||||
mut height := cfg.height * scale
|
mut height := cfg.height * scale
|
||||||
@ -135,27 +142,25 @@ pub fn new_context(cfg gg.Cfg) *Context {
|
|||||||
// height = height * 2// scale// 2
|
// height = height * 2// scale// 2
|
||||||
// font_size *= scale// 2
|
// font_size *= scale// 2
|
||||||
// }
|
// }
|
||||||
/*
|
/*
|
||||||
gl.viewport(0, 0, width, height)
|
gl.viewport(0, 0, width, height)
|
||||||
*/
|
*/
|
||||||
// gl.enable(GL_CULL_FACE) // TODO NEED CULL?
|
// gl.enable(GL_CULL_FACE) // TODO NEED CULL?
|
||||||
gl.enable(GL_BLEND)
|
gl.enable(GL_BLEND)
|
||||||
//return &GG{}
|
C.glBlendFunc(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA)
|
||||||
// return &GG{}
|
|
||||||
# glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
shader := gl.new_shader('text')
|
shader := gl.new_shader('text')
|
||||||
shader.use()
|
shader.use()
|
||||||
projection := glm.ortho(0, width, 0, height)// 0 at BOT
|
projection := glm.ortho(0, width, 0, height)// 0 at BOT
|
||||||
// projection_new := ortho(0, width, 0, height)// 0 at BOT
|
|
||||||
// projection := gl.ortho(0, width,height,0) // 0 at TOP
|
|
||||||
shader.set_mat4('projection', projection)
|
shader.set_mat4('projection', projection)
|
||||||
// FREETYPE
|
// FREETYPE
|
||||||
# FT_Library ft;
|
ft := FT_Library{}
|
||||||
// All functions return a value different than 0 whenever an error occurred
|
// All functions return a value different than 0 whenever
|
||||||
# if (FT_Init_FreeType(&ft))
|
// an error occurred
|
||||||
println('ERROR::FREETYPE: Could not init FreeType Library')
|
mut ret := C.FT_Init_FreeType(&ft)
|
||||||
|
if ret != 0 {
|
||||||
|
panic('freetype: Could not init FreeType Library')
|
||||||
|
}
|
||||||
// Load font as face
|
// Load font as face
|
||||||
// face := FT_Face{}
|
|
||||||
mut font_path := cfg.font_path
|
mut font_path := cfg.font_path
|
||||||
if font_path == '' {
|
if font_path == '' {
|
||||||
font_path = 'RobotoMono-Regular.ttf'
|
font_path = 'RobotoMono-Regular.ttf'
|
||||||
@ -170,37 +175,27 @@ pub fn new_context(cfg gg.Cfg) *Context {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
println('Trying to load font from $font_path')
|
println('Trying to load font from $font_path')
|
||||||
# FT_Face face;
|
face := C.FT_Face{}
|
||||||
# int condition = FT_New_Face(ft, font_path.str, 0, &face);
|
ret = int(C.FT_New_Face(ft, font_path.str, 0, &face))
|
||||||
if (C.condition != 0)
|
if ret != 0 {
|
||||||
// # if (FT_New_Face(ft, "/Library/Fonts/Courier New.ttf", 0, &face))
|
println('freetype: failed to load the font (error=$ret)')
|
||||||
// # if (FT_New_Face(ft, "/System/Library/Fonts/Apple Color Emoji.ttc", 0, &face))
|
|
||||||
{
|
|
||||||
println('freetyp: Failed to load font')
|
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
// Set size to load glyphs as
|
// Set size to load glyphs as
|
||||||
# FT_Set_Pixel_Sizes(face, 0, font_size) ;
|
C.FT_Set_Pixel_Sizes(face, 0, font_size)
|
||||||
// Disable byte-alignment restriction
|
// Disable byte-alignment restriction
|
||||||
# glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 1)
|
||||||
// Gen texture
|
// Gen texture
|
||||||
// Load first 128 characters of ASCII set
|
// Load first 128 characters of ASCII set
|
||||||
mut chars := []Character{}
|
mut chars := []Character{}
|
||||||
f := Face {
|
f := Face {
|
||||||
cobj: 0
|
cobj: &face
|
||||||
}
|
}
|
||||||
# f.cobj = &face;
|
|
||||||
// # for (GLubyte c = 0; c < 128; c++)
|
|
||||||
for c := 0; c < 128; c++ {
|
for c := 0; c < 128; c++ {
|
||||||
// ch := Character{}
|
|
||||||
// ch:=ft_load_char(face, c)
|
|
||||||
// # ch =gg__ft_load_char(&face, &c);
|
|
||||||
// ////////////////////////////////
|
|
||||||
mut ch := ft_load_char(f, i64(c))
|
mut ch := ft_load_char(f, i64(c))
|
||||||
// s := utf32_to_str(uint(0x043f))
|
// s := utf32_to_str(uint(0x043f))
|
||||||
// s := 'п'
|
// s := 'п'
|
||||||
// ch = ft_load_char(f, s.utf32_code())
|
// ch = ft_load_char(f, s.utf32_code())
|
||||||
// # ch = gg__ft_load_char(f, 0x043f); // RUS P
|
|
||||||
// # unsigned long c = FT_Get_Char_Index(face, 0x043f );
|
// # unsigned long c = FT_Get_Char_Index(face, 0x043f );
|
||||||
// # printf("!!!!!!!!! %lu\n", c);
|
// # printf("!!!!!!!!! %lu\n", c);
|
||||||
// # c = FT_Get_Char_Index(face, 0xd0bf );
|
// # c = FT_Get_Char_Index(face, 0xd0bf );
|
||||||
@ -209,9 +204,6 @@ pub fn new_context(cfg gg.Cfg) *Context {
|
|||||||
chars << ch
|
chars << ch
|
||||||
}
|
}
|
||||||
ch := Character{}
|
ch := Character{}
|
||||||
// # ch = gg__ft_load_char(f, 0x0000043f);
|
|
||||||
// # ch = gg__ft_load_char(f, 128169);
|
|
||||||
// chars.push(ch)
|
|
||||||
// Configure VAO
|
// Configure VAO
|
||||||
vao := gl.gen_vertex_array()
|
vao := gl.gen_vertex_array()
|
||||||
println('new gg text context vao=$vao')
|
println('new gg text context vao=$vao')
|
||||||
@ -225,13 +217,13 @@ pub fn new_context(cfg gg.Cfg) *Context {
|
|||||||
// gl.bind_buffer(GL_ARRAY_BUFFER, uint(0))
|
// gl.bind_buffer(GL_ARRAY_BUFFER, uint(0))
|
||||||
// # glBindVertexArray(0);
|
// # glBindVertexArray(0);
|
||||||
mut ctx := &Context {
|
mut ctx := &Context {
|
||||||
shader: shader,
|
shader: shader
|
||||||
width: width,
|
width: width
|
||||||
height: height,
|
height: height
|
||||||
scale: scale
|
scale: scale
|
||||||
vao: vao,
|
vao: vao
|
||||||
vbo: vbo,
|
vbo: vbo
|
||||||
chars: chars,
|
chars: chars
|
||||||
face: f
|
face: f
|
||||||
}
|
}
|
||||||
ctx.init_utf8_runes()
|
ctx.init_utf8_runes()
|
||||||
@ -239,10 +231,11 @@ pub fn new_context(cfg gg.Cfg) *Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A dirty hack to implement rendering of cyrillic letters.
|
// A dirty hack to implement rendering of cyrillic letters.
|
||||||
// All UTF-8 must be supported.
|
// All UTF-8 must be supported.
|
||||||
fn (ctx mut Context) init_utf8_runes() {
|
fn (ctx mut Context) init_utf8_runes() {
|
||||||
s := '≈≠⩽⩾йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ'
|
s := '≈≠⩽⩾йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ'
|
||||||
println(s)
|
print('init utf8 runes: ')
|
||||||
|
//println(s)
|
||||||
us := s.ustring()
|
us := s.ustring()
|
||||||
for i := 0; i < us.len; i++ {
|
for i := 0; i < us.len; i++ {
|
||||||
_rune := us.at(i)
|
_rune := us.at(i)
|
||||||
@ -253,25 +246,18 @@ fn (ctx mut Context) init_utf8_runes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn (ctx &GG) render_text(text string, x, y, scale f32, color gx.Color) {
|
pub fn (ctx mut Context) draw_text(_x, _y int, text string, cfg gx.TextCfg) {
|
||||||
pub fn (ctx &Context) draw_text(_x, _y int, text string, cfg gx.TextCfg) {
|
|
||||||
//utext := text.ustring_tmp()
|
//utext := text.ustring_tmp()
|
||||||
utext := text.ustring()
|
utext := text.ustring()
|
||||||
ctx._draw_text(_x, _y, utext, cfg)
|
ctx._draw_text(_x, _y, utext, cfg)
|
||||||
// utext.free()
|
|
||||||
// # glScissor(0,0,ctx->width*2,ctx->height*2);
|
|
||||||
// gl.disable(GL_SCISSOR_TEST)// TODO
|
|
||||||
// #free(text.str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (ctx &Context) draw_text_fast(_x, _y int, text ustring, cfg gx.TextCfg) {
|
fn (ctx mut Context) draw_text_fast(_x, _y int, text ustring, cfg gx.TextCfg) {
|
||||||
ctx._draw_text(_x, _y, text, cfg)
|
ctx._draw_text(_x, _y, text, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO HACK with second text context
|
fn (ctx mut Context) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
|
||||||
// fn (ctx &GG) _draw_text(_x, _y int, text string, cfg gx.TextCfg) {
|
/*
|
||||||
fn (ctx &Context) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
|
|
||||||
/*
|
|
||||||
if utext.s.contains('on_seg') {
|
if utext.s.contains('on_seg') {
|
||||||
println('\nat(0)')
|
println('\nat(0)')
|
||||||
println(utext.runes)
|
println(utext.runes)
|
||||||
@ -282,8 +268,8 @@ fn (ctx &Context) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
mut x := f32(_x)
|
mut x := f32(_x)
|
||||||
mut y := f32(_y)
|
mut y := f32(_y)
|
||||||
// println('scale=$ctx.scale size=$cfg.size')
|
// println('scale=$ctx.scale size=$cfg.size')
|
||||||
if cfg.align == gx.ALIGN_RIGHT {
|
if cfg.align == gx.ALIGN_RIGHT {
|
||||||
width := utext.len * 7
|
width := utext.len * 7
|
||||||
@ -293,12 +279,12 @@ fn (ctx &Context) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
|
|||||||
// println('y=$_y height=$ctx.height')
|
// println('y=$_y height=$ctx.height')
|
||||||
// _y = _y * int(ctx.scale) //+ 26
|
// _y = _y * int(ctx.scale) //+ 26
|
||||||
y = y * int(ctx.scale) + ((cfg.size * ctx.scale) / 2) + 5 * ctx.scale
|
y = y * int(ctx.scale) + ((cfg.size * ctx.scale) / 2) + 5 * ctx.scale
|
||||||
y = f32(ctx.height) - y
|
y = f32(ctx.height) - y
|
||||||
color := cfg.color
|
color := cfg.color
|
||||||
// Activate corresponding render state
|
// Activate corresponding render state
|
||||||
ctx.shader.use()
|
ctx.shader.use()
|
||||||
ctx.shader.set_color('textColor', color)
|
ctx.shader.set_color('textColor', color)
|
||||||
# glActiveTexture(GL_TEXTURE0);
|
C.glActiveTexture(C.GL_TEXTURE0)
|
||||||
gl.bind_vao(ctx.vao)
|
gl.bind_vao(ctx.vao)
|
||||||
// Iterate through all characters
|
// Iterate through all characters
|
||||||
// utext := text.ustring()
|
// utext := text.ustring()
|
||||||
@ -318,65 +304,52 @@ fn (ctx &Context) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
|
|||||||
// TODO O(1) use map
|
// TODO O(1) use map
|
||||||
for j := 0; j < ctx.utf_runes.len; j++ {
|
for j := 0; j < ctx.utf_runes.len; j++ {
|
||||||
rune_j := ctx.utf_runes[j]
|
rune_j := ctx.utf_runes[j]
|
||||||
// if string_eq(ctx.utf_runes[j], rune) {
|
|
||||||
if rune_j==_rune {
|
if rune_j==_rune {
|
||||||
ch = ctx.utf_chars[j]
|
ch = ctx.utf_chars[j]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ch.size.x == 0 {
|
if ch.size.x == 0 && _rune.len > 1{
|
||||||
|
c := _rune[0]
|
||||||
|
println('cant draw rune "$_rune" code=$c, loading')
|
||||||
|
continue
|
||||||
|
ch = ft_load_char(ctx.face, _rune.utf32_code())
|
||||||
|
println('done loading')
|
||||||
|
ctx.utf_runes << _rune
|
||||||
|
ctx.utf_chars << ch
|
||||||
// continue
|
// continue
|
||||||
}
|
}
|
||||||
// mut c := int(text[i])
|
|
||||||
// c = 128
|
|
||||||
// s := 'A'
|
|
||||||
// c := int(s[0])
|
|
||||||
// ch := ctx.chars[c]
|
|
||||||
xpos := x + f32(ch.bearing.x) * 1
|
xpos := x + f32(ch.bearing.x) * 1
|
||||||
ypos := y - f32(ch.size.y - ch.bearing.y) * 1
|
ypos := y - f32(ch.size.y - ch.bearing.y) * 1
|
||||||
w := f32(ch.size.x) * 1
|
w := f32(ch.size.x) * 1
|
||||||
h := f32(ch.size.y) * 1
|
h := f32(ch.size.y) * 1
|
||||||
// Update VBO for each character
|
// Update VBO for each character
|
||||||
# GLfloat vertices[6][4] = {
|
vertices := [
|
||||||
# { xpos, ypos + h, 0.0, 0.0 },
|
xpos, ypos + h, 0.0, 0.0 ,
|
||||||
# { xpos, ypos, 0.0, 1.0 },
|
xpos, ypos, 0.0, 1.0 ,
|
||||||
# { xpos + w, ypos, 1.0, 1.0 },
|
xpos + w, ypos, 1.0, 1.0 ,
|
||||||
# { xpos, ypos + h, 0.0, 0.0 },
|
xpos, ypos + h, 0.0, 0.0 ,
|
||||||
# { xpos + w, ypos, 1.0, 1.0 },
|
xpos + w, ypos, 1.0, 1.0 ,
|
||||||
# { xpos + w, ypos + h, 1.0, 0.0 }
|
xpos + w, ypos + h, 1.0, 0.0
|
||||||
# };
|
]
|
||||||
// t := glfw.get_time()
|
|
||||||
// Render glyph texture over quad
|
// Render glyph texture over quad
|
||||||
// t1 := glfw.get_time()
|
C.glBindTexture(C.GL_TEXTURE_2D, ch.texture_id)
|
||||||
# glBindTexture(GL_TEXTURE_2D, ch.texture_id);
|
|
||||||
// Update content of VBO memory
|
// Update content of VBO memory
|
||||||
gl.bind_buffer(GL_ARRAY_BUFFER, ctx.vbo)
|
gl.bind_buffer(GL_ARRAY_BUFFER, ctx.vbo)
|
||||||
// t2 := glfw.get_time()
|
// glBufferSubData(..)
|
||||||
// # glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
|
C.glBufferData(GL_ARRAY_BUFFER, 96, vertices.data, C.GL_DYNAMIC_DRAW)
|
||||||
# glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
|
|
||||||
// t3 := glfw.get_time()
|
|
||||||
// gl.bind_buffer(GL_ARRAY_BUFFER, uint(0))
|
|
||||||
// t4 := glfw.get_time()
|
|
||||||
// Render quad
|
// Render quad
|
||||||
gl.draw_arrays(GL_TRIANGLES, 0, 6)
|
gl.draw_arrays(GL_TRIANGLES, 0, 6)
|
||||||
// t5 := glfw.get_time()
|
|
||||||
// # if (glfw__get_time() - t > 0.001)
|
|
||||||
// {
|
|
||||||
// # printf("do_text = %f '%s' \n", glfw__get_time() - t, text.str);
|
|
||||||
// # printf("t1=%f, t2=%f, t3=%f, t4=%f, t5=%f\n\n\n", t1-t, t2-t1, t3-t2, t4-t3, t5-t4);
|
|
||||||
// }
|
|
||||||
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
// 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))
|
// 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 >> 6) * 1;
|
x += ch.advance >> u32(6)
|
||||||
}
|
}
|
||||||
gl.bind_vao(u32(0))
|
gl.bind_vao(u32(0))
|
||||||
# glBindTexture(GL_TEXTURE_2D, 0);
|
C.glBindTexture(C.GL_TEXTURE_2D, 0)
|
||||||
// runes.free()
|
|
||||||
// #free(runes.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ctx &Context) draw_text_def(x, y int, text string) {
|
pub fn (ctx mut Context) draw_text_def(x, y int, text string) {
|
||||||
cfg := gx.TextCfg {
|
cfg := gx.TextCfg {
|
||||||
color: gx.Black,
|
color: gx.Black,
|
||||||
size: DEFAULT_FONT_SIZE,
|
size: DEFAULT_FONT_SIZE,
|
||||||
|
@ -19,7 +19,7 @@ struct Context {
|
|||||||
last_name ui.TextBox
|
last_name ui.TextBox
|
||||||
age ui.TextBox
|
age ui.TextBox
|
||||||
users []User
|
users []User
|
||||||
window *ui.Window
|
window &ui.Window
|
||||||
txt_pos int
|
txt_pos int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user